Transaction Hash:
Block:
5701540 at May-30-2018 07:48:23 AM +UTC
Transaction Fee:
0.001910616 ETH
$3.92
Gas Used:
159,218 Gas / 12 Gwei
Emitted Events:
| 63 |
WarToken.Transfer( from=WarToken, to=[Sender] 0x401678df30b5a77ee5d9c6716da6679a77b4c4d6, tokenId=57335 )
|
| 64 |
WarToken.CreateFashion( owner=[Sender] 0x401678df30b5a77ee5d9c6716da6679a77b4c4d6, tokenId=57335, protoId=2, quality=1, pos=4, createType=2 )
|
| 65 |
ActionMining.MiningResolved( index=0, miner=[Sender] 0x401678df30b5a77ee5d9c6716da6679a77b4c4d6, chestCnt=1 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x1A720862...2fa4a7831 | |||||
| 0x401678df...a77b4C4D6 |
0.55388209439328481 Eth
Nonce: 12
|
0.54197147839328481 Eth
Nonce: 13
| 0.011910616 | ||
| 0x75f75B2A...57052937B | 18.18635203408471594 Eth | 18.19135203408471594 Eth | 0.005 | ||
| 0x76a8bDd4...AB5332F44 | 7.586501827324213709 Eth | 7.591501827324213709 Eth | 0.005 | ||
| 0xDA9c03dF...832Eb08b2 | |||||
|
0xEA674fdD...16B898ec8
Miner
| (Ethermine) | 871.042758944422629892 Eth | 871.044669560422629892 Eth | 0.001910616 |
Execution Trace
ETH 0.01
ActionMining.CALL( )
-
WarToken.createFashion( _owner=0x401678df30b5a77ee5D9C6716DA6679a77b4C4D6, _attrs=[2, 1, 4, 0, 0, 0, 62, 0, 0], _createType=2 ) => ( 57335 )
-
DataMining.getRecommender( _target=0x401678df30b5a77ee5D9C6716DA6679a77b4C4D6 ) => ( 0x0000000000000000000000000000000000000000 ) - ETH 0.005
0x76a8bdd40031556fb0c25d7c920ff16ab5332f44.CALL( ) - ETH 0.005
PrizePool.CALL( )
File 1 of 4: ActionMining
File 2 of 4: WarToken
File 3 of 4: DataMining
File 4 of 4: PrizePool
/* ==================================================================== */
/* Copyright (c) 2018 The ether.online Project. All rights reserved.
/*
/* https://ether.online The first RPG game of blockchain
/*
/* authors rickhunter.shen@gmail.com
/* ssesunding@gmail.com
/* ==================================================================== */
pragma solidity ^0.4.20;
/// @title ERC-165 Standard Interface Detection
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
interface ERC165 {
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
/// @title ERC-721 Non-Fungible Token Standard
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
contract ERC721 is ERC165 {
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external;
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external;
function transferFrom(address _from, address _to, uint256 _tokenId) external;
function approve(address _approved, uint256 _tokenId) external;
function setApprovalForAll(address _operator, bool _approved) external;
function getApproved(uint256 _tokenId) external view returns (address);
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}
/// @title ERC-721 Non-Fungible Token Standard
interface ERC721TokenReceiver {
function onERC721Received(address _from, uint256 _tokenId, bytes data) external returns(bytes4);
}
contract AccessAdmin {
bool public isPaused = false;
address public addrAdmin;
event AdminTransferred(address indexed preAdmin, address indexed newAdmin);
function AccessAdmin() public {
addrAdmin = msg.sender;
}
modifier onlyAdmin() {
require(msg.sender == addrAdmin);
_;
}
modifier whenNotPaused() {
require(!isPaused);
_;
}
modifier whenPaused {
require(isPaused);
_;
}
function setAdmin(address _newAdmin) external onlyAdmin {
require(_newAdmin != address(0));
AdminTransferred(addrAdmin, _newAdmin);
addrAdmin = _newAdmin;
}
function doPause() external onlyAdmin whenNotPaused {
isPaused = true;
}
function doUnpause() external onlyAdmin whenPaused {
isPaused = false;
}
}
contract AccessService is AccessAdmin {
address public addrService;
address public addrFinance;
modifier onlyService() {
require(msg.sender == addrService);
_;
}
modifier onlyFinance() {
require(msg.sender == addrFinance);
_;
}
function setService(address _newService) external {
require(msg.sender == addrService || msg.sender == addrAdmin);
require(_newService != address(0));
addrService = _newService;
}
function setFinance(address _newFinance) external {
require(msg.sender == addrFinance || msg.sender == addrAdmin);
require(_newFinance != address(0));
addrFinance = _newFinance;
}
function withdraw(address _target, uint256 _amount)
external
{
require(msg.sender == addrFinance || msg.sender == addrAdmin);
require(_amount > 0);
address receiver = _target == address(0) ? addrFinance : _target;
uint256 balance = this.balance;
if (_amount < balance) {
receiver.transfer(_amount);
} else {
receiver.transfer(this.balance);
}
}
}
interface IDataMining {
function getRecommender(address _target) external view returns(address);
function subFreeMineral(address _target) external returns(bool);
}
interface IDataEquip {
function isEquiped(address _target, uint256 _tokenId) external view returns(bool);
function isEquipedAny2(address _target, uint256 _tokenId1, uint256 _tokenId2) external view returns(bool);
function isEquipedAny3(address _target, uint256 _tokenId1, uint256 _tokenId2, uint256 _tokenId3) external view returns(bool);
}
contract Random {
uint256 _seed;
function _rand() internal returns (uint256) {
_seed = uint256(keccak256(_seed, block.blockhash(block.number - 1), block.coinbase, block.difficulty));
return _seed;
}
function _randBySeed(uint256 _outSeed) internal view returns (uint256) {
return uint256(keccak256(_outSeed, block.blockhash(block.number - 1), block.coinbase, block.difficulty));
}
}
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
contract WarToken is ERC721, AccessAdmin {
/// @dev The equipment info
struct Fashion {
uint16 protoId; // 0 Equipment ID
uint16 quality; // 1 Rarity: 1 Coarse/2 Good/3 Rare/4 Epic/5 Legendary
uint16 pos; // 2 Slots: 1 Weapon/2 Hat/3 Cloth/4 Pant/5 Shoes/9 Pets
uint16 health; // 3 Health
uint16 atkMin; // 4 Min attack
uint16 atkMax; // 5 Max attack
uint16 defence; // 6 Defennse
uint16 crit; // 7 Critical rate
uint16 isPercent; // 8 Attr value type
uint16 attrExt1; // 9 future stat 1
uint16 attrExt2; // 10 future stat 2
uint16 attrExt3; // 11 future stat 3
}
/// @dev All equipments tokenArray (not exceeding 2^32-1)
Fashion[] public fashionArray;
/// @dev Amount of tokens destroyed
uint256 destroyFashionCount;
/// @dev Equipment token ID vs owner address
mapping (uint256 => address) fashionIdToOwner;
/// @dev Equipments owner by the owner (array)
mapping (address => uint256[]) ownerToFashionArray;
/// @dev Equipment token ID search in owner array
mapping (uint256 => uint256) fashionIdToOwnerIndex;
/// @dev The authorized address for each WAR
mapping (uint256 => address) fashionIdToApprovals;
/// @dev The authorized operators for each address
mapping (address => mapping (address => bool)) operatorToApprovals;
/// @dev Trust contract
mapping (address => bool) actionContracts;
function setActionContract(address _actionAddr, bool _useful) external onlyAdmin {
actionContracts[_actionAddr] = _useful;
}
function getActionContract(address _actionAddr) external view onlyAdmin returns(bool) {
return actionContracts[_actionAddr];
}
/// @dev This emits when the approved address for an WAR is changed or reaffirmed.
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
/// @dev This emits when an operator is enabled or disabled for an owner.
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
/// @dev This emits when the equipment ownership changed
event Transfer(address indexed from, address indexed to, uint256 tokenId);
/// @dev This emits when the equipment created
event CreateFashion(address indexed owner, uint256 tokenId, uint16 protoId, uint16 quality, uint16 pos, uint16 createType);
/// @dev This emits when the equipment's attributes changed
event ChangeFashion(address indexed owner, uint256 tokenId, uint16 changeType);
/// @dev This emits when the equipment destroyed
event DeleteFashion(address indexed owner, uint256 tokenId, uint16 deleteType);
function WarToken() public {
addrAdmin = msg.sender;
fashionArray.length += 1;
}
// modifier
/// @dev Check if token ID is valid
modifier isValidToken(uint256 _tokenId) {
require(_tokenId >= 1 && _tokenId <= fashionArray.length);
require(fashionIdToOwner[_tokenId] != address(0));
_;
}
modifier canTransfer(uint256 _tokenId) {
address owner = fashionIdToOwner[_tokenId];
require(msg.sender == owner || msg.sender == fashionIdToApprovals[_tokenId] || operatorToApprovals[owner][msg.sender]);
_;
}
// ERC721
function supportsInterface(bytes4 _interfaceId) external view returns(bool) {
// ERC165 || ERC721 || ERC165^ERC721
return (_interfaceId == 0x01ffc9a7 || _interfaceId == 0x80ac58cd || _interfaceId == 0x8153916a) && (_interfaceId != 0xffffffff);
}
function name() public pure returns(string) {
return "WAR Token";
}
function symbol() public pure returns(string) {
return "WAR";
}
/// @dev Search for token quantity address
/// @param _owner Address that needs to be searched
/// @return Returns token quantity
function balanceOf(address _owner) external view returns(uint256) {
require(_owner != address(0));
return ownerToFashionArray[_owner].length;
}
/// @dev Find the owner of an WAR
/// @param _tokenId The tokenId of WAR
/// @return Give The address of the owner of this WAR
function ownerOf(uint256 _tokenId) external view /*isValidToken(_tokenId)*/ returns (address owner) {
return fashionIdToOwner[_tokenId];
}
/// @dev Transfers the ownership of an WAR from one address to another address
/// @param _from The current owner of the WAR
/// @param _to The new owner
/// @param _tokenId The WAR to transfer
/// @param data Additional data with no specified format, sent in call to `_to`
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data)
external
whenNotPaused
{
_safeTransferFrom(_from, _to, _tokenId, data);
}
/// @dev Transfers the ownership of an WAR from one address to another address
/// @param _from The current owner of the WAR
/// @param _to The new owner
/// @param _tokenId The WAR to transfer
function safeTransferFrom(address _from, address _to, uint256 _tokenId)
external
whenNotPaused
{
_safeTransferFrom(_from, _to, _tokenId, "");
}
/// @dev Transfer ownership of an WAR, '_to' must be a vaild address, or the WAR will lost
/// @param _from The current owner of the WAR
/// @param _to The new owner
/// @param _tokenId The WAR to transfer
function transferFrom(address _from, address _to, uint256 _tokenId)
external
whenNotPaused
isValidToken(_tokenId)
canTransfer(_tokenId)
{
address owner = fashionIdToOwner[_tokenId];
require(owner != address(0));
require(_to != address(0));
require(owner == _from);
_transfer(_from, _to, _tokenId);
}
/// @dev Set or reaffirm the approved address for an WAR
/// @param _approved The new approved WAR controller
/// @param _tokenId The WAR to approve
function approve(address _approved, uint256 _tokenId)
external
whenNotPaused
{
address owner = fashionIdToOwner[_tokenId];
require(owner != address(0));
require(msg.sender == owner || operatorToApprovals[owner][msg.sender]);
fashionIdToApprovals[_tokenId] = _approved;
Approval(owner, _approved, _tokenId);
}
/// @dev Enable or disable approval for a third party ("operator") to manage all your asset.
/// @param _operator Address to add to the set of authorized operators.
/// @param _approved True if the operators is approved, false to revoke approval
function setApprovalForAll(address _operator, bool _approved)
external
whenNotPaused
{
operatorToApprovals[msg.sender][_operator] = _approved;
ApprovalForAll(msg.sender, _operator, _approved);
}
/// @dev Get the approved address for a single WAR
/// @param _tokenId The WAR to find the approved address for
/// @return The approved address for this WAR, or the zero address if there is none
function getApproved(uint256 _tokenId) external view isValidToken(_tokenId) returns (address) {
return fashionIdToApprovals[_tokenId];
}
/// @dev Query if an address is an authorized operator for another address
/// @param _owner The address that owns the WARs
/// @param _operator The address that acts on behalf of the owner
/// @return True if `_operator` is an approved operator for `_owner`, false otherwise
function isApprovedForAll(address _owner, address _operator) external view returns (bool) {
return operatorToApprovals[_owner][_operator];
}
/// @dev Count WARs tracked by this contract
/// @return A count of valid WARs tracked by this contract, where each one of
/// them has an assigned and queryable owner not equal to the zero address
function totalSupply() external view returns (uint256) {
return fashionArray.length - destroyFashionCount - 1;
}
/// @dev Do the real transfer with out any condition checking
/// @param _from The old owner of this WAR(If created: 0x0)
/// @param _to The new owner of this WAR
/// @param _tokenId The tokenId of the WAR
function _transfer(address _from, address _to, uint256 _tokenId) internal {
if (_from != address(0)) {
uint256 indexFrom = fashionIdToOwnerIndex[_tokenId];
uint256[] storage fsArray = ownerToFashionArray[_from];
require(fsArray[indexFrom] == _tokenId);
// If the WAR is not the element of array, change it to with the last
if (indexFrom != fsArray.length - 1) {
uint256 lastTokenId = fsArray[fsArray.length - 1];
fsArray[indexFrom] = lastTokenId;
fashionIdToOwnerIndex[lastTokenId] = indexFrom;
}
fsArray.length -= 1;
if (fashionIdToApprovals[_tokenId] != address(0)) {
delete fashionIdToApprovals[_tokenId];
}
}
// Give the WAR to '_to'
fashionIdToOwner[_tokenId] = _to;
ownerToFashionArray[_to].push(_tokenId);
fashionIdToOwnerIndex[_tokenId] = ownerToFashionArray[_to].length - 1;
Transfer(_from != address(0) ? _from : this, _to, _tokenId);
}
/// @dev Actually perform the safeTransferFrom
function _safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data)
internal
isValidToken(_tokenId)
canTransfer(_tokenId)
{
address owner = fashionIdToOwner[_tokenId];
require(owner != address(0));
require(_to != address(0));
require(owner == _from);
_transfer(_from, _to, _tokenId);
// Do the callback after everything is done to avoid reentrancy attack
uint256 codeSize;
assembly { codeSize := extcodesize(_to) }
if (codeSize == 0) {
return;
}
bytes4 retval = ERC721TokenReceiver(_to).onERC721Received(_from, _tokenId, data);
// bytes4(keccak256("onERC721Received(address,uint256,bytes)")) = 0xf0b9e5ba;
require(retval == 0xf0b9e5ba);
}
//----------------------------------------------------------------------------------------------------------
/// @dev Equipment creation
/// @param _owner Owner of the equipment created
/// @param _attrs Attributes of the equipment created
/// @return Token ID of the equipment created
function createFashion(address _owner, uint16[9] _attrs, uint16 _createType)
external
whenNotPaused
returns(uint256)
{
require(actionContracts[msg.sender]);
require(_owner != address(0));
uint256 newFashionId = fashionArray.length;
require(newFashionId < 4294967296);
fashionArray.length += 1;
Fashion storage fs = fashionArray[newFashionId];
fs.protoId = _attrs[0];
fs.quality = _attrs[1];
fs.pos = _attrs[2];
if (_attrs[3] != 0) {
fs.health = _attrs[3];
}
if (_attrs[4] != 0) {
fs.atkMin = _attrs[4];
fs.atkMax = _attrs[5];
}
if (_attrs[6] != 0) {
fs.defence = _attrs[6];
}
if (_attrs[7] != 0) {
fs.crit = _attrs[7];
}
if (_attrs[8] != 0) {
fs.isPercent = _attrs[8];
}
_transfer(0, _owner, newFashionId);
CreateFashion(_owner, newFashionId, _attrs[0], _attrs[1], _attrs[2], _createType);
return newFashionId;
}
/// @dev One specific attribute of the equipment modified
function _changeAttrByIndex(Fashion storage _fs, uint16 _index, uint16 _val) internal {
if (_index == 3) {
_fs.health = _val;
} else if(_index == 4) {
_fs.atkMin = _val;
} else if(_index == 5) {
_fs.atkMax = _val;
} else if(_index == 6) {
_fs.defence = _val;
} else if(_index == 7) {
_fs.crit = _val;
} else if(_index == 9) {
_fs.attrExt1 = _val;
} else if(_index == 10) {
_fs.attrExt2 = _val;
} else if(_index == 11) {
_fs.attrExt3 = _val;
}
}
/// @dev Equiment attributes modified (max 4 stats modified)
/// @param _tokenId Equipment Token ID
/// @param _idxArray Stats order that must be modified
/// @param _params Stat value that must be modified
/// @param _changeType Modification type such as enhance, socket, etc.
function changeFashionAttr(uint256 _tokenId, uint16[4] _idxArray, uint16[4] _params, uint16 _changeType)
external
whenNotPaused
isValidToken(_tokenId)
{
require(actionContracts[msg.sender]);
Fashion storage fs = fashionArray[_tokenId];
if (_idxArray[0] > 0) {
_changeAttrByIndex(fs, _idxArray[0], _params[0]);
}
if (_idxArray[1] > 0) {
_changeAttrByIndex(fs, _idxArray[1], _params[1]);
}
if (_idxArray[2] > 0) {
_changeAttrByIndex(fs, _idxArray[2], _params[2]);
}
if (_idxArray[3] > 0) {
_changeAttrByIndex(fs, _idxArray[3], _params[3]);
}
ChangeFashion(fashionIdToOwner[_tokenId], _tokenId, _changeType);
}
/// @dev Equipment destruction
/// @param _tokenId Equipment Token ID
/// @param _deleteType Destruction type, such as craft
function destroyFashion(uint256 _tokenId, uint16 _deleteType)
external
whenNotPaused
isValidToken(_tokenId)
{
require(actionContracts[msg.sender]);
address _from = fashionIdToOwner[_tokenId];
uint256 indexFrom = fashionIdToOwnerIndex[_tokenId];
uint256[] storage fsArray = ownerToFashionArray[_from];
require(fsArray[indexFrom] == _tokenId);
if (indexFrom != fsArray.length - 1) {
uint256 lastTokenId = fsArray[fsArray.length - 1];
fsArray[indexFrom] = lastTokenId;
fashionIdToOwnerIndex[lastTokenId] = indexFrom;
}
fsArray.length -= 1;
fashionIdToOwner[_tokenId] = address(0);
delete fashionIdToOwnerIndex[_tokenId];
destroyFashionCount += 1;
Transfer(_from, 0, _tokenId);
DeleteFashion(_from, _tokenId, _deleteType);
}
/// @dev Safe transfer by trust contracts
function safeTransferByContract(uint256 _tokenId, address _to)
external
whenNotPaused
{
require(actionContracts[msg.sender]);
require(_tokenId >= 1 && _tokenId <= fashionArray.length);
address owner = fashionIdToOwner[_tokenId];
require(owner != address(0));
require(_to != address(0));
require(owner != _to);
_transfer(owner, _to, _tokenId);
}
//----------------------------------------------------------------------------------------------------------
/// @dev Get fashion attrs by tokenId
function getFashion(uint256 _tokenId) external view isValidToken(_tokenId) returns (uint16[12] datas) {
Fashion storage fs = fashionArray[_tokenId];
datas[0] = fs.protoId;
datas[1] = fs.quality;
datas[2] = fs.pos;
datas[3] = fs.health;
datas[4] = fs.atkMin;
datas[5] = fs.atkMax;
datas[6] = fs.defence;
datas[7] = fs.crit;
datas[8] = fs.isPercent;
datas[9] = fs.attrExt1;
datas[10] = fs.attrExt2;
datas[11] = fs.attrExt3;
}
/// @dev Get tokenIds and flags by owner
function getOwnFashions(address _owner) external view returns(uint256[] tokens, uint32[] flags) {
require(_owner != address(0));
uint256[] storage fsArray = ownerToFashionArray[_owner];
uint256 length = fsArray.length;
tokens = new uint256[](length);
flags = new uint32[](length);
for (uint256 i = 0; i < length; ++i) {
tokens[i] = fsArray[i];
Fashion storage fs = fashionArray[fsArray[i]];
flags[i] = uint32(uint32(fs.protoId) * 100 + uint32(fs.quality) * 10 + fs.pos);
}
}
/// @dev WAR token info returned based on Token ID transfered (64 at most)
function getFashionsAttrs(uint256[] _tokens) external view returns(uint16[] attrs) {
uint256 length = _tokens.length;
require(length <= 64);
attrs = new uint16[](length * 11);
uint256 tokenId;
uint256 index;
for (uint256 i = 0; i < length; ++i) {
tokenId = _tokens[i];
if (fashionIdToOwner[tokenId] != address(0)) {
index = i * 11;
Fashion storage fs = fashionArray[tokenId];
attrs[index] = fs.health;
attrs[index + 1] = fs.atkMin;
attrs[index + 2] = fs.atkMax;
attrs[index + 3] = fs.defence;
attrs[index + 4] = fs.crit;
attrs[index + 5] = fs.isPercent;
attrs[index + 6] = fs.attrExt1;
attrs[index + 7] = fs.attrExt2;
attrs[index + 8] = fs.attrExt3;
}
}
}
}
contract ActionMining is Random, AccessService {
using SafeMath for uint256;
event MiningOrderCreated(uint256 indexed index, address indexed miner, uint64 chestCnt);
event MiningResolved(uint256 indexed index, address indexed miner, uint64 chestCnt);
struct MiningOrder {
address miner;
uint64 chestCnt;
uint64 tmCreate;
uint64 tmResolve;
}
/// @dev Max fashion suit id
uint16 maxProtoId;
/// @dev If the recommender can get reward
bool isRecommendOpen;
/// @dev prizepool percent
uint256 constant prizePoolPercent = 50;
/// @dev prizepool contact address
address poolContract;
/// @dev WarToken(NFT) contract address
WarToken public tokenContract;
/// @dev DataMining contract address
IDataMining public dataContract;
/// @dev mining order array
MiningOrder[] public ordersArray;
mapping (uint16 => uint256) public protoIdToCount;
function ActionMining(address _nftAddr, uint16 _maxProtoId) public {
addrAdmin = msg.sender;
addrService = msg.sender;
addrFinance = msg.sender;
tokenContract = WarToken(_nftAddr);
maxProtoId = _maxProtoId;
MiningOrder memory order = MiningOrder(0, 0, 1, 1);
ordersArray.push(order);
}
function() external payable {
}
function getOrderCount() external view returns(uint256) {
return ordersArray.length - 1;
}
function setDataMining(address _addr) external onlyAdmin {
require(_addr != address(0));
dataContract = IDataMining(_addr);
}
function setPrizePool(address _addr) external onlyAdmin {
require(_addr != address(0));
poolContract = _addr;
}
function setMaxProtoId(uint16 _maxProtoId) external onlyAdmin {
require(_maxProtoId > 0 && _maxProtoId < 10000);
require(_maxProtoId != maxProtoId);
maxProtoId = _maxProtoId;
}
function setRecommendStatus(bool _isOpen) external onlyAdmin {
require(_isOpen != isRecommendOpen);
isRecommendOpen = _isOpen;
}
function setFashionSuitCount(uint16 _protoId, uint256 _cnt) external onlyAdmin {
require(_protoId > 0 && _protoId <= maxProtoId);
require(_cnt > 0 && _cnt <= 5);
require(protoIdToCount[_protoId] != _cnt);
protoIdToCount[_protoId] = _cnt;
}
function _getFashionParam(uint256 _seed) internal view returns(uint16[9] attrs) {
uint256 curSeed = _seed;
// quality
uint256 rdm = curSeed % 10000;
uint16 qtyParam;
if (rdm < 6900) {
attrs[1] = 1;
qtyParam = 0;
} else if (rdm < 8700) {
attrs[1] = 2;
qtyParam = 1;
} else if (rdm < 9600) {
attrs[1] = 3;
qtyParam = 2;
} else if (rdm < 9900) {
attrs[1] = 4;
qtyParam = 4;
} else {
attrs[1] = 5;
qtyParam = 6;
}
// protoId
curSeed /= 10000;
rdm = ((curSeed % 10000) / (9999 / maxProtoId)) + 1;
attrs[0] = uint16(rdm <= maxProtoId ? rdm : maxProtoId);
// pos
curSeed /= 10000;
uint256 tmpVal = protoIdToCount[attrs[0]];
if (tmpVal == 0) {
tmpVal = 5;
}
rdm = ((curSeed % 10000) / (9999 / tmpVal)) + 1;
uint16 pos = uint16(rdm <= tmpVal ? rdm : tmpVal);
attrs[2] = pos;
rdm = attrs[0] % 3;
curSeed /= 10000;
tmpVal = (curSeed % 10000) % 21 + 90;
if (rdm == 0) {
if (pos == 1) {
uint256 attr = (200 + qtyParam * 200) * tmpVal / 100; // +atk
attrs[4] = uint16(attr * 40 / 100);
attrs[5] = uint16(attr * 160 / 100);
} else if (pos == 2) {
attrs[6] = uint16((40 + qtyParam * 40) * tmpVal / 100); // +def
} else if (pos == 3) {
attrs[3] = uint16((600 + qtyParam * 600) * tmpVal / 100); // +hp
} else if (pos == 4) {
attrs[6] = uint16((60 + qtyParam * 60) * tmpVal / 100); // +def
} else {
attrs[3] = uint16((400 + qtyParam * 400) * tmpVal / 100); // +hp
}
} else if (rdm == 1) {
if (pos == 1) {
uint256 attr2 = (190 + qtyParam * 190) * tmpVal / 100; // +atk
attrs[4] = uint16(attr2 * 50 / 100);
attrs[5] = uint16(attr2 * 150 / 100);
} else if (pos == 2) {
attrs[6] = uint16((42 + qtyParam * 42) * tmpVal / 100); // +def
} else if (pos == 3) {
attrs[3] = uint16((630 + qtyParam * 630) * tmpVal / 100); // +hp
} else if (pos == 4) {
attrs[6] = uint16((63 + qtyParam * 63) * tmpVal / 100); // +def
} else {
attrs[3] = uint16((420 + qtyParam * 420) * tmpVal / 100); // +hp
}
} else {
if (pos == 1) {
uint256 attr3 = (210 + qtyParam * 210) * tmpVal / 100; // +atk
attrs[4] = uint16(attr3 * 30 / 100);
attrs[5] = uint16(attr3 * 170 / 100);
} else if (pos == 2) {
attrs[6] = uint16((38 + qtyParam * 38) * tmpVal / 100); // +def
} else if (pos == 3) {
attrs[3] = uint16((570 + qtyParam * 570) * tmpVal / 100); // +hp
} else if (pos == 4) {
attrs[6] = uint16((57 + qtyParam * 57) * tmpVal / 100); // +def
} else {
attrs[3] = uint16((380 + qtyParam * 380) * tmpVal / 100); // +hp
}
}
attrs[8] = 0;
}
function _addOrder(address _miner, uint64 _chestCnt) internal {
uint64 newOrderId = uint64(ordersArray.length);
ordersArray.length += 1;
MiningOrder storage order = ordersArray[newOrderId];
order.miner = _miner;
order.chestCnt = _chestCnt;
order.tmCreate = uint64(block.timestamp);
MiningOrderCreated(newOrderId, _miner, _chestCnt);
}
function _transferHelper(uint256 ethVal) private {
bool recommenderSended = false;
uint256 fVal;
uint256 pVal;
if (isRecommendOpen) {
address recommender = dataContract.getRecommender(msg.sender);
if (recommender != address(0)) {
uint256 rVal = ethVal.div(10);
fVal = ethVal.sub(rVal).mul(prizePoolPercent).div(100);
addrFinance.transfer(fVal);
recommenderSended = true;
recommender.transfer(rVal);
pVal = ethVal.sub(rVal).sub(fVal);
if (poolContract != address(0) && pVal > 0) {
poolContract.transfer(pVal);
}
}
}
if (!recommenderSended) {
fVal = ethVal.mul(prizePoolPercent).div(100);
pVal = ethVal.sub(fVal);
addrFinance.transfer(fVal);
if (poolContract != address(0) && pVal > 0) {
poolContract.transfer(pVal);
}
}
}
function miningOneFree()
external
whenNotPaused
{
require(dataContract != address(0));
uint256 seed = _rand();
uint16[9] memory attrs = _getFashionParam(seed);
require(dataContract.subFreeMineral(msg.sender));
tokenContract.createFashion(msg.sender, attrs, 3);
MiningResolved(0, msg.sender, 1);
}
function miningOneSelf()
external
payable
whenNotPaused
{
require(msg.value >= 0.01 ether);
uint256 seed = _rand();
uint16[9] memory attrs = _getFashionParam(seed);
tokenContract.createFashion(msg.sender, attrs, 2);
_transferHelper(0.01 ether);
if (msg.value > 0.01 ether) {
msg.sender.transfer(msg.value - 0.01 ether);
}
MiningResolved(0, msg.sender, 1);
}
function miningOne()
external
payable
whenNotPaused
{
require(msg.value >= 0.01 ether);
_addOrder(msg.sender, 1);
_transferHelper(0.01 ether);
if (msg.value > 0.01 ether) {
msg.sender.transfer(msg.value - 0.01 ether);
}
}
function miningThree()
external
payable
whenNotPaused
{
require(msg.value >= 0.03 ether);
_addOrder(msg.sender, 3);
_transferHelper(0.03 ether);
if (msg.value > 0.03 ether) {
msg.sender.transfer(msg.value - 0.03 ether);
}
}
function miningFive()
external
payable
whenNotPaused
{
require(msg.value >= 0.0475 ether);
_addOrder(msg.sender, 5);
_transferHelper(0.0475 ether);
if (msg.value > 0.0475 ether) {
msg.sender.transfer(msg.value - 0.0475 ether);
}
}
function miningTen()
external
payable
whenNotPaused
{
require(msg.value >= 0.09 ether);
_addOrder(msg.sender, 10);
_transferHelper(0.09 ether);
if (msg.value > 0.09 ether) {
msg.sender.transfer(msg.value - 0.09 ether);
}
}
function miningResolve(uint256 _orderIndex, uint256 _seed)
external
onlyService
{
require(_orderIndex > 0 && _orderIndex < ordersArray.length);
MiningOrder storage order = ordersArray[_orderIndex];
require(order.tmResolve == 0);
address miner = order.miner;
require(miner != address(0));
uint64 chestCnt = order.chestCnt;
require(chestCnt >= 1 && chestCnt <= 10);
uint256 rdm = _seed;
uint16[9] memory attrs;
for (uint64 i = 0; i < chestCnt; ++i) {
rdm = _randBySeed(rdm);
attrs = _getFashionParam(rdm);
tokenContract.createFashion(miner, attrs, 2);
}
order.tmResolve = uint64(block.timestamp);
MiningResolved(_orderIndex, miner, chestCnt);
}
}File 2 of 4: WarToken
/* ==================================================================== */
/* Copyright (c) 2018 The ether.online Project. All rights reserved.
/*
/* https://ether.online The first RPG game of blockchain
/* ==================================================================== */
pragma solidity ^0.4.20;
/// @title ERC-165 Standard Interface Detection
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md
interface ERC165 {
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
/// @title ERC-721 Non-Fungible Token Standard
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
contract ERC721 is ERC165 {
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external;
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external;
function transferFrom(address _from, address _to, uint256 _tokenId) external;
function approve(address _approved, uint256 _tokenId) external;
function setApprovalForAll(address _operator, bool _approved) external;
function getApproved(uint256 _tokenId) external view returns (address);
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}
/// @title ERC-721 Non-Fungible Token Standard
interface ERC721TokenReceiver {
function onERC721Received(address _from, uint256 _tokenId, bytes data) external returns(bytes4);
}
contract AccessAdmin {
bool public isPaused = false;
address public addrAdmin;
event AdminTransferred(address indexed preAdmin, address indexed newAdmin);
function AccessAdmin() public {
addrAdmin = msg.sender;
}
modifier onlyAdmin() {
require(msg.sender == addrAdmin);
_;
}
modifier whenNotPaused() {
require(!isPaused);
_;
}
modifier whenPaused {
require(isPaused);
_;
}
function setAdmin(address _newAdmin) external onlyAdmin {
require(_newAdmin != address(0));
AdminTransferred(addrAdmin, _newAdmin);
addrAdmin = _newAdmin;
}
function doPause() external onlyAdmin whenNotPaused {
isPaused = true;
}
function doUnpause() external onlyAdmin whenPaused {
isPaused = false;
}
}
contract WarToken is ERC721, AccessAdmin {
/// @dev The equipment info
struct Fashion {
uint16 protoId; // 0 Equipment ID
uint16 quality; // 1 Rarity: 1 Coarse/2 Good/3 Rare/4 Epic/5 Legendary
uint16 pos; // 2 Slots: 1 Weapon/2 Hat/3 Cloth/4 Pant/5 Shoes/9 Pets
uint16 health; // 3 Health
uint16 atkMin; // 4 Min attack
uint16 atkMax; // 5 Max attack
uint16 defence; // 6 Defennse
uint16 crit; // 7 Critical rate
uint16 isPercent; // 8 Attr value type
uint16 attrExt1; // 9 future stat 1
uint16 attrExt2; // 10 future stat 2
uint16 attrExt3; // 11 future stat 3
}
/// @dev All equipments tokenArray (not exceeding 2^32-1)
Fashion[] public fashionArray;
/// @dev Amount of tokens destroyed
uint256 destroyFashionCount;
/// @dev Equipment token ID vs owner address
mapping (uint256 => address) fashionIdToOwner;
/// @dev Equipments owner by the owner (array)
mapping (address => uint256[]) ownerToFashionArray;
/// @dev Equipment token ID search in owner array
mapping (uint256 => uint256) fashionIdToOwnerIndex;
/// @dev The authorized address for each WAR
mapping (uint256 => address) fashionIdToApprovals;
/// @dev The authorized operators for each address
mapping (address => mapping (address => bool)) operatorToApprovals;
/// @dev Trust contract
mapping (address => bool) actionContracts;
function setActionContract(address _actionAddr, bool _useful) external onlyAdmin {
actionContracts[_actionAddr] = _useful;
}
function getActionContract(address _actionAddr) external view onlyAdmin returns(bool) {
return actionContracts[_actionAddr];
}
/// @dev This emits when the approved address for an WAR is changed or reaffirmed.
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
/// @dev This emits when an operator is enabled or disabled for an owner.
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
/// @dev This emits when the equipment ownership changed
event Transfer(address indexed from, address indexed to, uint256 tokenId);
/// @dev This emits when the equipment created
event CreateFashion(address indexed owner, uint256 tokenId, uint16 protoId, uint16 quality, uint16 pos, uint16 createType);
/// @dev This emits when the equipment's attributes changed
event ChangeFashion(address indexed owner, uint256 tokenId, uint16 changeType);
/// @dev This emits when the equipment destroyed
event DeleteFashion(address indexed owner, uint256 tokenId, uint16 deleteType);
function WarToken() public {
addrAdmin = msg.sender;
fashionArray.length += 1;
}
// modifier
/// @dev Check if token ID is valid
modifier isValidToken(uint256 _tokenId) {
require(_tokenId >= 1 && _tokenId <= fashionArray.length);
require(fashionIdToOwner[_tokenId] != address(0));
_;
}
modifier canTransfer(uint256 _tokenId) {
address owner = fashionIdToOwner[_tokenId];
require(msg.sender == owner || msg.sender == fashionIdToApprovals[_tokenId] || operatorToApprovals[owner][msg.sender]);
_;
}
// ERC721
function supportsInterface(bytes4 _interfaceId) external view returns(bool) {
// ERC165 || ERC721 || ERC165^ERC721
return (_interfaceId == 0x01ffc9a7 || _interfaceId == 0x80ac58cd || _interfaceId == 0x8153916a) && (_interfaceId != 0xffffffff);
}
function name() public pure returns(string) {
return "WAR Token";
}
function symbol() public pure returns(string) {
return "WAR";
}
/// @dev Search for token quantity address
/// @param _owner Address that needs to be searched
/// @return Returns token quantity
function balanceOf(address _owner) external view returns(uint256) {
require(_owner != address(0));
return ownerToFashionArray[_owner].length;
}
/// @dev Find the owner of an WAR
/// @param _tokenId The tokenId of WAR
/// @return Give The address of the owner of this WAR
function ownerOf(uint256 _tokenId) external view /*isValidToken(_tokenId)*/ returns (address owner) {
return fashionIdToOwner[_tokenId];
}
/// @dev Transfers the ownership of an WAR from one address to another address
/// @param _from The current owner of the WAR
/// @param _to The new owner
/// @param _tokenId The WAR to transfer
/// @param data Additional data with no specified format, sent in call to `_to`
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data)
external
whenNotPaused
{
_safeTransferFrom(_from, _to, _tokenId, data);
}
/// @dev Transfers the ownership of an WAR from one address to another address
/// @param _from The current owner of the WAR
/// @param _to The new owner
/// @param _tokenId The WAR to transfer
function safeTransferFrom(address _from, address _to, uint256 _tokenId)
external
whenNotPaused
{
_safeTransferFrom(_from, _to, _tokenId, "");
}
/// @dev Transfer ownership of an WAR, '_to' must be a vaild address, or the WAR will lost
/// @param _from The current owner of the WAR
/// @param _to The new owner
/// @param _tokenId The WAR to transfer
function transferFrom(address _from, address _to, uint256 _tokenId)
external
whenNotPaused
isValidToken(_tokenId)
canTransfer(_tokenId)
{
address owner = fashionIdToOwner[_tokenId];
require(owner != address(0));
require(_to != address(0));
require(owner == _from);
_transfer(_from, _to, _tokenId);
}
/// @dev Set or reaffirm the approved address for an WAR
/// @param _approved The new approved WAR controller
/// @param _tokenId The WAR to approve
function approve(address _approved, uint256 _tokenId)
external
whenNotPaused
{
address owner = fashionIdToOwner[_tokenId];
require(owner != address(0));
require(msg.sender == owner || operatorToApprovals[owner][msg.sender]);
fashionIdToApprovals[_tokenId] = _approved;
Approval(owner, _approved, _tokenId);
}
/// @dev Enable or disable approval for a third party ("operator") to manage all your asset.
/// @param _operator Address to add to the set of authorized operators.
/// @param _approved True if the operators is approved, false to revoke approval
function setApprovalForAll(address _operator, bool _approved)
external
whenNotPaused
{
operatorToApprovals[msg.sender][_operator] = _approved;
ApprovalForAll(msg.sender, _operator, _approved);
}
/// @dev Get the approved address for a single WAR
/// @param _tokenId The WAR to find the approved address for
/// @return The approved address for this WAR, or the zero address if there is none
function getApproved(uint256 _tokenId) external view isValidToken(_tokenId) returns (address) {
return fashionIdToApprovals[_tokenId];
}
/// @dev Query if an address is an authorized operator for another address
/// @param _owner The address that owns the WARs
/// @param _operator The address that acts on behalf of the owner
/// @return True if `_operator` is an approved operator for `_owner`, false otherwise
function isApprovedForAll(address _owner, address _operator) external view returns (bool) {
return operatorToApprovals[_owner][_operator];
}
/// @dev Count WARs tracked by this contract
/// @return A count of valid WARs tracked by this contract, where each one of
/// them has an assigned and queryable owner not equal to the zero address
function totalSupply() external view returns (uint256) {
return fashionArray.length - destroyFashionCount - 1;
}
/// @dev Do the real transfer with out any condition checking
/// @param _from The old owner of this WAR(If created: 0x0)
/// @param _to The new owner of this WAR
/// @param _tokenId The tokenId of the WAR
function _transfer(address _from, address _to, uint256 _tokenId) internal {
if (_from != address(0)) {
uint256 indexFrom = fashionIdToOwnerIndex[_tokenId];
uint256[] storage fsArray = ownerToFashionArray[_from];
require(fsArray[indexFrom] == _tokenId);
// If the WAR is not the element of array, change it to with the last
if (indexFrom != fsArray.length - 1) {
uint256 lastTokenId = fsArray[fsArray.length - 1];
fsArray[indexFrom] = lastTokenId;
fashionIdToOwnerIndex[lastTokenId] = indexFrom;
}
fsArray.length -= 1;
if (fashionIdToApprovals[_tokenId] != address(0)) {
delete fashionIdToApprovals[_tokenId];
}
}
// Give the WAR to '_to'
fashionIdToOwner[_tokenId] = _to;
ownerToFashionArray[_to].push(_tokenId);
fashionIdToOwnerIndex[_tokenId] = ownerToFashionArray[_to].length - 1;
Transfer(_from != address(0) ? _from : this, _to, _tokenId);
}
/// @dev Actually perform the safeTransferFrom
function _safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data)
internal
isValidToken(_tokenId)
canTransfer(_tokenId)
{
address owner = fashionIdToOwner[_tokenId];
require(owner != address(0));
require(_to != address(0));
require(owner == _from);
_transfer(_from, _to, _tokenId);
// Do the callback after everything is done to avoid reentrancy attack
uint256 codeSize;
assembly { codeSize := extcodesize(_to) }
if (codeSize == 0) {
return;
}
bytes4 retval = ERC721TokenReceiver(_to).onERC721Received(_from, _tokenId, data);
// bytes4(keccak256("onERC721Received(address,uint256,bytes)")) = 0xf0b9e5ba;
require(retval == 0xf0b9e5ba);
}
//----------------------------------------------------------------------------------------------------------
/// @dev Equipment creation
/// @param _owner Owner of the equipment created
/// @param _attrs Attributes of the equipment created
/// @return Token ID of the equipment created
function createFashion(address _owner, uint16[9] _attrs, uint16 _createType)
external
whenNotPaused
returns(uint256)
{
require(actionContracts[msg.sender]);
require(_owner != address(0));
uint256 newFashionId = fashionArray.length;
require(newFashionId < 4294967296);
fashionArray.length += 1;
Fashion storage fs = fashionArray[newFashionId];
fs.protoId = _attrs[0];
fs.quality = _attrs[1];
fs.pos = _attrs[2];
if (_attrs[3] != 0) {
fs.health = _attrs[3];
}
if (_attrs[4] != 0) {
fs.atkMin = _attrs[4];
fs.atkMax = _attrs[5];
}
if (_attrs[6] != 0) {
fs.defence = _attrs[6];
}
if (_attrs[7] != 0) {
fs.crit = _attrs[7];
}
if (_attrs[8] != 0) {
fs.isPercent = _attrs[8];
}
_transfer(0, _owner, newFashionId);
CreateFashion(_owner, newFashionId, _attrs[0], _attrs[1], _attrs[2], _createType);
return newFashionId;
}
/// @dev One specific attribute of the equipment modified
function _changeAttrByIndex(Fashion storage _fs, uint16 _index, uint16 _val) internal {
if (_index == 3) {
_fs.health = _val;
} else if(_index == 4) {
_fs.atkMin = _val;
} else if(_index == 5) {
_fs.atkMax = _val;
} else if(_index == 6) {
_fs.defence = _val;
} else if(_index == 7) {
_fs.crit = _val;
} else if(_index == 9) {
_fs.attrExt1 = _val;
} else if(_index == 10) {
_fs.attrExt2 = _val;
} else if(_index == 11) {
_fs.attrExt3 = _val;
}
}
/// @dev Equiment attributes modified (max 4 stats modified)
/// @param _tokenId Equipment Token ID
/// @param _idxArray Stats order that must be modified
/// @param _params Stat value that must be modified
/// @param _changeType Modification type such as enhance, socket, etc.
function changeFashionAttr(uint256 _tokenId, uint16[4] _idxArray, uint16[4] _params, uint16 _changeType)
external
whenNotPaused
isValidToken(_tokenId)
{
require(actionContracts[msg.sender]);
Fashion storage fs = fashionArray[_tokenId];
if (_idxArray[0] > 0) {
_changeAttrByIndex(fs, _idxArray[0], _params[0]);
}
if (_idxArray[1] > 0) {
_changeAttrByIndex(fs, _idxArray[1], _params[1]);
}
if (_idxArray[2] > 0) {
_changeAttrByIndex(fs, _idxArray[2], _params[2]);
}
if (_idxArray[3] > 0) {
_changeAttrByIndex(fs, _idxArray[3], _params[3]);
}
ChangeFashion(fashionIdToOwner[_tokenId], _tokenId, _changeType);
}
/// @dev Equipment destruction
/// @param _tokenId Equipment Token ID
/// @param _deleteType Destruction type, such as craft
function destroyFashion(uint256 _tokenId, uint16 _deleteType)
external
whenNotPaused
isValidToken(_tokenId)
{
require(actionContracts[msg.sender]);
address _from = fashionIdToOwner[_tokenId];
uint256 indexFrom = fashionIdToOwnerIndex[_tokenId];
uint256[] storage fsArray = ownerToFashionArray[_from];
require(fsArray[indexFrom] == _tokenId);
if (indexFrom != fsArray.length - 1) {
uint256 lastTokenId = fsArray[fsArray.length - 1];
fsArray[indexFrom] = lastTokenId;
fashionIdToOwnerIndex[lastTokenId] = indexFrom;
}
fsArray.length -= 1;
fashionIdToOwner[_tokenId] = address(0);
delete fashionIdToOwnerIndex[_tokenId];
destroyFashionCount += 1;
Transfer(_from, 0, _tokenId);
DeleteFashion(_from, _tokenId, _deleteType);
}
/// @dev Safe transfer by trust contracts
function safeTransferByContract(uint256 _tokenId, address _to)
external
whenNotPaused
{
require(actionContracts[msg.sender]);
require(_tokenId >= 1 && _tokenId <= fashionArray.length);
address owner = fashionIdToOwner[_tokenId];
require(owner != address(0));
require(_to != address(0));
require(owner != _to);
_transfer(owner, _to, _tokenId);
}
//----------------------------------------------------------------------------------------------------------
/// @dev Get fashion attrs by tokenId
function getFashion(uint256 _tokenId) external view isValidToken(_tokenId) returns (uint16[12] datas) {
Fashion storage fs = fashionArray[_tokenId];
datas[0] = fs.protoId;
datas[1] = fs.quality;
datas[2] = fs.pos;
datas[3] = fs.health;
datas[4] = fs.atkMin;
datas[5] = fs.atkMax;
datas[6] = fs.defence;
datas[7] = fs.crit;
datas[8] = fs.isPercent;
datas[9] = fs.attrExt1;
datas[10] = fs.attrExt2;
datas[11] = fs.attrExt3;
}
/// @dev Get tokenIds and flags by owner
function getOwnFashions(address _owner) external view returns(uint256[] tokens, uint32[] flags) {
require(_owner != address(0));
uint256[] storage fsArray = ownerToFashionArray[_owner];
uint256 length = fsArray.length;
tokens = new uint256[](length);
flags = new uint32[](length);
for (uint256 i = 0; i < length; ++i) {
tokens[i] = fsArray[i];
Fashion storage fs = fashionArray[fsArray[i]];
flags[i] = uint32(uint32(fs.protoId) * 100 + uint32(fs.quality) * 10 + fs.pos);
}
}
/// @dev WAR token info returned based on Token ID transfered (64 at most)
function getFashionsAttrs(uint256[] _tokens) external view returns(uint16[] attrs) {
uint256 length = _tokens.length;
require(length <= 64);
attrs = new uint16[](length * 11);
uint256 tokenId;
uint256 index;
for (uint256 i = 0; i < length; ++i) {
tokenId = _tokens[i];
if (fashionIdToOwner[tokenId] != address(0)) {
index = i * 11;
Fashion storage fs = fashionArray[tokenId];
attrs[index] = fs.health;
attrs[index + 1] = fs.atkMin;
attrs[index + 2] = fs.atkMax;
attrs[index + 3] = fs.defence;
attrs[index + 4] = fs.crit;
attrs[index + 5] = fs.isPercent;
attrs[index + 6] = fs.attrExt1;
attrs[index + 7] = fs.attrExt2;
attrs[index + 8] = fs.attrExt3;
}
}
}
}File 3 of 4: DataMining
/* ==================================================================== */
/* Copyright (c) 2018 The ether.online Project. All rights reserved.
/*
/* https://ether.online The first RPG game of blockchain
/*
/* authors rickhunter.shen@gmail.com
/* ssesunding@gmail.com
/* ==================================================================== */
pragma solidity ^0.4.20;
contract AccessAdmin {
bool public isPaused = false;
address public addrAdmin;
event AdminTransferred(address indexed preAdmin, address indexed newAdmin);
function AccessAdmin() public {
addrAdmin = msg.sender;
}
modifier onlyAdmin() {
require(msg.sender == addrAdmin);
_;
}
modifier whenNotPaused() {
require(!isPaused);
_;
}
modifier whenPaused {
require(isPaused);
_;
}
function setAdmin(address _newAdmin) external onlyAdmin {
require(_newAdmin != address(0));
AdminTransferred(addrAdmin, _newAdmin);
addrAdmin = _newAdmin;
}
function doPause() external onlyAdmin whenNotPaused {
isPaused = true;
}
function doUnpause() external onlyAdmin whenPaused {
isPaused = false;
}
}
contract AccessService is AccessAdmin {
address public addrService;
address public addrFinance;
modifier onlyService() {
require(msg.sender == addrService);
_;
}
modifier onlyFinance() {
require(msg.sender == addrFinance);
_;
}
function setService(address _newService) external {
require(msg.sender == addrService || msg.sender == addrAdmin);
require(_newService != address(0));
addrService = _newService;
}
function setFinance(address _newFinance) external {
require(msg.sender == addrFinance || msg.sender == addrAdmin);
require(_newFinance != address(0));
addrFinance = _newFinance;
}
function withdraw(address _target, uint256 _amount)
external
{
require(msg.sender == addrFinance || msg.sender == addrAdmin);
require(_amount > 0);
address receiver = _target == address(0) ? addrFinance : _target;
uint256 balance = this.balance;
if (_amount < balance) {
receiver.transfer(_amount);
} else {
receiver.transfer(this.balance);
}
}
}
interface IDataMining {
function getRecommender(address _target) external view returns(address);
function subFreeMineral(address _target) external returns(bool);
}
interface IDataEquip {
function isEquiped(address _target, uint256 _tokenId) external view returns(bool);
function isEquipedAny2(address _target, uint256 _tokenId1, uint256 _tokenId2) external view returns(bool);
function isEquipedAny3(address _target, uint256 _tokenId1, uint256 _tokenId2, uint256 _tokenId3) external view returns(bool);
}
contract DataMining is AccessService, IDataMining {
event RecommenderChange(address indexed _target, address _recommender);
event FreeMineralChange(address indexed _target, uint32 _accCnt);
/// @dev Recommend relationship map
mapping (address => address) recommendRelation;
/// @dev Free mining count map
mapping (address => uint32) freeMineral;
/// @dev Trust contract
mapping (address => bool) actionContracts;
function DataMining() public {
addrAdmin = msg.sender;
addrService = msg.sender;
addrFinance = msg.sender;
}
function setRecommender(address _target, address _recommender)
external
onlyService
{
require(_target != address(0));
recommendRelation[_target] = _recommender;
RecommenderChange(_target, _recommender);
}
function setRecommenderMulti(address[] _targets, address[] _recommenders)
external
onlyService
{
uint256 targetLength = _targets.length;
require(targetLength <= 64);
require(targetLength == _recommenders.length);
address addrZero = address(0);
for (uint256 i = 0; i < targetLength; ++i) {
if (_targets[i] != addrZero) {
recommendRelation[_targets[i]] = _recommenders[i];
RecommenderChange(_targets[i], _recommenders[i]);
}
}
}
function getRecommender(address _target) external view returns(address) {
return recommendRelation[_target];
}
function addFreeMineral(address _target, uint32 _cnt)
external
onlyService
{
require(_target != address(0));
require(_cnt <= 32);
uint32 oldCnt = freeMineral[_target];
freeMineral[_target] = oldCnt + _cnt;
FreeMineralChange(_target, freeMineral[_target]);
}
function addFreeMineralMulti(address[] _targets, uint32[] _cnts)
external
onlyService
{
uint256 targetLength = _targets.length;
require(targetLength <= 64);
require(targetLength == _cnts.length);
address addrZero = address(0);
uint32 oldCnt;
uint32 newCnt;
address addr;
for (uint256 i = 0; i < targetLength; ++i) {
addr = _targets[i];
if (addr != addrZero && _cnts[i] <= 32) {
oldCnt = freeMineral[addr];
newCnt = oldCnt + _cnts[i];
assert(oldCnt < newCnt);
freeMineral[addr] = newCnt;
FreeMineralChange(addr, freeMineral[addr]);
}
}
}
function setActionContract(address _actionAddr, bool _useful) external onlyAdmin {
actionContracts[_actionAddr] = _useful;
}
function getActionContract(address _actionAddr) external view onlyAdmin returns(bool) {
return actionContracts[_actionAddr];
}
function subFreeMineral(address _target) external returns(bool) {
require(actionContracts[msg.sender]);
require(_target != address(0));
uint32 cnts = freeMineral[_target];
assert(cnts > 0);
freeMineral[_target] = cnts - 1;
FreeMineralChange(_target, cnts - 1);
return true;
}
function getFreeMineral(address _target) external view returns(uint32) {
return freeMineral[_target];
}
}File 4 of 4: PrizePool
/* ==================================================================== */
/* Copyright (c) 2018 The ether.online Project. All rights reserved.
/*
/* https://ether.online The first RPG game of blockchain
/*
/* authors rickhunter.shen@gmail.com
/* sesunding@gmail.com
/* ==================================================================== */
pragma solidity ^0.4.20;
contract AccessAdmin {
bool public isPaused = false;
address public addrAdmin;
event AdminTransferred(address indexed preAdmin, address indexed newAdmin);
function AccessAdmin() public {
addrAdmin = msg.sender;
}
modifier onlyAdmin() {
require(msg.sender == addrAdmin);
_;
}
modifier whenNotPaused() {
require(!isPaused);
_;
}
modifier whenPaused {
require(isPaused);
_;
}
function setAdmin(address _newAdmin) external onlyAdmin {
require(_newAdmin != address(0));
AdminTransferred(addrAdmin, _newAdmin);
addrAdmin = _newAdmin;
}
function doPause() external onlyAdmin whenNotPaused {
isPaused = true;
}
function doUnpause() external onlyAdmin whenPaused {
isPaused = false;
}
}
contract AccessService is AccessAdmin {
address public addrService;
address public addrFinance;
modifier onlyService() {
require(msg.sender == addrService);
_;
}
modifier onlyFinance() {
require(msg.sender == addrFinance);
_;
}
function setService(address _newService) external {
require(msg.sender == addrService || msg.sender == addrAdmin);
require(_newService != address(0));
addrService = _newService;
}
function setFinance(address _newFinance) external {
require(msg.sender == addrFinance || msg.sender == addrAdmin);
require(_newFinance != address(0));
addrFinance = _newFinance;
}
function withdraw(address _target, uint256 _amount)
external
{
require(msg.sender == addrFinance || msg.sender == addrAdmin);
require(_amount > 0);
address receiver = _target == address(0) ? addrFinance : _target;
uint256 balance = this.balance;
if (_amount < balance) {
receiver.transfer(_amount);
} else {
receiver.transfer(this.balance);
}
}
}
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Substracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
contract PrizePool is AccessService {
using SafeMath for uint256;
event SendPrizeSuccesss(uint64 flag, uint256 oldBalance, uint256 sendVal);
event PrizeTimeClear(uint256 newVal);
uint64 public nextPrizeTime;
uint256 maxPrizeOneDay = 30;
function PrizePool() public {
addrAdmin = msg.sender;
addrService = msg.sender;
addrFinance = msg.sender;
}
function() external payable {
}
function getBalance() external view returns(uint256) {
return this.balance;
}
function clearNextPrizeTime() external onlyService {
nextPrizeTime = 0;
PrizeTimeClear(0);
}
function setMaxPrizeOneDay(uint256 val) external onlyAdmin {
require(val > 0 && val < 100);
require(val != maxPrizeOneDay);
maxPrizeOneDay = val;
}
// gas 130000 per 10 address
function sendPrize(address[] winners, uint256[] amounts, uint64 _flag)
external
onlyService
whenNotPaused
{
uint64 tmNow = uint64(block.timestamp);
uint256 length = winners.length;
require(length == amounts.length);
require(length <= 64);
uint256 sum = 0;
for (uint32 i = 0; i < length; ++i) {
sum = sum.add(amounts[i]);
}
uint256 balance = this.balance;
require((sum.mul(100).div(balance)) <= maxPrizeOneDay);
address addrZero = address(0);
for (uint32 j = 0; j < length; ++j) {
if (winners[j] != addrZero) {
winners[j].transfer(amounts[j]);
}
}
nextPrizeTime = tmNow + 72000;
SendPrizeSuccesss(_flag, balance, sum);
}
}