pragma solidity ^0.4.16;
contract BasicAccessControl {
address public owner;
// address[] public moderators;
uint16 public totalModerators = 0;
mapping (address => bool) public moderators;
bool public isMaintaining = false;
function BasicAccessControl() public {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
modifier onlyModerators() {
require(msg.sender == owner || moderators[msg.sender] == true);
_;
}
modifier isActive {
require(!isMaintaining);
_;
}
function ChangeOwner(address _newOwner) onlyOwner public {
if (_newOwner != address(0)) {
owner = _newOwner;
}
}
function AddModerator(address _newModerator) onlyOwner public {
if (moderators[_newModerator] == false) {
moderators[_newModerator] = true;
totalModerators += 1;
}
}
function RemoveModerator(address _oldModerator) onlyOwner public {
if (moderators[_oldModerator] == true) {
moderators[_oldModerator] = false;
totalModerators -= 1;
}
}
function UpdateMaintaining(bool _isMaintaining) onlyOwner public {
isMaintaining = _isMaintaining;
}
}
contract EtheremonEnum {
enum ArrayType {
CLASS_TYPE,
STAT_STEP,
STAT_START,
STAT_BASE,
OBJ_SKILL
}
}
interface EtheremonTradeInterface {
function isOnTrading(uint64 _objId) constant external returns(bool);
}
contract EtheremonDataBase is EtheremonEnum {
function getMonsterObj(uint64 _objId) constant public returns(uint64 objId, uint32 classId, address trainer, uint32 exp, uint32 createIndex, uint32 lastClaimIndex, uint createTime);
function getMonsterDexSize(address _trainer) constant public returns(uint);
function getElementInArrayType(ArrayType _type, uint64 _id, uint _index) constant public returns(uint8);
function addMonsterObj(uint32 _classId, address _trainer, string _name) public returns(uint64);
function addElementToArrayType(ArrayType _type, uint64 _id, uint8 _value) public returns(uint);
}
interface EtheremonRankData {
function setPlayer(address _trainer, uint64 _a0, uint64 _a1, uint64 _a2, uint64 _s0, uint64 _s1, uint64 _s2) external returns(uint32 playerId);
}
contract EtheremonRankBattle is BasicAccessControl, EtheremonEnum {
struct MonsterObjAcc {
uint64 monsterId;
uint32 classId;
address trainer;
string name;
uint32 exp;
uint32 createIndex;
uint32 lastClaimIndex;
uint createTime;
}
// linked smart contract
address public dataContract;
address public tradeContract;
address public rankDataContract;
uint32[3] public starterClasses;
uint public maxDexSize = 200;
// modifier
modifier requireDataContract {
require(dataContract != address(0));
_;
}
modifier requireTradeContract {
require(tradeContract != address(0));
_;
}
modifier requireRankDataContract {
require(rankDataContract != address(0));
_;
}
// event
event EventUpdateCastle(address indexed trainer, uint32 playerId);
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
function EtheremonRankBattle(address _dataContract, address _tradeContract, address _rankDataContract) public {
dataContract = _dataContract;
tradeContract = _tradeContract;
rankDataContract = _rankDataContract;
}
function setContract(address _dataContract, address _tradeContract, address _rankDataContract) onlyModerators external {
dataContract = _dataContract;
tradeContract = _tradeContract;
rankDataContract = _rankDataContract;
}
function setStarterClass(uint _index, uint32 _classId) onlyModerators external {
starterClasses[_index] = _classId;
}
function quickSetStarterClasses() onlyModerators external {
starterClasses[0] = 25;
starterClasses[1] = 26;
starterClasses[2] = 27;
}
function setMaxDexSize(uint _value) onlyModerators external {
maxDexSize = _value;
}
// public
// public functions
function getRandom(uint _seed) constant public returns(uint) {
return uint(keccak256(block.timestamp, block.difficulty)) ^ _seed;
}
function getValidClassId(uint64 _objId, address _owner) constant public returns(uint32) {
EtheremonDataBase data = EtheremonDataBase(dataContract);
MonsterObjAcc memory obj;
(obj.monsterId, obj.classId, obj.trainer, obj.exp, obj.createIndex, obj.lastClaimIndex, obj.createTime) = data.getMonsterObj(_objId);
if (obj.trainer != _owner || obj.classId == 21) return 0;
return obj.classId;
}
function hasValidParam(address _trainer, uint64 _a1, uint64 _a2, uint64 _a3, uint64 _s1, uint64 _s2, uint64 _s3) constant public returns(bool) {
if (_a1 == 0 || _a2 == 0 || _a3 == 0)
return false;
if (_a1 == _a2 || _a1 == _a3 || _a1 == _s1 || _a1 == _s2 || _a1 == _s3)
return false;
if (_a2 == _a3 || _a2 == _s1 || _a2 == _s2 || _a2 == _s3)
return false;
if (_a3 == _s1 || _a3 == _s2 || _a3 == _s3)
return false;
if (_s1 > 0 && (_s1 == _s2 || _s1 == _s3))
return false;
if (_s2 > 0 && (_s2 == _s3))
return false;
uint32 classA1 = getValidClassId(_a1, _trainer);
uint32 classA2 = getValidClassId(_a2, _trainer);
uint32 classA3 = getValidClassId(_a3, _trainer);
if (classA1 == 0 || classA2 == 0 || classA3 == 0)
return false;
if (classA1 == classA2 || classA1 == classA3 || classA2 == classA3)
return false;
if (_s1 > 0 && getValidClassId(_s1, _trainer) == 0)
return false;
if (_s2 > 0 && getValidClassId(_s2, _trainer) == 0)
return false;
if (_s3 > 0 && getValidClassId(_s3, _trainer) == 0)
return false;
return true;
}
function setCastle(uint64 _a1, uint64 _a2, uint64 _a3, uint64 _s1, uint64 _s2, uint64 _s3) isActive requireDataContract
requireTradeContract requireRankDataContract external {
if (!hasValidParam(msg.sender, _a1, _a2, _a3, _s1, _s2, _s3))
revert();
EtheremonTradeInterface trade = EtheremonTradeInterface(tradeContract);
if (trade.isOnTrading(_a1) || trade.isOnTrading(_a2) || trade.isOnTrading(_a3) ||
trade.isOnTrading(_s1) || trade.isOnTrading(_s2) || trade.isOnTrading(_s3))
revert();
EtheremonRankData rank = EtheremonRankData(rankDataContract);
uint32 playerId = rank.setPlayer(msg.sender, _a1, _a2, _a3, _s1, _s2, _s3);
EventUpdateCastle(msg.sender, playerId);
}
function catchStarters() isActive requireDataContract external {
EtheremonDataBase data = EtheremonDataBase(dataContract);
// can not keep too many etheremon
if (data.getMonsterDexSize(msg.sender) > maxDexSize)
revert();
uint i = 0;
uint j = 0;
uint seed = 0;
uint64 objId = 0;
uint32 classId = 0;
uint8 value = 0;
for (i = 0; i < starterClasses.length; i+=1) {
classId = starterClasses[i];
seed = getRandom(uint(block.blockhash(block.number - i)));
objId = data.addMonsterObj(classId, msg.sender, "..name me...");
for (j = 0; j < 6; j += 1) {
seed = seed ^ (i + j);
value = uint8(seed % 32) + data.getElementInArrayType(ArrayType.STAT_START, uint64(classId), j);
data.addElementToArrayType(ArrayType.STAT_BASE, objId, value);
}
Transfer(address(0), msg.sender, objId);
}
}
}
{
"compilationTarget": {
"EtheremonRankBattle.sol": "EtheremonRankBattle"
},
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"setMaxDexSize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"dataContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"moderators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxDexSize","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_trainer","type":"address"},{"name":"_a1","type":"uint64"},{"name":"_a2","type":"uint64"},{"name":"_a3","type":"uint64"},{"name":"_s1","type":"uint64"},{"name":"_s2","type":"uint64"},{"name":"_s3","type":"uint64"}],"name":"hasValidParam","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"starterClasses","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_dataContract","type":"address"},{"name":"_tradeContract","type":"address"},{"name":"_rankDataContract","type":"address"}],"name":"setContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_isMaintaining","type":"bool"}],"name":"UpdateMaintaining","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_a1","type":"uint64"},{"name":"_a2","type":"uint64"},{"name":"_a3","type":"uint64"},{"name":"_s1","type":"uint64"},{"name":"_s2","type":"uint64"},{"name":"_s3","type":"uint64"}],"name":"setCastle","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalModerators","outputs":[{"name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_index","type":"uint256"},{"name":"_classId","type":"uint32"}],"name":"setStarterClass","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newModerator","type":"address"}],"name":"AddModerator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_oldModerator","type":"address"}],"name":"RemoveModerator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rankDataContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"catchStarters","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"quickSetStarterClasses","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_seed","type":"uint256"}],"name":"getRandom","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_objId","type":"uint64"},{"name":"_owner","type":"address"}],"name":"getValidClassId","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isMaintaining","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"ChangeOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tradeContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_dataContract","type":"address"},{"name":"_tradeContract","type":"address"},{"name":"_rankDataContract","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"trainer","type":"address"},{"indexed":false,"name":"playerId","type":"uint32"}],"name":"EventUpdateCastle","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"}]