Contract 0xF72459056C3440d846f47E8a24d79E1531104e8e

 
 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x83168d6a08616ad2e691bb4146930bba1454f83bd9eaf097b3e29a3442d9cd2fRun Adventure VR...262157132022-03-22 5:53:50193 days 5 hrs ago0x0474e22fa791c86c91ca66bcafda7dd519b407e1 IN  0xf72459056c3440d846f47e8a24d79e1531104e8e0 MATIC0.0007685760632.000002501
0xbc660264b300bd129fa850b91981555753e1729d0c2c12b4bbfb200ffebf82ecAdd Team259263362022-03-14 8:07:22201 days 3 hrs ago0xd32f25dfa932b8064a81b8254e7997caebc85f97 IN  0xf72459056c3440d846f47e8a24d79e1531104e8e0 MATIC0.0044034 150
0x3bb35d8f63c942b66f14d07738206bde637b751e407a8654d232545d9b532d36Run Adventure259112362022-03-13 22:22:09201 days 12 hrs ago0x027747771ce20e60d24344e2a62a1377960cced0 IN  0xf72459056c3440d846f47e8a24d79e1531104e8e0 MATIC0.00329985 150
0x351ede0bcab0d80496e8def542adc773ef250ed9714525e4af8bbd20ee8f0f580x60806040258262332022-03-11 10:36:57204 days 42 mins agoCyberKongz: Deployer IN  Create: JungleAdventure0 MATIC0.14287573355830.919647538
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
JungleAdventure

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 13 : JungleAdventure.sol
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;

/*
 *     ,_,
 *    (',')
 *    {/"\}
 *    -"-"-
 */

import "IERC20.sol";
import "SafeMath.sol";
import "IERC721.sol";
import "IERC1155.sol";
import "Ownable.sol";
import "JungleLogic.sol";
import "VRFConsumerBase2.sol";
import "KongzExtraData.sol";


interface ILock is IERC721 {
	function lockId(uint256 _id) external;
	function unlockId(uint256 _id) external;
}

interface INana is IERC20 {
	function burn(uint256 _amount) external;
}

contract JungleAdventure is VRFConsumerBaseV2 {
	using SafeMath for uint256;

	struct CharmEffect {
		uint256 charmType;
		uint256 hp;
	}

	struct AdventureData {
		address user;
		uint256 data;
	}

	address constant BURN_ADDRESS = 0x000000000000000000000000000000000000dEaD;
	bytes32 constant public KONGIUM_ID = 0x6b446311b91ce49327a43ee3d0f0361dbfae79e9b9af3f89d0d8420676a1abb0;
	bytes32 constant public LVL_ID = 0xd7fe74ba2795604f471717a6182ac81070ad95ecee0b7d8ebcfbec785af7e796;

	bool setup;
	bool public isPaused;
	INana public nanas;
	ILock public vx;
	IERC1155 public charms;
	IJungleLogic public logic;
	KongzExtraData public extraData;
	bool public useVrf;
	uint256 counter;

	// 10 days 8 hours
	uint256 public seasonDuration = 892800;
	uint256 public season;

	uint256 public nanaFee;
	uint256 public energyFee;
	uint256 public rodCost = 500;
	uint256 public nanaCost = 200;
	uint256[4] public nanaRewardTable;

	mapping(address => mapping(uint256 => uint256)) public teams;
	mapping(address => uint256) public teamCount;
	mapping(address => uint256) public weights;

	mapping(address => mapping(uint256 => CharmEffect)) public charmInUse;

	// add + 1 always
	mapping(uint256 => uint256) public vxXp;
	mapping(uint256 => uint256) public lastFreeRun;
	
	mapping(uint256 => mapping(address => uint256)) public energyCount;
	mapping(uint256 => mapping(address => uint256)) public seasonLastUpdate;
	mapping(uint256 => uint256) public seasonStartTime;
	mapping(uint256 => uint256) public seasonRewardBalance;

	mapping(uint256 => mapping(address => uint256)) public committedKongium;
	mapping(uint256 => uint256) public globalCommittedKongium;
	mapping(address => mapping(uint256 => bool)) public hasCommitted;

	mapping(address => bool) public approvedContract;
	mapping(uint256 => AdventureData) adventureData;

	event StartSeason(uint256 id, uint256 prize);
	event TeamAdded(address owner, uint256 teamId, uint256 teamData);
	event TeamChanged(address owner, uint256 teamId, uint256 teamData);
	event TeamRemoved(address owner, uint256 teamId);
	event ActivateCharm(uint256 teamId, uint256 charm);
	event CommitKongium(uint256 indexed seasonId, uint256 amount, address indexed commiter);
	event UpgradeVX(uint256[] tokenIds, uint256[] newLevels);
	event KongiumBurn(address indexed user, uint256 amount);
	event KongiumMint(address indexed user, uint256 amount);
	event AdventureDone(address indexed user, uint256 indexed teamId, uint256 data, uint256 timestamp);

	constructor(address _nanas, address _vx, address _charms, address _logic, address _extra,address _vrfCoordinator, address _link) public VRFConsumerBaseV2(_vrfCoordinator, _link) {
		nanas = INana(_nanas);
		energyFee = 1e6;
		vx = ILock(_vx);
		charms = IERC1155(_charms);
		logic = IJungleLogic(_logic);
		extraData = KongzExtraData(_extra);
		nanaRewardTable[0] = 5000 ether;
		nanaRewardTable[1] = 10000 ether;
		nanaRewardTable[2] = 15000 ether;
		nanaRewardTable[3] = 20000 ether;
	}

	function init(address _nanas, address _vx, address _charms, address _logic, address _extra,address _vrfCoordinator, address _link, address _newOwner) external {
		require(!setup);
		setup = true;

		nanas = INana(_nanas);
		energyFee = 1e6;
		rodCost = 500;
		nanaCost = 200;
		seasonDuration = 892800;
		vx = ILock(_vx);
		charms = IERC1155(_charms);
		logic = IJungleLogic(_logic);
		extraData = KongzExtraData(_extra);
		nanaRewardTable[0] = 5000 ether;
		nanaRewardTable[1] = 10000 ether;
		nanaRewardTable[2] = 15000 ether;
		nanaRewardTable[3] = 20000 ether;
		_initVRF(_vrfCoordinator, _link);
		_owner = _newOwner;
        emit OwnershipTransferred(address(0), _newOwner);
	}

	function setPause(bool _val) external onlyOwner {
		isPaused = _val;
	}

	function startSeason() external onlyOwner {
		_startSeason();
	}

	function updateSeasonLength(uint256 _length) external onlyOwner {
		seasonDuration = _length;
	}

	function switchVrf(bool _val) external onlyOwner {
		useVrf = _val;
	}

	function updateApprovedContracts(address[] calldata _contracts, bool[] calldata _values) external onlyOwner {
		require(_contracts.length == _values.length, "!length");
		for(uint256 i = 0; i < _contracts.length; i++)
			approvedContract[_contracts[i]] = _values[i];
	}

	function updateLogic(address _logic) external onlyOwner {
		logic = IJungleLogic(_logic);
	}

	function updateExtraData(address _extra) external onlyOwner {
		extraData = KongzExtraData(_extra);
	}

	function updateNanaFee(uint256 _fee) external onlyOwner {
		nanaFee = _fee;
	}

	function updateRodCost(uint256 _cost) external onlyOwner {
		rodCost = _cost;
	}
	
	function updateNanaCost(uint256 _cost) external onlyOwner {
		nanaCost = _cost;
	}

	function updateEnergyFee(uint256 _fee) external onlyOwner {
		energyFee = _fee;
	}

	function burnKongium(address _user, uint256 _amount) external {
		require(approvedContract[msg.sender], "JungleAdventure: Not allowed to burn kongium");
		_spendKongium(_user, _amount);
	}

	function mintKongium(address _user, uint256 _amount) public {
		require(approvedContract[msg.sender], "JungleAdventure: Not allowed to mint kongium");
		_mintKongium(_user, _amount);
	}

	function grantExp(uint256 _tokenId, uint256 _amount) public {
		require(approvedContract[msg.sender], "JungleAdventure: Not allowed to mint kongium");
		vxXp[_tokenId] = vxXp[_tokenId].add(_amount);
	}

	/*=================* User accessed functions *=================*/
	function addTeam(uint256[5] calldata _vx) external {
		uint256 team = 0;
		uint256 count = teamCount[msg.sender];
		uint256 weight = 0;
		for(uint256 i = 0; i < _vx.length; i++) {
			if (_vx[i] != 0) {
				require(vx.ownerOf(_vx[i]) == msg.sender, "!owner");
				weight++;
				vx.lockId(_vx[i]);
			}
			team = (team + _vx[i]) << 32;
		}
		team >>= 32;
		require(team > 0, "KongAdventures: Empty team");
		_syncEnergy(msg.sender);
		weights[msg.sender] += weight;
		teams[msg.sender][count] = team;
		teamCount[msg.sender]++;
		emit TeamAdded(msg.sender, count, team);
	}

	function removeTeam(uint256 _id) external {
		uint256 team = teams[msg.sender][_id];
		require(team != 0, "KongAdventures: Empty team");
		uint256 count = teamCount[msg.sender];
		uint256 weight = 0;

		for (uint256 i = 0 ; i < 5; i ++) {
			uint256 vxId = (team >> (32 * i)) & 0xffffffff;
			if (vxId != 0) {
				weight++;
				vx.unlockId(vxId);
			}
		}
		if (count > 1) {
			teams[msg.sender][_id] = teams[msg.sender][count - 1];
			charmInUse[msg.sender][_id] = charmInUse[msg.sender][count - 1];
		}
		teams[msg.sender][count - 1] = 0;
		delete charmInUse[msg.sender][count - 1];
		_syncEnergy(msg.sender);
		weights[msg.sender] -= weight;
		teamCount[msg.sender]--;
		emit TeamRemoved(msg.sender, _id);
	}

	function editTeam(uint256 _id, uint256[5] calldata _vx) external {
		uint256 team = teams[msg.sender][_id];
		require(team != 0, "KongAdventures: Empty team");
		uint256 currentTeamWeight = _vxInTeam(team);
		uint256 newTeam;
		uint256 weight;
		for (uint256 i = 0 ; i < 5; i++) {
			uint256 vxId = (team >> (32 * (4 - i))) & 0xffffffff;
			uint256 newId = _vx[i];
			if (newId > 0 && newId != vxId) {
				require(vx.ownerOf(newId) == msg.sender, "!owner");
				vx.lockId(newId);
			}
			if (vxId > 0 && newId != vxId)
				vx.unlockId(vxId);
			newTeam = (newTeam + newId) << 32;
			if (newId > 0)
				weight++;		
		}
		newTeam >>= 32;
		require(newTeam != 0, "KongAdventures: Empty team");
		teams[msg.sender][_id] = newTeam;
		_syncEnergy(msg.sender);
		if (weight > currentTeamWeight)
			weights[msg.sender] += weight - currentTeamWeight;
		else if (weight < currentTeamWeight)
			weights[msg.sender] -= currentTeamWeight - weight;
		emit TeamChanged(msg.sender, _id, newTeam);
	}

	function activateCharm(uint256 _teamId, uint256 _charm) external {
		require(_teamId < teamCount[msg.sender], "JungleAdventure: Index does not exist");
		charmInUse[msg.sender][_teamId] = CharmEffect(_charm, 10001);
		charms.safeTransferFrom(msg.sender, BURN_ADDRESS, _charm, 1, "");
		emit ActivateCharm(_teamId, _charm);
	}

	function upgradeVxLvl(uint256[] calldata _vx) external {
		uint256 expReq;
		uint256 kongiumReq;
		uint256[] memory newLevels = new uint256[](_vx.length);
		for (uint256 i = 0 ; i < _vx.length; i++) {
			require(vx.ownerOf(_vx[i]) == msg.sender, "!owner");
			uint256 lvl = extraData.stats(_vx[i], LVL_ID);
			(expReq, kongiumReq) = logic.getReqForLvl(lvl + 1);
			_spendExp(_vx[i], expReq);
			_spendKongium(msg.sender, kongiumReq);
			extraData.incStats(LVL_ID, _vx[i], 1);
			newLevels[i] = lvl + 1;
		}
		emit UpgradeVX(_vx, newLevels);
	}

	function kongium(address _user) external view returns(uint256) {
		return extraData.items(_user, KONGIUM_ID);
	}

	function getLevelsInTeam(uint256 _team) public view returns(uint256[5] memory _levels) {
		for (uint256 i = 0; i < 5; i++) {
			uint256 vxId = (_team >> (32 * i)) & 0xffffffff;
			if (vxId > 0)
				_levels[i] = extraData.stats(vxId, LVL_ID) + 1;
			else
				_levels[i] = 0;
		}
	}

	function getCharmInUse(address _user, uint256 _index) external view returns(uint256) {
		CharmEffect memory charm = charmInUse[_user][_index];
		if (charm.hp > 0)
			return charm.charmType;
		return 0;
	}

	function getKongStats(uint256[] calldata _kongIds) public view returns(uint256[] memory, uint256[] memory, uint256[] memory) {
		uint256[] memory _levels = new uint256[](_kongIds.length);
		uint256[] memory exp = new uint256[](_kongIds.length);
		uint256[] memory lastFreeRuns = new uint256[](_kongIds.length);
        for (uint256 i = 0; i < _kongIds.length; i++) {
                exp[i] = vxXp[_kongIds[i]];
                _levels[i] = extraData.stats(_kongIds[i], LVL_ID) + 1;
				lastFreeRuns[i] = lastFreeRun[_kongIds[i]];
        }
		return (_levels, exp, lastFreeRuns);
    }

	function getExpInTeam(uint256 _team) public view returns(uint256[5] memory exp) {
		for (uint256 i = 0; i < 5; i++) {
			uint256 vxId = (_team >> (32 * i)) & 0xffffffff;
			if (vxId > 0)
				exp[i] = vxXp[vxId];
			else
				exp[i] = 0;
		}
	}

	function pendingEnergy(address _user) external view returns(uint256) {
		uint startTime = seasonStartTime[season];
		uint256 time = min(block.timestamp - startTime, seasonDuration);
		uint256 timerUser = seasonLastUpdate[season][_user];
		return weights[_user].mul(1e6).mul(time.sub(timerUser)).div(86400);
	}

	function runAdventure(uint256 _teamId, bool _energy) external {
		require(!useVrf, "Use VRF");
		require(!isPaused, "!paused");
		uint256 team = teams[msg.sender][_teamId];
		require(team > 0, "JungleAdventure: team not set");

		_syncEnergy(msg.sender);
		uint256 bonusExp;
		if (_energy)
			_spendEnergy(msg.sender, _vxInTeam(team) * energyFee);
		else {
			uint256 fee = _vxInTeam(team).mul(nanaFee);
			nanas.transferFrom(msg.sender, address(this), fee);
			seasonRewardBalance[season] = seasonRewardBalance[season].add(fee.div(2));
			nanas.transfer(owner(), fee.div(10));
			nanas.transfer(BURN_ADDRESS, fee.sub(fee.div(2)).sub(fee.div(10)));
			bonusExp++;
		}
		_consumeCharm(msg.sender, _teamId, _energy);
		(uint256 gameData, 
		 address[2] memory rewardAddress,
		 uint256[2] memory tokenId,
		 uint256[2] memory amounts,
		 uint256[2] memory tokenTypes) = logic.run(_getActiveCharm(msg.sender, _teamId), _generateSeed(0), team, getLevelsInTeam(team));
		uint256 expFlag = _increaseXp(team, (((gameData >> 32) & 0xffffffff) + bonusExp) * (1 + ((gameData >> 224) & 1)));
		for (uint256 i = 0; i < 2; i++) {
			if (tokenTypes[i] == 1155) {
				IERC1155(rewardAddress[i]).safeTransferFrom(address(this), msg.sender, tokenId[i], amounts[i], "");
			}
			else if (tokenTypes[i] == 20) {
				IERC20(rewardAddress[i]).transfer(msg.sender, amounts[i]);
			}
		}
		_mintKongium(msg.sender, gameData & 0xffffffff);
		emit AdventureDone(
			msg.sender,
			team,
			gameData |
			(expFlag << 64) |
			(bonusExp << 69) |
			(_encodeTeam(getLevelsInTeam(team)) << 70) |
			(_getActiveCharm(msg.sender, _teamId) << 95),
			block.timestamp);
	}

	function runAdventureVRF(uint256 _teamId, bool _energy) external returns(uint256) {
		require(useVrf, "Don't use VRF");
		require(!isPaused, "!paused");
		uint256 team = teams[msg.sender][_teamId];
		require(team > 0, "JungleAdventure: team not set");
		_syncEnergy(msg.sender);
		uint256 bonusExp;
		if (_energy)
			_spendEnergy(msg.sender, _vxInTeam(team) * energyFee);
		else {
			uint256 fee = _vxInTeam(team).mul(nanaFee);
			nanas.transferFrom(msg.sender, address(this), fee);
			seasonRewardBalance[season] = seasonRewardBalance[season].add(fee.div(2));
			nanas.transfer(owner(), fee.div(10));
			nanas.transfer(BURN_ADDRESS, fee.sub(fee.div(2)).sub(fee.div(10)));
			bonusExp++;
		}
		uint256 requestId = requestRandomWords();
		_consumeCharm(msg.sender, _teamId, _energy);
		adventureData[requestId] = AdventureData({
			user: msg.sender,
			data: _encodeGameData(bonusExp, _getActiveCharm(msg.sender, _teamId), team, getLevelsInTeam(team))
		});
		return requestId;
	}

	function commitKongium() external {
		require(block.timestamp < seasonDuration + seasonStartTime[season], "Committing is over");
		require(!isPaused, "!paused");

		uint256 amount = extraData.items(msg.sender, KONGIUM_ID);
		committedKongium[season][msg.sender] += amount;
		globalCommittedKongium[season] += amount;
		_spendKongium(msg.sender, amount);
		emit CommitKongium(season, amount, msg.sender);
	}
	
	function claimNana(uint256 _season) external {
		require(_season < season, "future");
		// require(block.timestamp > seasonDuration + seasonStartTime[_season], "Committing is not over");

		uint256 committedCount = committedKongium[_season][msg.sender];
		uint256 globalCount = globalCommittedKongium[_season];
		uint256 amountToGive = seasonRewardBalance[_season].mul(committedCount).div(globalCount);
		committedKongium[_season][msg.sender] = 0;
		globalCommittedKongium[_season] = globalCount.sub(committedCount);
		seasonRewardBalance[_season] = seasonRewardBalance[_season].sub(amountToGive);
		nanas.transfer(msg.sender, amountToGive);
	}

	function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override {
		AdventureData memory userData = adventureData[requestId];
		address user = userData.user;
		uint256 data = userData.data;
		(uint256 gameData,
		 address[2] memory rewardAddress,
		 uint256[2] memory tokenId,
		 uint256[2] memory amounts,
		 uint256[2] memory tokenTypes) = logic.run((data >> 185) & 3, _generateSeed(randomWords[0]), data & (2 ** 160 - 1), _decodeTeamLevels((data >> 160) & 33554431));
		uint256 expFlag = _increaseXp(data & (2 ** 160 - 1), (((gameData >> 32) & 0xffffffff) + (data >> 187)) * (1 + ((gameData >> 224) & 1)));
		for (uint256 i = 0; i < 2; i++) {
			if (tokenTypes[i] == 1155) {
				IERC1155(rewardAddress[i]).safeTransferFrom(address(this), user, tokenId[i], amounts[i], "");
			}
			else if (tokenTypes[i] == 20) {
				IERC20(rewardAddress[i]).transfer(user, amounts[i]);
			}
		}
		_mintKongium(user, gameData & 0xffffffff);
		emit AdventureDone(
			user,
			data & (2 ** 160 - 1),
			gameData |
			(expFlag << 64) |
			((data >> 187) << 69) |
			(((data >> 160) & 33554431) << 70) |
			(((data >> 185) & 3) << 95),
			block.timestamp);
	}

	function _encodeGameData(uint256 _bonusExp, uint256 _charm, uint256 _team, uint256[5] memory _levels) internal pure returns(uint256) {
		uint256 data = _bonusExp << 2;
		data += _charm;
		data <<= 25;
		data += _encodeTeam(_levels);
		data <<= 160;
		data += _team;
		return data;
	}

	function _encodeTeam(uint256[5] memory _levels) internal pure returns(uint256) {
		uint256 teamData;
		for (uint256 i = 0 ; i < _levels.length; i++) {
			teamData = (teamData + _levels[i]) << 5;
		}
		teamData >>= 5;
		return teamData;
	}

	function _decodeTeamLevels(uint256 _levelsData) internal pure returns(uint256[5] memory teamLevels) {
		for (uint256 i = 0 ; i < 5; i++) {
			teamLevels[4 - i] = (_levelsData >> (5 * i)) & 31;
		}
	}

	function _startSeason() internal {
		seasonStartTime[++season] = block.timestamp;
		uint256 seed = _generateSeed(0);
		uint256 prize = nanaRewardTable[seed % 4];
		_fundSeason(prize);
		emit StartSeason(season, prize);
	}

	function _fundSeason(uint256 _amount) internal {
		seasonRewardBalance[season] += _amount;
		nanas.transferFrom(owner(), address(this), _amount);
	}

	function _getActiveCharm(address _user, uint256 _teamId) internal view returns(uint256) {
		CharmEffect memory charm = charmInUse[_user][_teamId];
		if (charm.hp > 0)
			return charm.charmType;
		return 0;
	}

	function _consumeCharm(address _user, uint256 _teamId, bool _energy) internal {
		CharmEffect storage charm = charmInUse[_user][_teamId];
		uint256 hp = charm.hp;
		uint256 cost;
		if (hp > 0) {
			if (_energy)
				cost = rodCost;
			else
				cost = nanaCost;
			charm.hp = hp < cost ? 0 : (hp - cost);
		}
	}

	function _vxInTeam(uint256 _team) internal pure returns(uint256) {
		uint _teamCount = 0;
		for (uint256 i = 0; i < 5; i++) {
			uint256 vxId = (_team >> (32 * i)) & 0xffffffff;
			_teamCount += vxId > 0 ? 1 : 0;
		}
		return _teamCount;
	}

	function _generateSeed(uint256 _seed) internal returns(uint256 rand) {
		if (_seed == 0)
			rand = uint256(keccak256(abi.encodePacked(msg.sender, block.difficulty, block.timestamp, counter++)));
		else
			rand = uint256(keccak256(abi.encodePacked(_seed)));
	}

	function _canClaimFreeExp(uint256 _vx, uint256 _now) internal returns(uint256) {
		uint256 lastUpdate = lastFreeRun[_vx];
		if (lastUpdate == 0) {
			lastFreeRun[_vx] = _now;
			return 1;
		}
		else if (_now.sub(lastUpdate) > 86400) {
			lastFreeRun[_vx] += 86400 * (_now.sub(lastUpdate).div(86400));
			return 1;
		}
		return 0;
	}

	function _increaseXp(uint256 _team, uint256 _value) internal returns(uint256 expFlag) {
		uint256 _now = block.timestamp;
		for (uint256 i = 0; i < 5; i++) {
			uint256 vxId = (_team >> (32 * i)) & 0xffffffff;
			if (vxId > 0 ) {
				uint freeExp = _canClaimFreeExp(vxId, _now);
				if (freeExp > 0)
					expFlag |= 1 << i;
				vxXp[vxId] += _value + freeExp;
			}
		}
	}

	function _spendEnergy(address _user, uint256 _amount) internal {
		energyCount[season][_user] = energyCount[season][_user].sub(_amount, "!energy");
	}

	function _spendKongium(address _user, uint256 _amount) internal {
		extraData.decItem(KONGIUM_ID, _user, _amount);
	}

	function _mintKongium(address _user, uint256 _amount) internal {
		extraData.incItem(KONGIUM_ID, _user, _amount);
	}

	function _spendExp(uint256 _vx, uint256 _amount) internal {
		vxXp[_vx] = vxXp[_vx].sub(_amount, "!exp");
	}

	function _checkSeason() internal {
		if (block.timestamp > seasonStartTime[season] + seasonDuration)
			_startSeason();
	}

	function _syncEnergy(address _user) internal {
		require(season > 0, "Game not started");
		if (!isPaused)
			_checkSeason();
		uint startTime = seasonStartTime[season];
		uint256 time = min(block.timestamp - startTime, seasonDuration);
		uint256 timerUser = seasonLastUpdate[season][_user];
		// weight * (time - timerUSer) / 86400
		if (time > timerUser)
			energyCount[season][_user] += weights[_user].mul(1e6).mul(time.sub(timerUser)).div(86400);
		seasonLastUpdate[season][_user] = time;
	}

	function min(uint256 a, uint256 b) internal pure returns (uint256) {
		return a < b ? a : b;
	}

	function onERC1155Received(address _operator, address _from, uint256 _id, uint256 _value, bytes calldata _data) external returns(bytes4) {
		return JungleAdventure.onERC1155Received.selector;
	}
}

File 2 of 13 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 3 of 13 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

File 4 of 13 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.2;

import "IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
      * @dev Safely transfers `tokenId` token from `from` to `to`.
      *
      * Requirements:
      *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
      * - `tokenId` token must exist and be owned by `from`.
      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
      *
      * Emits a {Transfer} event.
      */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}

File 5 of 13 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 6 of 13 : IERC1155.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.2;

import "IERC165.sol";

/**
 * @dev Required interface of an ERC1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the amount of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
}

File 7 of 13 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import "Context.sol";
/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
contract Ownable is Context {
    address internal _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(_owner == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

File 8 of 13 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

File 9 of 13 : JungleLogic.sol
pragma solidity ^0.6.12;

/*
 *     ,_,
 *    (',')
 *    {/"\}
 *    -"-"-
 */

import "IERC20.sol";
import "SafeMath.sol";
import "IERC721.sol";
import "IERC1155.sol";
import "Ownable.sol";

interface IJungleLogic {
	function run(uint256 _charm, uint256 _seed, uint256 _team, uint256[5] calldata _levels )
		external
		view
		returns(uint256 gameData, address[2] memory rewardAddress, uint256[2] memory tokenId, uint256[2] memory amounts, uint256[2] memory tokenTypes);
	function getReqForLvl(uint256 _currentLevel) external view returns(uint256 exp, uint256 kongium);
}

contract JungleLogic is IJungleLogic, Ownable {

	// struct GameEvent {
	// 	uint256 eventType; // 2 bits
	// 	uint256 charmRequirement; // 2 bits
	// 	uint256 teamSizeRequirement; // 3 bits
	// 	uint256 singleLevelRequirement; // 5 bits
	// 	uint256 totalLevelRequirement; // 7 bits
	// 	uint256 tokenType; // 11 bits
	// 	uint256 chance; // 17 bits
	// 	address tokenReward; // 160 bits
	// 	uint256 reward; // 128 bits
	// 	uint256 amount; // 128 bits
	// }

	struct GameEvent {
		uint256 l1;
		uint256 l2;
	}

	uint256 constant MAX_CHANCE = 100000;
	uint256 public eventCounter;
	uint256 public enabledEventCounter;
	uint256 public maxChanceCounter;
	mapping(uint256 => GameEvent) public gameEvents;
	mapping(uint256 => uint256) public gameEventQueue;

	uint256 public charmEventCounter;
	uint256 public enabledCharmEventCounter;
	uint256 public charmMaxChanceCounter;
	mapping(uint256 => GameEvent) public charmGameEvents;
	mapping(uint256 => uint256) public charmGameEventQueue;

	function addEvent(
		uint256 _chance,
		uint256 _eventType,
		uint256 _tokenType,
		address _token,
		uint256 _reward,
		uint256  _amount,
		uint256 _singleLevel,
		uint256 _totalLevel,
		uint256 _teamSize,
		uint256 _charm) external onlyOwner {
		require(_chance <= MAX_CHANCE);
		uint256 l1 = _eventType << 2;
		l1 = (l1 + _charm) << 3;
		l1 = (l1 + _teamSize) << 5;
		l1 = (l1 + _singleLevel) << 7;
		l1 = (l1 + _totalLevel) << 11;
		l1 = (l1 + _tokenType) << 17;
		l1 = (l1 + _chance) << 160;
		l1 = l1 + uint256(uint160(_token));
		uint l2 = (_reward << 128) + _amount;
		gameEvents[eventCounter++] = GameEvent(l1, l2);
	}

	function enableEvent(uint256 _eventId) external onlyOwner {
		require(_eventId < eventCounter, "Outside of range");
		GameEvent memory _event = gameEvents[_eventId];
		require(maxChanceCounter + _chance(_event.l1) <= MAX_CHANCE, "chance");
		gameEventQueue[enabledEventCounter++] = _eventId;
		maxChanceCounter += _chance(_event.l1);
	}

	function disableEvent(uint256 _index) external onlyOwner {
		require(_index < enabledEventCounter, "Outside of range");
		uint256 eventId = gameEventQueue[_index];
		GameEvent memory _event = gameEvents[eventId];
		gameEventQueue[_index] = gameEventQueue[enabledEventCounter - 1];
		delete gameEventQueue[enabledEventCounter - 1];
		enabledEventCounter--;
		maxChanceCounter -= _chance(_event.l1);
	}

	function charmAddEvent(
		uint256 _chance,
		uint256 _eventType,
		uint256 _tokenType,
		address _token,
		uint256 _reward,
		uint256  _amount,
		uint256 _singleLevel,
		uint256 _totalLevel,
		uint256 _teamSize,
		uint256 _charm) external onlyOwner {
		require(_chance <= MAX_CHANCE);
		require(_charm > 0, "!charm");
		uint256 l1 = _eventType << 2;
		l1 = (l1 + _charm) << 3;
		l1 = (l1 + _teamSize) << 5;
		l1 = (l1 + _singleLevel) << 7;
		l1 = (l1 + _totalLevel) << 11;
		l1 = (l1 + _tokenType) << 17;
		l1 = (l1 + _chance) << 160;
		l1 = l1 + uint256(uint160(_token));
		uint l2 = (_reward << 128) + _amount;
		charmGameEvents[charmEventCounter++] = GameEvent(l1, l2);
	}

	function charmDisableEvent(uint256 _index) external onlyOwner {
		require(_index < enabledCharmEventCounter, "Outside of range");
		uint256 charmEventId = charmGameEventQueue[_index];
		GameEvent memory _event = charmGameEvents[charmEventId];
		gameEventQueue[_index] = charmGameEventQueue[enabledCharmEventCounter - 1];
		delete charmGameEventQueue[enabledCharmEventCounter - 1];
		enabledCharmEventCounter--;
		charmMaxChanceCounter -= _chance(_event.l1);
	}

	function charmEnableEvent(uint256 _eventId) external onlyOwner {
		require(_eventId < charmEventCounter, "Outside of range");
		GameEvent storage _event = charmGameEvents[_eventId];
		require(charmMaxChanceCounter + _chance(_event.l1) <= MAX_CHANCE);
		charmGameEventQueue[enabledCharmEventCounter++] = _eventId;
		charmMaxChanceCounter += _chance(_event.l1);
	}

	function _getRange(uint256 _level) internal pure returns(uint256 min, uint256 max) {
		if (_level == 1) {
			min = 1;
			max = 5;
		}
		else if (_level == 2) {
			min = 1;
			max = 6;
		}
		else if (_level == 3) {
			min = 1;
			max = 7;
		}
		else if (_level == 4) {
			min = 1;
			max = 8;
		}
		else if (_level == 5) {
			min = 1;
			max = 9;
		}
		else if (_level == 6) {
			min = 1;
			max = 10;
		}
		else if (_level == 7) {
			min = 2;
			max = 10;
		}
		else if (_level == 8) {
			min = 3;
			max = 10;
		}
		else if (_level == 9) {
			min = 4;
			max = 10;
		}
		else if (_level == 10) {
			min = 5;
			max = 10;
		}
		else if (_level == 11) {
			min = 5;
			max = 11;
		}
		else if (_level == 12) {
			min = 5;
			max = 12;
		}
		else if (_level == 13) {
			min = 5;
			max = 13;
		}
		else if (_level == 14) {
			min = 5;
			max = 14;
		}
		else if (_level == 15) {
			min = 5;
			max = 15;
		}
		else if (_level == 16) {
			min = 6;
			max = 15;
		}
		else if (_level == 17) {
			min = 7;
			max = 15;
		}
		else if (_level == 18) {
			min = 8;
			max = 15;
		}
		else if (_level == 19) {
			min = 9;
			max = 15;
		}
		else if (_level == 20) {
			min = 10;
			max = 15;
		}	
	}

	function _rollDoubleKongium(uint256 _seed, uint256 _charm) internal pure returns(bool) {
		uint256 rand = _seed % 100;
		if (_charm == 1 && rand < 20)
			return true;
		else if (_charm == 2 && rand < 40)
			return true;
		else if (_charm == 3 && rand < 100)
			return true;
		return false;
	}

	function _rollDoubleExp(uint256 _seed, uint256 _charm) internal pure returns(uint256) {
		uint256 rand = _seed % 100;
		if (_charm == 1 && rand < 10)
			return 2;
		else if (_charm == 2 && rand < 20)
			return 2;
		else if (_charm == 3 && rand < 50)
			return 2;
		return 1;
	}

	function _rollRandomEvent(uint256 _seed, uint256 _team, uint256[5] calldata _levels, uint256 _charm) internal view returns(uint256, uint256) {
		_seed = _seed % MAX_CHANCE;
		uint256 len = enabledEventCounter;
		uint256 counter;
		uint256 eventData;

		for (uint256 i = 0; i < len; i++) {
			uint256 eventId = gameEventQueue[i];
			uint256 l1 = gameEvents[eventId].l1;
			counter += _chance(l1);
			if (_seed < counter) {
				eventData = ((eventId + 1) << 4) + (_eventType(l1) << 2);
				if (_totalLevel(l1) <= _sumOfLevels(_levels) &&
					_singleLevel(l1) <= _maxLevel(_levels) &&
					_teamSize(l1)<= _vxInTeam(_team) &&
					_charmRequirement(l1)<= _charm)
					return (eventId + 1, eventData + 2);
				else
					return (0, eventData);
			}
		}
		return (0, 0);
	}

	function _rollRandomCharmEvent(uint256 _seed, uint256 _team, uint256[5] calldata _levels, uint256 _charm) internal view returns(uint256, uint256) {
		_seed= _seed % MAX_CHANCE;
		uint256 len = enabledCharmEventCounter;
		uint256 counter;
		uint256 eventData;
		for (uint256 i = 0; i < len; i++) {
			uint256 eventId = charmGameEventQueue[i];
			uint256 l1 = charmGameEvents[eventId].l1;
			counter += _chance(l1);
			if (_seed < counter) {
				eventData = ((eventId + 1) << 4) + (_eventType(l1) << 2);
				if (_totalLevel(l1) <= _sumOfLevels(_levels) &&
					_singleLevel(l1) <= _maxLevel(_levels) &&
					_teamSize(l1)<= _vxInTeam(_team) &&
					_charmRequirement(l1)<= _charm)
					return (eventId + 1, eventData + 2);
				else
					return (0, eventData);
			}
		}
		return (0, 0);
	}

	// starting from left
	// gameData: 1-30 -> kongium earned per vx | 31 : double kongium | 32 : double exp
	//           33-40 : charm event id - 1 (0 is no event) 41-42: event type |  43: if eligible | 44: if succeeded (applicable for event type 3))
	//           45-76: event ID data (exp/kongium/exp+kongium)
	// 			 77-88: repeat with bit 84 for success of type 3
	// 			 89-120 : event Id data
	// 
	// starting from right
	// 			1-32 : kongium earned | 33-64: bonusExp
	function run(uint256 _charm, uint256 _seed, uint256 _team, uint256[5] calldata _levels)
		external
		view
		override
		returns(uint256 gameData, address[2] memory rewardAddress, uint256[2] memory tokenId, uint256[2] memory amounts, uint256[2] memory tokenTypes) {
		uint256 counter;
		{
			uint256 min;
			uint256 max;
			for (uint256 i = 0; i < _levels.length; i++) {
				if (_levels[i] > 0) {
					(min, max) = _getRange(_levels[i]);
					counter += min + (_seed % (max + 1 - min));
					gameData = gameData + (min + _seed % (max + 1 - min));
					_seed = generateSeed(_seed);
				}
				gameData <<= 6;
			}
		}
		gameData >>= 5;
		_seed = generateSeed(_seed);
		if (_rollDoubleKongium(_seed, _charm)) {
			gameData++;
			counter *= 2;
		}
		gameData <<= 1;
		_seed = generateSeed(_seed);
		if (_rollDoubleExp(_seed, _charm) == 2)
			gameData++;
		_seed = generateSeed(_seed);
		{
			uint256 l1;
			uint256 l2;
			gameData <<= 12;
			if (_charm > 0) {
				(l1, l2) = _rollRandomCharmEvent(_seed, _team, _levels, _charm);
				gameData = (gameData + l2) << 32;
				if (l1 > 0) {
					GameEvent memory _event = charmGameEvents[l1 - 1];
					l1 = _event.l1;
					l2 = _event.l2;
					// extra kongium
					if (_eventType(l1) == 0) {
						gameData += _reward(l2);
						counter += _reward(l2);
					}
					// extra exp
					else if (_eventType(l1) == 1) {
						gameData += _reward(l2);
						counter += _reward(l2) << 32;
					}
					// extra exp and kongium
					else if (_eventType(l1) == 2) {
						gameData += ((_reward(l2) & (2 ** 64 - 1)) << 16) + ((_reward(l2) >> 64));
						counter += _reward(l2) & (2 ** 64 - 1);
						counter += (_reward(l2) >> 64) << 32;
					}
					// nft
					else if (_eventType(l1) == 3) {
						if (_tokenType(l1) == 1155) {
							if (IERC1155(_token(l1)).balanceOf(msg.sender, _reward(l2)) > _amount(l2)) {
								gameData |= (1 << 32);
								rewardAddress[0] = _token(l1);
								tokenId[0] = _reward(l2);
								amounts[0] = _amount(l2);
								tokenTypes[0] = 1155;
							}
							else
								counter += 500;
						}
						else if (_tokenType(l1) == 20) {
							if (IERC20(_token(l1)).balanceOf(msg.sender) > _amount(l2)) {
								gameData |= (1 << 32);
								rewardAddress[0] = _token(l1);
								amounts[0] = _amount(l2);
								tokenTypes[0] = 20;
							}
							else
								counter += 500;
						}
					}
				}
			}
			else
				gameData <<= 32;
			_seed = generateSeed(_seed);
			gameData <<= 12;
			(l1, l2) = _rollRandomEvent(_seed, _team, _levels, _charm);
			gameData = (gameData + l2) << 32;
			if (l1 > 0) {
				GameEvent memory _event = gameEvents[l1 - 1];
				l1 = _event.l1;
				l2 = _event.l2;
				// extra kongium
				if (_eventType(l1) == 0) {
					gameData += _reward(l2);
					counter += _reward(l2);
				}
				// extra exp
				else if (_eventType(l1) == 1) {
					gameData += _reward(l2);
					counter += _reward(l2) << 32;
				}
				// extra exp and kongium
				else if (_eventType(l1) == 2) {
					gameData += ((_reward(l2) & (2 ** 64 - 1)) << 16) + ((_reward(l2) >> 64));
					counter += _reward(l2) & (2 ** 64 - 1);
					counter += (_reward(l2) >> 64) << 32;
				}
				// nft
				else if (_eventType(l1) == 3) {
					if (_tokenType(l1) == 1155) {
						if (IERC1155(_token(l1)).balanceOf(msg.sender, _reward(l2)) > _amount(l2)) {
							gameData += 1 << 32;
							rewardAddress[1] = _token(l1);
							tokenId[1] = _reward(l2);
							amounts[1] = _amount(l2);
							tokenTypes[1] = 1155;
						}
						else
							counter += 500;
					}
					else if (_tokenType(l1) == 20) {
						if (IERC20(_token(l1)).balanceOf(msg.sender) > _amount(l2)) {
							gameData += 1 << 32;
							rewardAddress[1] = _token(l1);
							amounts[1] = _amount(l2);
							tokenTypes[1] = 20;
						}
						else
							counter += 500;
					}
				}
			}
			gameData <<= 136;
			gameData += counter;
		}
	}

	function _vxInTeam(uint256 _team) internal pure returns(uint256) {
		uint _teamCount = 0;
		for (uint256 i = 0; i < 5; i++) {
			uint256 vxId = (_team >> (32 * i)) & 0xffffffff;
			_teamCount += vxId > 0 ? 1 : 0;
		}
		return _teamCount;
	}

	function _sumOfLevels(uint256[5] calldata _levels) internal pure returns(uint256 sum) {
		for(uint256 i = 0; i < 5; i++)
			sum += _levels[i];
	}

	function _maxLevel(uint256[5] calldata _levels) internal pure returns(uint256 max) {
		for(uint256 i = 0; i < 5; i++)
			if (_levels[i] > max)
				max = _levels[i];
	}

	function getReqForLvl(uint256 _currentLevel) external view override returns(uint256 exp, uint256 kongium) {
		if (_currentLevel == 1) {
			exp = 10;
			kongium = 10;
		}
		else if (_currentLevel == 2) {
			exp = 20;
			kongium = 40;
		}
		else if (_currentLevel == 3) {
			exp = 40;
			kongium = 60;
		}
		else if (_currentLevel == 4) {
			exp = 60;
			kongium = 100;
		}
		else if (_currentLevel == 5) {
			exp = 80;
			kongium = 150;
		}
		else if (_currentLevel == 6) {
			exp = 100;
			kongium = 200;
		}
		else if (_currentLevel == 7) {
			exp = 125;
			kongium = 250;
		}
		else if (_currentLevel == 8) {
			exp = 150;
			kongium = 400;
		}
		else if (_currentLevel == 9) {
			exp = 175;
			kongium = 500;
		}
		else if (_currentLevel == 10) {
			exp = 200;
			kongium = 600;
		}
		else if (_currentLevel == 11) {
			exp = 225;
			kongium = 700;
		}
		else if (_currentLevel == 12) {
			exp = 250;
			kongium = 800;
		}
		else if (_currentLevel == 13) {
			exp = 275;
			kongium = 900;
		}
		else if (_currentLevel == 14) {
			exp = 300;
			kongium = 1000;
		}
		else if (_currentLevel == 15) {
			exp = 325;
			kongium = 1200;
		}
		else if (_currentLevel == 16) {
			exp = 350;
			kongium = 1400;
		}
		else if (_currentLevel == 17) {
			exp = 400;
			kongium = 1600;
		}
		else if (_currentLevel == 18) {
			exp = 450;
			kongium = 1800;
		}
		else if (_currentLevel == 19) {
			exp = 500;
			kongium = 2000;
		}
		else{
			exp = uint256(-1);
			kongium = uint256(-1);
		}
	}

	function generateSeed(uint256 _seed) internal view returns(uint256 rand) {
		rand = uint256(keccak256(abi.encodePacked(_seed)));
	}

	function _eventType(uint256 _blob) internal pure returns(uint256) {
		return _blob >> 205;
	}

	function _charmRequirement(uint256 _blob) internal pure returns(uint256) {
		return (_blob >> 203) & 3; // 0b11
	}

	function _teamSize(uint256 _blob) internal pure returns(uint256) {
		return (_blob >> 200) & 7; // 0b111
	}

	function _singleLevel(uint256 _blob) internal pure returns(uint256) {
		return (_blob >> 195) & 31; // 0b11111
	}

	function _totalLevel(uint256 _blob) internal pure returns(uint256) {
		return (_blob >> 188) & 127; // 0b1111111
	}

	function _tokenType(uint256 _blob) internal pure returns(uint256) {
		return (_blob >> 177) & 2047; // 0b11111111111
	}

	function _chance(uint256 _blob) internal pure returns(uint256) {
		return (_blob >> 160) & 131071; // 0b11111111111111111
	}

	function _token(uint256 _blob) internal pure returns(address) {
		return address(uint160(_blob & 1461501637330902918203684832716283019655932542975));
	}

	function _reward(uint256 _blob) internal pure returns(uint256) {
		return _blob >> 128;
	}

	function _amount(uint256 _blob) internal pure returns(uint256) {
		return _blob & 0xffffffffffffffffffffffffffffffff;
	}
}

File 10 of 13 : VRFConsumerBase2.sol
pragma solidity ^0.6.12;

import "IVRFCoordinator2.sol";
import "ILink.sol";
import "Ownable.sol";

abstract contract VRFConsumerBaseV2 is Ownable {

	struct RequestConfig {
		uint64 subId;
		uint32 callbackGasLimit;
		uint16 requestConfirmations;
		uint32 numWords;
		bytes32 keyHash;
	}

	RequestConfig public config;
	VRFCoordinatorV2Interface private COORDINATOR;
	LinkTokenInterface private LINK;


	/**
	* @param _vrfCoordinator address of VRFCoordinator contract
	*/
	// poly coord: 0xAE975071Be8F8eE67addBC1A82488F1C24858067
	// poly link:  0xb0897686c545045afc77cf20ec7a532e3120e0f1
	constructor(address _vrfCoordinator, address _link) public {
		COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator);
		LINK = LinkTokenInterface(_link);
		
		config = RequestConfig({
			subId: 0,
			callbackGasLimit: 1000000,
			requestConfirmations: 3,
			numWords: 1,
			keyHash: 0x6e099d640cde6de9d40ac749b4b594126b0169747122711109c9985d47751f93
		});
	}

	function _initVRF(address _vrfCoordinator, address _link) internal {
		COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator);
		LINK = LinkTokenInterface(_link);
		
		config = RequestConfig({
			subId: 0,
			callbackGasLimit: 1000000,
			requestConfirmations: 3,
			numWords: 1,
			keyHash: 0x6e099d640cde6de9d40ac749b4b594126b0169747122711109c9985d47751f93
		});
	}

	/**
	* @notice fulfillRandomness handles the VRF response. Your contract must
	* @notice implement it. See "SECURITY CONSIDERATIONS" above for important
	* @notice principles to keep in mind when implementing your fulfillRandomness
	* @notice method.
	*
	* @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this
	* @dev signature, and will call it once it has verified the proof
	* @dev associated with the randomness. (It is triggered via a call to
	* @dev rawFulfillRandomness, below.)
	*
	* @param requestId The Id initially returned by requestRandomness
	* @param randomWords the VRF output expanded to the requested number of words
	*/
	function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual;

	// rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF
	// proof. rawFulfillRandomness then calls fulfillRandomness, after validating
	// the origin of the call
	function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external {
		require (msg.sender == address(COORDINATOR), "!coordinator");
		fulfillRandomWords(requestId, randomWords);
	}

	  // Assumes the subscription is funded sufficiently.
	function requestRandomWords() internal returns(uint256 requestId) {
		RequestConfig memory rc = config;
		// Will revert if subscription is not set and funded.
		requestId = COORDINATOR.requestRandomWords(
			rc.keyHash,
			rc.subId,
			rc.requestConfirmations,
			rc.callbackGasLimit,
			rc.numWords
		);
	}

	function topUpSubscription(uint256 amount) external onlyOwner {
		LINK.transferAndCall(address(COORDINATOR), amount, abi.encode(config.subId));
	}

	function withdraw(uint256 amount, address to) external onlyOwner {
		LINK.transfer(to, amount);
	}

	function unsubscribe(address to) external onlyOwner {
		// Returns funds to this address
		COORDINATOR.cancelSubscription(config.subId, to);
		config.subId = 0;
	}

	function subscribe() public onlyOwner {
		// Create a subscription, current subId
		address[] memory consumers = new address[](1);
		consumers[0] = address(this);
		config.subId = COORDINATOR.createSubscription();
		COORDINATOR.addConsumer(config.subId, consumers[0]);
	}
}

File 11 of 13 : IVRFCoordinator2.sol
pragma solidity ^0.6.12;

interface VRFCoordinatorV2Interface {
  /**
   * @notice Get configuration relevant for making requests
   * @return minimumRequestConfirmations global min for request confirmations
   * @return maxGasLimit global max for request gas limit
   * @return s_provingKeyHashes list of registered key hashes
   */
  function getRequestConfig()
    external
    view
    returns (
      uint16,
      uint32,
      bytes32[] memory
    );

  /**
   * @notice Request a set of random words.
   * @param keyHash - Corresponds to a particular oracle job which uses
   * that key for generating the VRF proof. Different keyHash's have different gas price
   * ceilings, so you can select a specific one to bound your maximum per request cost.
   * @param subId  - The ID of the VRF subscription. Must be funded
   * with the minimum subscription balance required for the selected keyHash.
   * @param minimumRequestConfirmations - How many blocks you'd like the
   * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS
   * for why you may want to request more. The acceptable range is
   * [minimumRequestBlockConfirmations, 200].
   * @param callbackGasLimit - How much gas you'd like to receive in your
   * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords
   * may be slightly less than this amount because of gas used calling the function
   * (argument decoding etc.), so you may need to request slightly more than you expect
   * to have inside fulfillRandomWords. The acceptable range is
   * [0, maxGasLimit]
   * @param numWords - The number of uint256 random values you'd like to receive
   * in your fulfillRandomWords callback. Note these numbers are expanded in a
   * secure way by the VRFCoordinator from a single random value supplied by the oracle.
   * @return requestId - A unique identifier of the request. Can be used to match
   * a request to a response in fulfillRandomWords.
   */
  function requestRandomWords(
    bytes32 keyHash,
    uint64 subId,
    uint16 minimumRequestConfirmations,
    uint32 callbackGasLimit,
    uint32 numWords
  ) external returns (uint256 requestId);

  /**
   * @notice Create a VRF subscription.
   * @return subId - A unique subscription id.
   * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.
   * @dev Note to fund the subscription, use transferAndCall. For example
   * @dev  LINKTOKEN.transferAndCall(
   * @dev    address(COORDINATOR),
   * @dev    amount,
   * @dev    abi.encode(subId));
   */
  function createSubscription() external returns (uint64 subId);

  /**
   * @notice Get a VRF subscription.
   * @param subId - ID of the subscription
   * @return balance - LINK balance of the subscription in juels.
   * @return reqCount - number of requests for this subscription, determines fee tier.
   * @return owner - owner of the subscription.
   * @return consumers - list of consumer address which are able to use this subscription.
   */
  function getSubscription(uint64 subId)
    external
    view
    returns (
      uint96 balance,
      uint64 reqCount,
      address owner,
      address[] memory consumers
    );

  /**
   * @notice Request subscription owner transfer.
   * @param subId - ID of the subscription
   * @param newOwner - proposed new owner of the subscription
   */
  function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external;

  /**
   * @notice Request subscription owner transfer.
   * @param subId - ID of the subscription
   * @dev will revert if original owner of subId has
   * not requested that msg.sender become the new owner.
   */
  function acceptSubscriptionOwnerTransfer(uint64 subId) external;

  /**
   * @notice Add a consumer to a VRF subscription.
   * @param subId - ID of the subscription
   * @param consumer - New consumer which can use the subscription
   */
  function addConsumer(uint64 subId, address consumer) external;

  /**
   * @notice Remove a consumer from a VRF subscription.
   * @param subId - ID of the subscription
   * @param consumer - Consumer to remove from the subscription
   */
  function removeConsumer(uint64 subId, address consumer) external;

  /**
   * @notice Cancel a subscription
   * @param subId - ID of the subscription
   * @param to - Where to send the remaining LINK to
   */
  function cancelSubscription(uint64 subId, address to) external;
}

File 12 of 13 : ILink.sol
pragma solidity ^0.6.12;

interface LinkTokenInterface {
  function allowance(address owner, address spender) external view returns (uint256 remaining);

  function approve(address spender, uint256 value) external returns (bool success);

  function balanceOf(address owner) external view returns (uint256 balance);

  function decimals() external view returns (uint8 decimalPlaces);

  function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);

  function increaseApproval(address spender, uint256 subtractedValue) external;

  function name() external view returns (string memory tokenName);

  function symbol() external view returns (string memory tokenSymbol);

  function totalSupply() external view returns (uint256 totalTokensIssued);

  function transfer(address to, uint256 value) external returns (bool success);

  function transferAndCall(
    address to,
    uint256 value,
    bytes calldata data
  ) external returns (bool success);

  function transferFrom(
    address from,
    address to,
    uint256 value
  ) external returns (bool success);
}

File 13 of 13 : KongzExtraData.sol
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;

import "IERC20.sol";
import "SafeMath.sol";
import "Ownable.sol";

/*
 *     ,_,
 *    (',')
 *    {/"\}
 *    -"-"-
 */

contract KongzExtraData is Ownable {
	using SafeMath for uint256;

	mapping(address => bool) public approvedContracts;
	mapping(address => mapping(bytes32 => bool)) public approvecContractToStat;
	mapping(address => mapping(bytes32 => bool)) public approvecContractToItem;
	mapping(bytes32 => bool) internal enabledStats;
	mapping(bytes32 => bool) internal enabledItems;
	mapping(uint256 => mapping(bytes32 => uint256)) public stats;
	mapping(address => mapping(bytes32 => uint256)) public items;

	event StatIncreased(bytes32 indexed stat, uint256 indexed tokenId, uint256 amount);
	event StatDecreased(bytes32 indexed stat, uint256 indexed tokenId, uint256 amount);

	event ItemIncreased(bytes32 indexed item, address indexed user, uint256 amount);
	event ItemDecreased(bytes32 indexed item, address indexed user, uint256 amount);

	function updateStatContracts(address[] calldata _contracts, string[] calldata _statIds, bool[] calldata _vals) external onlyOwner {
		require(_contracts.length == _vals.length, "!len");

		for (uint256 i = 0 ; i < _contracts.length; i++) {
			approvecContractToStat[_contracts[i]][keccak256(abi.encodePacked(_statIds[i]))] = _vals[i];
		}
	}

	function updateItemContracts(address[] calldata _contracts, string[] calldata _itemIds, bool[] calldata _vals) external onlyOwner {
		require(_contracts.length == _vals.length, "!len");

		for (uint256 i = 0 ; i < _contracts.length; i++) {
			approvecContractToItem[_contracts[i]][keccak256(abi.encodePacked(_itemIds[i]))] = _vals[i];
		}
	}

	function adminUpdateStats(string[] calldata _stats, bool[] calldata _vals) external onlyOwner {
		require(_stats.length == _vals.length, "!len");

		for (uint256 i = 0 ; i < _stats.length; i++) {
			enabledStats[keccak256(abi.encodePacked(_stats[i]))] = _vals[i];
		}
	}

	function adminUpdateItems(string[] calldata _items, bool[] calldata _vals) external onlyOwner {
		require(_items.length == _vals.length, "!len");

		for (uint256 i = 0 ; i < _items.length; i++) {
			enabledItems[keccak256(abi.encodePacked(_items[i]))] = _vals[i];
		}
	}

	function incStats(string calldata _stat, uint256 _id, uint256 _amount) external {
		bytes32 statId = keccak256(abi.encodePacked(_stat));
		require(approvecContractToStat[msg.sender][statId] || msg.sender == owner(), "!stat");
		require(enabledStats[statId]);
		stats[_id][statId] = stats[_id][statId].add(_amount);
		emit StatIncreased(statId, _id, _amount);
	}

	function decStats(string calldata _stat, uint256 _id, uint256 _amount) external {
		bytes32 statId = keccak256(abi.encodePacked(_stat));
		require(approvecContractToStat[msg.sender][statId] || msg.sender == owner(), "!stat");
		require(enabledStats[statId]);
		stats[_id][statId] = stats[_id][statId].sub(_amount);
		emit StatDecreased(statId, _id, _amount);
	}

	function incStats(bytes32 _statId, uint256 _id, uint256 _amount) external {
		require(approvecContractToStat[msg.sender][_statId] || msg.sender == owner(), "!stat");
		require(enabledStats[_statId]);
		stats[_id][_statId] = stats[_id][_statId].add(_amount);
		emit StatIncreased(_statId, _id, _amount);
	}

	function decStats(bytes32 _statId, uint256 _id, uint256 _amount) external {
		require(approvecContractToStat[msg.sender][_statId] || msg.sender == owner(), "!stat");
		require(enabledStats[_statId]);
		stats[_id][_statId] = stats[_id][_statId].sub(_amount);
		emit StatDecreased(_statId, _id, _amount);
	}

	function incItem(string calldata _item, address _user, uint256 _amount) external {
		bytes32 itemId = keccak256(abi.encodePacked(_item));
		require(approvecContractToItem[msg.sender][itemId] || msg.sender == owner(), "!item");
		require(enabledItems[itemId]);
		items[_user][itemId] = items[_user][itemId].add(_amount);
		emit ItemIncreased(itemId, _user, _amount);
	}

	function decItem(string calldata _item, address _user, uint256 _amount) external {
		bytes32 itemId = keccak256(abi.encodePacked(_item));
		require(approvecContractToItem[msg.sender][itemId] || msg.sender == owner(), "!item");
		require(enabledItems[itemId]);
		items[_user][itemId] = items[_user][itemId].sub(_amount);
		emit ItemDecreased(itemId, _user, _amount);
	}

	function incItem(bytes32 _itemId, address _user, uint256 _amount) external {
		require(approvecContractToItem[msg.sender][_itemId] || msg.sender == owner(), "!item");
		require(enabledItems[_itemId]);
		items[_user][_itemId] = items[_user][_itemId].add(_amount);
		emit ItemIncreased(_itemId, _user, _amount);
	}

	function decItem(bytes32 _itemId, address _user, uint256 _amount) external {
		require(approvecContractToItem[msg.sender][_itemId] || msg.sender == owner(), "!item");
		require(enabledItems[_itemId]);
		items[_user][_itemId] = items[_user][_itemId].sub(_amount);
		emit ItemDecreased(_itemId, _user, _amount);
	}
}

Settings
{
  "evmVersion": "istanbul",
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_nanas","type":"address"},{"internalType":"address","name":"_vx","type":"address"},{"internalType":"address","name":"_charms","type":"address"},{"internalType":"address","name":"_logic","type":"address"},{"internalType":"address","name":"_extra","type":"address"},{"internalType":"address","name":"_vrfCoordinator","type":"address"},{"internalType":"address","name":"_link","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"teamId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"charm","type":"uint256"}],"name":"ActivateCharm","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"teamId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"data","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"AdventureDone","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"seasonId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"commiter","type":"address"}],"name":"CommitKongium","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"KongiumBurn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"KongiumMint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"prize","type":"uint256"}],"name":"StartSeason","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"teamId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"teamData","type":"uint256"}],"name":"TeamAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"teamId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"teamData","type":"uint256"}],"name":"TeamChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"teamId","type":"uint256"}],"name":"TeamRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"newLevels","type":"uint256[]"}],"name":"UpgradeVX","type":"event"},{"inputs":[],"name":"KONGIUM_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LVL_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_teamId","type":"uint256"},{"internalType":"uint256","name":"_charm","type":"uint256"}],"name":"activateCharm","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[5]","name":"_vx","type":"uint256[5]"}],"name":"addTeam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"approvedContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burnKongium","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"charmInUse","outputs":[{"internalType":"uint256","name":"charmType","type":"uint256"},{"internalType":"uint256","name":"hp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"charms","outputs":[{"internalType":"contract IERC1155","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_season","type":"uint256"}],"name":"claimNana","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"commitKongium","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"committedKongium","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"config","outputs":[{"internalType":"uint64","name":"subId","type":"uint64"},{"internalType":"uint32","name":"callbackGasLimit","type":"uint32"},{"internalType":"uint16","name":"requestConfirmations","type":"uint16"},{"internalType":"uint32","name":"numWords","type":"uint32"},{"internalType":"bytes32","name":"keyHash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint256[5]","name":"_vx","type":"uint256[5]"}],"name":"editTeam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"energyCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"energyFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"extraData","outputs":[{"internalType":"contract KongzExtraData","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getCharmInUse","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_team","type":"uint256"}],"name":"getExpInTeam","outputs":[{"internalType":"uint256[5]","name":"exp","type":"uint256[5]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_kongIds","type":"uint256[]"}],"name":"getKongStats","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_team","type":"uint256"}],"name":"getLevelsInTeam","outputs":[{"internalType":"uint256[5]","name":"_levels","type":"uint256[5]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"globalCommittedKongium","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"grantExp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"hasCommitted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nanas","type":"address"},{"internalType":"address","name":"_vx","type":"address"},{"internalType":"address","name":"_charms","type":"address"},{"internalType":"address","name":"_logic","type":"address"},{"internalType":"address","name":"_extra","type":"address"},{"internalType":"address","name":"_vrfCoordinator","type":"address"},{"internalType":"address","name":"_link","type":"address"},{"internalType":"address","name":"_newOwner","type":"address"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"kongium","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastFreeRun","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"logic","outputs":[{"internalType":"contract IJungleLogic","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintKongium","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nanaCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nanaFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nanaRewardTable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nanas","outputs":[{"internalType":"contract INana","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"pendingEnergy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"removeTeam","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rodCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_teamId","type":"uint256"},{"internalType":"bool","name":"_energy","type":"bool"}],"name":"runAdventure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_teamId","type":"uint256"},{"internalType":"bool","name":"_energy","type":"bool"}],"name":"runAdventureVRF","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"season","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"seasonDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"seasonLastUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"seasonRewardBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"seasonStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_val","type":"bool"}],"name":"setPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startSeason","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subscribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_val","type":"bool"}],"name":"switchVrf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"teamCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"teams","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"topUpSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"unsubscribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_contracts","type":"address[]"},{"internalType":"bool[]","name":"_values","type":"bool[]"}],"name":"updateApprovedContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"updateEnergyFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_extra","type":"address"}],"name":"updateExtraData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_logic","type":"address"}],"name":"updateLogic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cost","type":"uint256"}],"name":"updateNanaCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"updateNanaFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cost","type":"uint256"}],"name":"updateRodCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_length","type":"uint256"}],"name":"updateSeasonLength","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_vx","type":"uint256[]"}],"name":"upgradeVxLvl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"useVrf","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vx","outputs":[{"internalType":"contract ILock","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"vxXp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"weights","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052620d9f80600b556101f4600f5560c86010553480156200002357600080fd5b50604051620050753803806200507583398101604081905262000046916200021c565b8181600062000054620001fa565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600380546001600160a01b03199081166001600160a01b03948516178255600480548216938516939093179092556040805160a0810182526000808252620f424060208301819052928201939093526001606082018190527f6e099d640cde6de9d40ac749b4b594126b0169747122711109c9985d47751f9360809092018290528054600160701b6001600160601b03199091166a0f424000000000000000001761ffff60601b19166c030000000000000000000000001763ffffffff60701b19161790556002556005805484168c8616179055600e556006805483168a85161790556007805483168985161790556008805483168885161790556009805490921692861692909217905569010f0cf064dd59200000906011015569021e19e0c9bab240000060116001015569032d26d12e980b60000060116002015569043c33c193756480000060116003015550620002b795505050505050565b3390565b80516001600160a01b03811681146200021657600080fd5b92915050565b600080600080600080600060e0888a03121562000237578283fd5b620002438989620001fe565b9650620002548960208a01620001fe565b9550620002658960408a01620001fe565b9450620002768960608a01620001fe565b9350620002878960808a01620001fe565b9250620002988960a08a01620001fe565b9150620002a98960c08a01620001fe565b905092959891949750929550565b614dae80620002c76000396000f3fe608060405234801561001057600080fd5b50600436106104115760003560e01c80638da5cb5b11610220578063bedb86fb11610130578063e76c5908116100b8578063f23a6e6111610087578063f23a6e611461087a578063f2fde38b1461089a578063f5b617db146108ad578063f9733cfc146108c0578063fceeda0d146108c857610411565b8063e76c590814610844578063e89571971461084c578063ea0316b614610854578063f0ee1cc41461086757610411565b8063d64d9314116100ff578063d64d9314146107e2578063d7dfa0dd146107f5578063dbebf55f146107fd578063dd229b6a14610810578063e1a347b81461083157610411565b8063bedb86fb146107a1578063c4750e19146107b4578063c4dc70da146107c7578063c50b0fb0146107da57610411565b8063a0e75cc8116101b3578063a8ec0ed811610182578063a8ec0ed814610758578063ac52e64414610760578063b187bd2614610773578063b1a6505f1461077b578063b39fafeb1461078e57610411565b8063a0e75cc81461070c578063a34671161461071f578063a56184a714610732578063a7cac8461461074557610411565b806396b17037116101ef57806396b17037146106bc5780639bcda08f146106cf5780639d66a187146106d75780639fd4b3e0146106f957610411565b80638da5cb5b1461069c5780638f449a05146106a4578063929e9519146106ac578063952a9633146106b457610411565b806344315a19116103265780637262561c116102ae578063795e617e1161027d578063795e617e1461063d578063803b71701461065057806382997ea11461066357806386850e931461067657806386d1f8551461068957610411565b80637262561c146105eb57806373003f37146105fe57806376fa77c31461061157806379502c551461062457610411565b806358de4c37116102f557806358de4c37146105ad578063609d3334146105c05780636d6a9961146105c8578063715018a6146105db578063715a1144146105e357610411565b806344315a191461055f57806346f8478b146105725780634e8c0bd614610592578063525240c01461059a57610411565b806315cfb908116103a95780633874bdb1116103785780633874bdb11461050b5780633ba98dd61461051e5780633d0700e2146105315780633ddb305f1461053957806343d6bf4c1461054c57610411565b806315cfb908146104d55780631fe543e3146104dd578063221b00c7146104f05780632ea9fb0c146104f857610411565b80631068eefa116103e55780631068eefa1461047a57806311237ba01461048d578063144f9da1146104a0578063156f3fc4146104c057610411565b8062f714ce14610416578063078bf0de1461042b578063089f9c86146104545780631009049c14610467575b600080fd5b610429610424366004614348565b6108db565b005b61043e610439366004614348565b6109a1565b60405161044b9190614661565b60405180910390f35b6104296104623660046141f3565b6109be565b61043e610475366004614318565b6109fb565b61043e6104883660046141f3565b610a0d565b61043e61049b3660046144f5565b610a6b565b6104b36104ae366004614318565b610dd1565b60405161044b9190614744565b6104c8610ec4565b60405161044b919061466a565b61043e610ed3565b6104296104eb36600461445a565b610ee5565b61043e610f19565b610429610506366004614318565b610f1f565b6104296105193660046144f5565b610f59565b61042961052c3660046142a1565b6114f6565b6104c8611841565b61043e610547366004614318565b611850565b61043e61055a366004614348565b611862565b61042961056d366004614318565b61187f565b6105856105803660046141f3565b611a5c565b60405161044b91906147eb565b6104c8611a7c565b6104296105a83660046140a7565b611a8b565b61043e6105bb366004614318565b611bb9565b6104c8611bcb565b6104296105d636600461442e565b611bda565b610429611edb565b610585611f5a565b6104296105f936600461406f565b611f6a565b6104b361060c366004614318565b612024565b61043e61061f366004614318565b61208d565b61062c6120a1565b60405161044b959493929190614c77565b61042961064b36600461406f565b6120db565b61043e61065e366004614348565b612132565b610429610671366004614519565b61214f565b610429610684366004614318565b61225a565b6104296106973660046141f3565b612346565b6104c861237f565b61042961238e565b61042961251e565b610429612695565b6104296106ca3660046142e0565b6126d4565b61043e612727565b6106ea6106e53660046142a1565b612739565b60405161044b939291906147a8565b61043e61070736600461406f565b612965565b61042961071a366004614318565b6129fe565b61042961072d366004614519565b612a38565b610429610740366004614318565b612a96565b61043e61075336600461406f565b612bd7565b61043e612be9565b61042961076e36600461421e565b612bef565b610585612cc4565b61058561078936600461406f565b612cd4565b61042961079c36600461406f565b612ce9565b6104296107af3660046142e0565b612d40565b61043e6107c2366004614318565b612d93565b61043e6107d536600461406f565b612da4565b61043e612e35565b6104296107f0366004614286565b612e3b565b6104c861305b565b61043e61080b366004614318565b61306a565b61082361081e3660046141f3565b61307c565b60405161044b929190614c10565b61042961083f366004614318565b6130a0565b61043e6130da565b61043e6130e0565b61043e61086236600461406f565b6130e6565b61043e6108753660046141f3565b6130f8565b61088d61088836600461414f565b613115565b60405161044b9190614864565b6104296108a836600461406f565b613127565b6104296108bb366004614318565b6131dd565b61043e613217565b6104296108d6366004614318565b61321d565b6108e3613257565b6000546001600160a01b039081169116146109195760405162461bcd60e51b815260040161091090614ad8565b60405180910390fd5b6004805460405163a9059cbb60e01b81526001600160a01b039091169163a9059cbb9161094a9185918791016146da565b602060405180830381600087803b15801561096457600080fd5b505af1158015610978573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099c91906142fc565b505050565b601b60209081526000928352604080842090915290825290205481565b3360009081526022602052604090205460ff166109ed5760405162461bcd60e51b81526004016109109061488c565b6109f7828261325b565b5050565b601a6020526000908152604090205481565b6000610a17613f17565b506001600160a01b03831660009081526018602090815260408083208584528252918290208251808401909352805483526001015490820181905215610a5f57519050610a65565b60009150505b92915050565b600954600090600160a01b900460ff16610a975760405162461bcd60e51b815260040161091090614a25565b600454600160a81b900460ff1615610ac15760405162461bcd60e51b815260040161091090614a4c565b33600090815260156020908152604080832086845290915290205480610af95760405162461bcd60e51b815260040161091090614bb9565b610b02336132d3565b60008315610b2557610b2033600e54610b1a856133fc565b0261343e565b610d42565b6000610b3c600d54610b36856133fc565b906134bc565b6005546040516323b872dd60e01b81529192506001600160a01b0316906323b872dd90610b719033903090869060040161467e565b602060405180830381600087803b158015610b8b57600080fd5b505af1158015610b9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc391906142fc565b50610bea610bd28260026134fd565b600c546000908152601e60205260409020549061353f565b600c546000908152601e60205260409020556005546001600160a01b031663a9059cbb610c1561237f565b610c2084600a6134fd565b6040518363ffffffff1660e01b8152600401610c3d9291906146da565b602060405180830381600087803b158015610c5757600080fd5b505af1158015610c6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8f91906142fc565b506005546001600160a01b031663a9059cbb61dead610ccd610cb285600a6134fd565b610cc7610cc08760026134fd565b8790613564565b90613564565b6040518363ffffffff1660e01b8152600401610cea9291906146da565b602060405180830381600087803b158015610d0457600080fd5b505af1158015610d18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3c91906142fc565b50506001015b6000610d4c6135a6565b9050610d59338787613699565b6040518060400160405280336001600160a01b03168152602001610d9084610d81338b610a0d565b87610d8b89610dd1565b6136fc565b90526000828152602360209081526040909120825181546001600160a01b0319166001600160a01b0390911617815591015160019091015595945050505050565b610dd9613f31565b60005b6005811015610ebe5763ffffffff6020820284901c168015610ea157600954604051639bf6e27760e01b81526001600160a01b0390911690639bf6e27790610e38908490600080516020614d5983398151915290600401614c10565b60206040518083038186803b158015610e5057600080fd5b505afa158015610e64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e889190614330565b600101838360058110610e9757fe5b6020020152610eb5565b6000838360058110610eaf57fe5b60200201525b50600101610ddc565b50919050565b6007546001600160a01b031681565b600080516020614d5983398151915281565b6003546001600160a01b03163314610f0f5760405162461bcd60e51b815260040161091090614b2d565b6109f78282613721565b60105481565b610f27613257565b6000546001600160a01b03908116911614610f545760405162461bcd60e51b815260040161091090614ad8565b600d55565b600954600160a01b900460ff1615610f835760405162461bcd60e51b815260040161091090614a04565b600454600160a81b900460ff1615610fad5760405162461bcd60e51b815260040161091090614a4c565b33600090815260156020908152604080832085845290915290205480610fe55760405162461bcd60e51b815260040161091090614bb9565b610fee336132d3565b6000821561100b5761100633600e54610b1a856133fc565b6111ef565b600061101c600d54610b36856133fc565b6005546040516323b872dd60e01b81529192506001600160a01b0316906323b872dd906110519033903090869060040161467e565b602060405180830381600087803b15801561106b57600080fd5b505af115801561107f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110a391906142fc565b506110b2610bd28260026134fd565b600c546000908152601e60205260409020556005546001600160a01b031663a9059cbb6110dd61237f565b6110e884600a6134fd565b6040518363ffffffff1660e01b81526004016111059291906146da565b602060405180830381600087803b15801561111f57600080fd5b505af1158015611133573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115791906142fc565b506005546001600160a01b031663a9059cbb61dead61117a610cb285600a6134fd565b6040518363ffffffff1660e01b81526004016111979291906146da565b602060405180830381600087803b1580156111b157600080fd5b505af11580156111c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e991906142fc565b50506001015b6111fa338585613699565b6000611204613f4f565b61120c613f4f565b611214613f4f565b61121c613f4f565b6008546001600160a01b031663132a3c77611237338c610a0d565b6112416000613aa2565b8a61124b8c610dd1565b6040518563ffffffff1660e01b815260040161126a9493929190614c1e565b6101206040518083038186803b15801561128357600080fd5b505afa158015611297573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bb9190614377565b9450945094509450945060006112e98860e088901c6001166001018960208a901c63ffffffff160102613b18565b905060005b600281101561146d5782816002811061130357fe5b602002015161048314156113aa5785816002811061131d57fe5b60200201516001600160a01b031663f242432a303388856002811061133e57fe5b602002015188866002811061134f57fe5b60200201516040518563ffffffff1660e01b815260040161137394939291906146a2565b600060405180830381600087803b15801561138d57600080fd5b505af11580156113a1573d6000803e3d6000fd5b50505050611465565b8281600281106113b657fe5b602002015160141415611465578581600281106113cf57fe5b60200201516001600160a01b031663a9059cbb338684600281106113ef57fe5b60200201516040518363ffffffff1660e01b81526004016114119291906146da565b602060405180830381600087803b15801561142b57600080fd5b505af115801561143f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061146391906142fc565b505b6001016112ee565b5061147e338763ffffffff1661325b565b87337f755d55693d08f747c78bd2707a8c8959f06e154f5434ab871837935f8b823db5605f6114ad838f610a0d565b901b60466114c26114bd8e610dd1565b613b81565b901b60458c901b604087901b8c17171717426040516114e2929190614c10565b60405180910390a350505050505050505050565b6000806060836001600160401b038111801561151157600080fd5b5060405190808252806020026020018201604052801561153b578160200160208202803683370190505b50905060005b848110156117fe5760065433906001600160a01b0316636352211e88888581811061156857fe5b905060200201356040518263ffffffff1660e01b815260040161158b9190614661565b60206040518083038186803b1580156115a357600080fd5b505afa1580156115b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115db919061408b565b6001600160a01b0316146116015760405162461bcd60e51b815260040161091090614bf0565b6009546000906001600160a01b0316639bf6e27788888581811061162157fe5b90506020020135600080516020614d5983398151915260001b6040518363ffffffff1660e01b8152600401611657929190614c10565b60206040518083038186803b15801561166f57600080fd5b505afa158015611683573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a79190614330565b6008546040516301e8e74960e41b81529192506001600160a01b031690631e8e7490906116db906001850190600401614661565b604080518083038186803b1580156116f257600080fd5b505afa158015611706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061172a919061453a565b909550935061174b87878481811061173e57fe5b9050602002013586613bbd565b6117553385613bf5565b6009546001600160a01b031663422f5e31600080516020614d5983398151915289898681811061178157fe5b9050602002013560016040518463ffffffff1660e01b81526004016117a893929190614815565b600060405180830381600087803b1580156117c257600080fd5b505af11580156117d6573d6000803e3d6000fd5b50505050806001018383815181106117ea57fe5b602090810291909101015250600101611541565b507fc5b54947489d8d7d1927d7a711b301d2309968735ad1ddb4e01651aa0bf36eeb85858360405161183293929190614752565b60405180910390a15050505050565b6005546001600160a01b031681565b601e6020526000908152604090205481565b601f60209081526000928352604080842090915290825290205481565b336000908152601560209081526040808320848452909152902054806118b75760405162461bcd60e51b8152600401610910906148d8565b3360009081526016602052604081205490805b60058110156119585763ffffffff6020820285901c16801561194f576006546040516340a9c8df60e01b81526001909401936001600160a01b03909116906340a9c8df9061191c908490600401614661565b600060405180830381600087803b15801561193657600080fd5b505af115801561194a573d6000803e3d6000fd5b505050505b506001016118ca565b5060018211156119b1573360008181526015602090815260408083206000198701808552908352818420548985528285205593835260188252808320938352929052818120868252919020815481556001918201549101555b3360008181526015602090815260408083206000198701808552908352818420849055848452601883528184209084529091528120818155600101556119f6906132d3565b336000818152601760209081526040808320805486900390556016909152908190208054600019019055517f56d724a27bc27aafed48ed31193014493b6d49352ecf862395040cefb8d7ee9191611a4e9187906146da565b60405180910390a150505050565b602160209081526000928352604080842090915290825290205460ff1681565b6006546001600160a01b031681565b600454600160a01b900460ff1615611aa257600080fd5b6004805460ff60a01b1916600160a01b179055600580546001600160a01b038a81166001600160a01b031992831617909255620f4240600e556101f4600f5560c8601055620d9f80600b55600680548a84169083161790556007805489841690831617905560088054888416908316179055600980549287169290911691909117905569010f0cf064dd5920000060115569021e19e0c9bab240000060125569032d26d12e980b60000060135569043c33c1937564800000601455611b678383613c37565b600080546001600160a01b0319166001600160a01b03831690811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35050505050505050565b601d6020526000908152604090205481565b6009546001600160a01b031681565b33600090815260156020908152604080832085845290915290205480611c125760405162461bcd60e51b8152600401610910906148d8565b6000611c1d826133fc565b905060008060005b6005811015611e085763ffffffff602060048390030286901c166000878360058110611c4d57fe5b60200201359050600081118015611c645750818114155b15611d72576006546040516331a9108f60e11b815233916001600160a01b031690636352211e90611c99908590600401614661565b60206040518083038186803b158015611cb157600080fd5b505afa158015611cc5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce9919061408b565b6001600160a01b031614611d0f5760405162461bcd60e51b815260040161091090614bf0565b60065460405163013cce6f60e51b81526001600160a01b0390911690632799cde090611d3f908490600401614661565b600060405180830381600087803b158015611d5957600080fd5b505af1158015611d6d573d6000803e3d6000fd5b505050505b600082118015611d825750818114155b15611dea576006546040516340a9c8df60e01b81526001600160a01b03909116906340a9c8df90611db7908590600401614661565b600060405180830381600087803b158015611dd157600080fd5b505af1158015611de5573d6000803e3d6000fd5b505050505b93840160201b938015611dfe576001909301925b5050600101611c25565b5060209190911c9081611e2d5760405162461bcd60e51b8152600401610910906148d8565b3360008181526015602090815260408083208a84529091529020839055611e53906132d3565b82811115611e77573360009081526017602052604090208054848303019055611e98565b82811015611e98573360009081526017602052604090208054828503900390555b7ffb059afa0f171c4c819ddc773ceb11b0916b243f583b0ba31df704024e1f4877338784604051611ecb939291906146f3565b60405180910390a1505050505050565b611ee3613257565b6000546001600160a01b03908116911614611f105760405162461bcd60e51b815260040161091090614ad8565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b600954600160a01b900460ff1681565b611f72613257565b6000546001600160a01b03908116911614611f9f5760405162461bcd60e51b815260040161091090614ad8565b600354600154604051630d7ae1d360e41b81526001600160a01b039092169163d7ae1d3091611fde916001600160401b03909116908590600401614c55565b600060405180830381600087803b158015611ff857600080fd5b505af115801561200c573d6000803e3d6000fd5b50506001805467ffffffffffffffff19169055505050565b61202c613f31565b60005b6005811015610ebe5763ffffffff6020820284901c1680156120705760008181526019602052604090205483836005811061206657fe5b6020020152612084565b600083836005811061207e57fe5b60200201525b5060010161202f565b6011816004811061209a57fe5b0154905081565b6001546002546001600160401b0382169163ffffffff600160401b820481169261ffff600160601b84041692600160701b90049091169085565b6120e3613257565b6000546001600160a01b039081169116146121105760405162461bcd60e51b815260040161091090614ad8565b600880546001600160a01b0319166001600160a01b0392909216919091179055565b601c60209081526000928352604080842090915290825290205481565b33600090815260166020526040902054821061217d5760405162461bcd60e51b815260040161091090614b74565b604080518082018252828152612711602080830191825233600081815260188352858120888252909252908490209251835590516001928301556007549251637921219560e11b81526001600160a01b039093169263f242432a926121eb929161dead9187916004016146a2565b600060405180830381600087803b15801561220557600080fd5b505af1158015612219573d6000803e3d6000fd5b505050507f3a53674ff33a6a6b6ff4b381268eb8f515e596650b9049e2f465559af56a6e61828260405161224e929190614c10565b60405180910390a15050565b612262613257565b6000546001600160a01b0390811691161461228f5760405162461bcd60e51b815260040161091090614ad8565b6004546003546001546040516001600160a01b0393841693634000aea093169185916122c7916001600160401b031690602001614c41565b6040516020818303038152906040526040518463ffffffff1660e01b81526004016122f493929190614714565b602060405180830381600087803b15801561230e57600080fd5b505af1158015612322573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f791906142fc565b3360009081526022602052604090205460ff166123755760405162461bcd60e51b815260040161091090614981565b6109f78282613bf5565b6000546001600160a01b031690565b612396613257565b6000546001600160a01b039081169116146123c35760405162461bcd60e51b815260040161091090614ad8565b6040805160018082528183019092526060916020808301908036833701905050905030816000815181106123f357fe5b6001600160a01b039283166020918202929092018101919091526003546040805163288688f960e21b81529051919093169263a21a23e49260048083019391928290030181600087803b15801561244957600080fd5b505af115801561245d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612481919061455d565b6001805467ffffffffffffffff19166001600160401b03928316179081905560035483516001600160a01b0390911692637341c10c92169084906000906124c457fe5b60200260200101516040518363ffffffff1660e01b81526004016124e9929190614c55565b600060405180830381600087803b15801561250357600080fd5b505af1158015612517573d6000803e3d6000fd5b5050505050565b600c546000908152601d6020526040902054600b540142106125525760405162461bcd60e51b81526004016109109061490f565b600454600160a81b900460ff161561257c5760405162461bcd60e51b815260040161091090614a4c565b60095460405163c00c813760e01b81526000916001600160a01b03169063c00c8137906125bd903390600080516020614d39833981519152906004016146da565b60206040518083038186803b1580156125d557600080fd5b505afa1580156125e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061260d9190614330565b600c80546000908152601f602090815260408083203380855290835281842080548701905593548352908052902080548301905590915061264e9082613bf5565b336001600160a01b0316600c547ff5f311a0329198906d6b8a4b641bb2ae4cfcfa61c2a5d4caf9f9bce29711fd9b8360405161268a9190614661565b60405180910390a350565b61269d613257565b6000546001600160a01b039081169116146126ca5760405162461bcd60e51b815260040161091090614ad8565b6126d2613cfc565b565b6126dc613257565b6000546001600160a01b039081169116146127095760405162461bcd60e51b815260040161091090614ad8565b60098054911515600160a01b0260ff60a01b19909216919091179055565b600080516020614d3983398151915281565b6060808080846001600160401b038111801561275457600080fd5b5060405190808252806020026020018201604052801561277e578160200160208202803683370190505b5090506060856001600160401b038111801561279957600080fd5b506040519080825280602002602001820160405280156127c3578160200160208202803683370190505b5090506060866001600160401b03811180156127de57600080fd5b50604051908082528060200260200182016040528015612808578160200160208202803683370190505b50905060005b8781101561295657601960008a8a8481811061282657fe5b9050602002013581526020019081526020016000205483828151811061284857fe5b60209081029190910101526009546001600160a01b0316639bf6e2778a8a8481811061287057fe5b90506020020135600080516020614d5983398151915260001b6040518363ffffffff1660e01b81526004016128a6929190614c10565b60206040518083038186803b1580156128be57600080fd5b505afa1580156128d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f69190614330565b60010184828151811061290557fe5b602002602001018181525050601a60008a8a8481811061292157fe5b9050602002013581526020019081526020016000205482828151811061294357fe5b602090810291909101015260010161280e565b50919450925090509250925092565b600c546000908152601d6020526040812054600b54829061298a904284900390613d75565b600c546000908152601c602090815260408083206001600160a01b03891684529091529020549091506129f3620151806129ed6129c78585613564565b6001600160a01b038916600090815260176020526040902054610b3690620f42406134bc565b906134fd565b93505050505b919050565b612a06613257565b6000546001600160a01b03908116911614612a335760405162461bcd60e51b815260040161091090614ad8565b600f55565b3360009081526022602052604090205460ff16612a675760405162461bcd60e51b81526004016109109061488c565b600082815260196020526040902054612a80908261353f565b6000928352601960205260409092209190915550565b600c548110612ab75760405162461bcd60e51b815260040161091090614b0d565b6000818152601f6020908152604080832033845282528083205484845282805281842054601e90935290832054909290612af79083906129ed90866134bc565b6000858152601f602090815260408083203384529091528120559050612b1d8284613564565b60008581526020808052604080832093909355601e90522054612b409082613564565b6000858152601e60205260409081902091909155600554905163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90612b8590339085906004016146da565b602060405180830381600087803b158015612b9f57600080fd5b505af1158015612bb3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061251791906142fc565b60176020526000908152604090205481565b600e5481565b612bf7613257565b6000546001600160a01b03908116911614612c245760405162461bcd60e51b815260040161091090614ad8565b828114612c435760405162461bcd60e51b815260040161091090614b53565b60005b8381101561251757828282818110612c5a57fe5b9050602002016020810190612c6f91906142e0565b60226000878785818110612c7f57fe5b9050602002016020810190612c94919061406f565b6001600160a01b031681526020810191909152604001600020805460ff1916911515919091179055600101612c46565b600454600160a81b900460ff1681565b60226020526000908152604090205460ff1681565b612cf1613257565b6000546001600160a01b03908116911614612d1e5760405162461bcd60e51b815260040161091090614ad8565b600980546001600160a01b0319166001600160a01b0392909216919091179055565b612d48613257565b6000546001600160a01b03908116911614612d755760405162461bcd60e51b815260040161091090614ad8565b60048054911515600160a81b0260ff60a81b19909216919091179055565b602080526000908152604090205481565b60095460405163c00c813760e01b81526000916001600160a01b03169063c00c813790612de5908590600080516020614d39833981519152906004016146da565b60206040518083038186803b158015612dfd57600080fd5b505afa158015612e11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a659190614330565b600c5481565b3360009081526016602052604081205481805b6005811015612fbd57848160058110612e6357fe5b602002013515612f9a5760065433906001600160a01b0316636352211e878460058110612e8c57fe5b60200201356040518263ffffffff1660e01b8152600401612ead9190614661565b60206040518083038186803b158015612ec557600080fd5b505afa158015612ed9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612efd919061408b565b6001600160a01b031614612f235760405162461bcd60e51b815260040161091090614bf0565b6006546001909201916001600160a01b0316632799cde0868360058110612f4657fe5b60200201356040518263ffffffff1660e01b8152600401612f679190614661565b600060405180830381600087803b158015612f8157600080fd5b505af1158015612f95573d6000803e3d6000fd5b505050505b6020858260058110612fa857fe5b60200201359490940190931b92600101612e4e565b50602083901c925060008311612fe55760405162461bcd60e51b8152600401610910906148d8565b612fee336132d3565b33600081815260176020908152604080832080548601905560158252808320868452825280832087905583835260169091529081902080546001019055517f46ba7f4daa6170e9b3c365725c0b59e6b10da8ff249c9bba46a9122f7dd1014e91611a4e91859087906146f3565b6008546001600160a01b031681565b60196020526000908152604090205481565b60186020908152600092835260408084209091529082529020805460019091015482565b6130a8613257565b6000546001600160a01b039081169116146130d55760405162461bcd60e51b815260040161091090614ad8565b600e55565b600b5481565b600f5481565b60166020526000908152604090205481565b601560209081526000928352604080842090915290825290205481565b63f23a6e6160e01b9695505050505050565b61312f613257565b6000546001600160a01b0390811691161461315c5760405162461bcd60e51b815260040161091090614ad8565b6001600160a01b0381166131825760405162461bcd60e51b81526004016109109061493b565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6131e5613257565b6000546001600160a01b039081169116146132125760405162461bcd60e51b815260040161091090614ad8565b601055565b600d5481565b613225613257565b6000546001600160a01b039081169116146132525760405162461bcd60e51b815260040161091090614ad8565b600b55565b3390565b6009546040516365199c3160e01b81526001600160a01b03909116906365199c319061329d90600080516020614d3983398151915290869086906004016147f6565b600060405180830381600087803b1580156132b757600080fd5b505af11580156132cb573d6000803e3d6000fd5b505050505050565b6000600c54116132f55760405162461bcd60e51b815260040161091090614a6d565b600454600160a81b900460ff1661330e5761330e613d8b565b600c546000908152601d6020526040812054600b54909190613334904284900390613d75565b600c546000908152601c602090815260408083206001600160a01b0388168452909152902054909150808211156133cc5761339f620151806129ed6133798585613564565b6001600160a01b038816600090815260176020526040902054610b3690620f42406134bc565b600c546000908152601b602090815260408083206001600160a01b03891684529091529020805490910190555b50600c546000908152601c602090815260408083206001600160a01b039096168352949052929092209190915550565b600080805b60058110156134375763ffffffff6020820285901c1680613423576000613426565b60015b60ff16929092019150600101613401565b5092915050565b604080518082018252600781526621656e6572677960c81b602080830191909152600c546000908152601b82528381206001600160a01b0387168252909152919091205461348d918390613db0565b600c546000908152601b602090815260408083206001600160a01b039096168352949052929092209190915550565b6000826134cb57506000610a65565b828202828482816134d857fe5b04146134f65760405162461bcd60e51b815260040161091090614a97565b9392505050565b60006134f683836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613ddc565b6000828201838110156134f65760405162461bcd60e51b8152600401610910906149cd565b60006134f683836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613db0565b60006135b0613f6d565b506040805160a0810182526001546001600160401b03811680835263ffffffff600160401b830481166020850181905261ffff600160601b850416858701819052600160701b909404909116606085018190526002546080860181905260035496516305d3b1d360e41b815295966001600160a01b031695635d3b1d3095613641959294929390929160040161482b565b602060405180830381600087803b15801561365b57600080fd5b505af115801561366f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136939190614330565b91505090565b6001600160a01b038316600090815260186020908152604080832085845290915281206001810154909181156132cb5783156136d85750600f546136dd565b506010545b8082106136ec578082036136ef565b60005b6001840155505050505050565b6000600285901b840160191b61371183613b81565b0160a01b83019050949350505050565b613729613f9b565b506000828152602360209081526040808320815180830190925280546001600160a01b0316808352600190910154928201839052909290919061376a613f4f565b613772613f4f565b61377a613f4f565b613782613f4f565b60085489516001600160a01b039091169063132a3c7790600360b98a901c16906137be908d906000906137b157fe5b6020026020010151613aa2565b896001600160a01b03166137db60a08c901c6301ffffff16613e13565b6040518563ffffffff1660e01b81526004016137fa9493929190614c1e565b6101206040518083038186803b15801561381357600080fd5b505afa158015613827573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061384b9190614377565b945094509450945094506000613886876001600160a01b031660e088901c60011660010160bb8a901c60208a901c63ffffffff160102613b18565b905060005b6002811015613a0a578281600281106138a057fe5b60200201516104831415613947578581600281106138ba57fe5b60200201516001600160a01b031663f242432a308b8885600281106138db57fe5b60200201518886600281106138ec57fe5b60200201516040518563ffffffff1660e01b815260040161391094939291906146a2565b600060405180830381600087803b15801561392a57600080fd5b505af115801561393e573d6000803e3d6000fd5b50505050613a02565b82816002811061395357fe5b602002015160141415613a025785816002811061396c57fe5b60200201516001600160a01b031663a9059cbb8a86846002811061398c57fe5b60200201516040518363ffffffff1660e01b81526004016139ae9291906146da565b602060405180830381600087803b1580156139c857600080fd5b505af11580156139dc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a0091906142fc565b505b60010161388b565b50613a1b888763ffffffff1661325b565b866001600160a01b0316886001600160a01b03167f755d55693d08f747c78bd2707a8c8959f06e154f5434ab871837935f8b823db5605f60b98b901c600316901b604660a08c901c6301ffffff16901b604560bb8d901c901b604087901b8c1717171742604051613a8d929190614c10565b60405180910390a35050505050505050505050565b600081613ae957600a805460018101909155604051613ac991339144914291602001614632565b6040516020818303038152906040528051906020012060001c90506129f9565b81604051602001613afa9190614661565b60408051601f19818403018152919052805160209091012092915050565b600042815b6005811015613b795763ffffffff6020820286901c168015613b70576000613b458285613e4d565b90508015613b5757826001901b851794505b6000828152601960205260409020805491870190910190555b50600101613b1d565b505092915050565b60008060005b6005811015613bb3576005848260058110613b9e57fe5b60200201519290920190911b90600101613b87565b5060051c92915050565b60408051808201825260048152630216578760e41b602080830191909152600085815260199091529190912054612a80918390613db0565b600954604051635b18f12960e11b81526001600160a01b039091169063b631e2529061329d90600080516020614d3983398151915290869086906004016147f6565b600380546001600160a01b03199081166001600160a01b039485161782556004805490911692909316919091179091556040805160a08101825260008152620f42406020820152908101919091526001606082018190527f6e099d640cde6de9d40ac749b4b594126b0169747122711109c9985d47751f9360809092018290528054600160701b6bffffffffffffffffffffffff199091166a0f424000000000000000001761ffff60601b1916600360601b1763ffffffff60701b1916179055600255565b600c8054600101908190556000908152601d60205260408120429055613d2181613aa2565b9050600060116004830660048110613d3557fe5b01549050613d4281613ec7565b7f9b492ca62dd845faf66276dbd14ed82e0d819d8b172cb51433ffe4268ab3dd9e600c548260405161224e929190614c10565b6000818310613d8457816134f6565b5090919050565b600b54600c546000908152601d6020526040902054014211156126d2576126d2613cfc565b60008184841115613dd45760405162461bcd60e51b81526004016109109190614879565b505050900390565b60008183613dfd5760405162461bcd60e51b81526004016109109190614879565b506000838581613e0957fe5b0495945050505050565b613e1b613f31565b60005b6005811015610ebe578060050283901c601f16828260040360058110613e4057fe5b6020020152600101613e1e565b6000828152601a602052604081205480613e7b5750506000828152601a602052604090208190556001610a65565b62015180613e898483613564565b1115610a5f57613ea0620151806129ed8584613564565b6000858152601a602052604090208054620151809290920290910190555060019050610a65565b600c546000908152601e602052604090208054820190556005546001600160a01b03166323b872dd613ef761237f565b30846040518463ffffffff1660e01b81526004016122f49392919061467e565b604051806040016040528060008152602001600081525090565b6040518060a001604052806005906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b604080518082019091526000808252602082015290565b8051610a6581614d12565b60008083601f840112613fce578081fd5b5081356001600160401b03811115613fe4578182fd5b6020830191508360208083028501011115613ffe57600080fd5b9250929050565b600082601f830112614015578081fd5b61401f6040614cb1565b905080828460408501111561403357600080fd5b60005b6002811015614055578151835260209283019290910190600101614036565b50505092915050565b8060a08101831015610a6557600080fd5b600060208284031215614080578081fd5b81356134f681614d12565b60006020828403121561409c578081fd5b81516134f681614d12565b600080600080600080600080610100898b0312156140c3578384fd5b88356140ce81614d12565b975060208901356140de81614d12565b965060408901356140ee81614d12565b955060608901356140fe81614d12565b9450608089013561410e81614d12565b935060a089013561411e81614d12565b925060c089013561412e81614d12565b915060e089013561413e81614d12565b809150509295985092959890939650565b60008060008060008060a08789031215614167578182fd5b863561417281614d12565b9550602087013561418281614d12565b9450604087013593506060870135925060808701356001600160401b03808211156141ab578384fd5b818901915089601f8301126141be578384fd5b8135818111156141cc578485fd5b8a60208285010111156141dd578485fd5b6020830194508093505050509295509295509295565b60008060408385031215614205578182fd5b823561421081614d12565b946020939093013593505050565b60008060008060408587031215614233578384fd5b84356001600160401b0380821115614249578586fd5b61425588838901613fbd565b9096509450602087013591508082111561426d578384fd5b5061427a87828801613fbd565b95989497509550505050565b600060a08284031215614297578081fd5b6134f6838361405e565b600080602083850312156142b3578182fd5b82356001600160401b038111156142c8578283fd5b6142d485828601613fbd565b90969095509350505050565b6000602082840312156142f1578081fd5b81356134f681614d2a565b60006020828403121561430d578081fd5b81516134f681614d2a565b600060208284031215614329578081fd5b5035919050565b600060208284031215614341578081fd5b5051919050565b6000806040838503121561435a578182fd5b82359150602083013561436c81614d12565b809150509250929050565b6000806000806000610120868803121561438f578283fd5b85519450602087603f8801126143a3578384fd5b60026143b66143b182614cd7565b614cb1565b80838a0160608b018c8111156143ca578889fd5b885b858110156143f0576143de8e84613fb2565b855293860193918601916001016143cc565b508299506143fe8d82614005565b98505050505050506144138760a08801614005565b91506144228760e08801614005565b90509295509295909350565b60008060c08385031215614440578182fd5b82359150614451846020850161405e565b90509250929050565b6000806040838503121561446c578182fd5b823591506020808401356001600160401b03811115614489578283fd5b8401601f81018613614499578283fd5b80356144a76143b182614cf3565b81815283810190838501858402850186018a10156144c3578687fd5b8694505b838510156144e55780358352600194909401939185019185016144c7565b5080955050505050509250929050565b60008060408385031215614507578182fd5b82359150602083013561436c81614d2a565b6000806040838503121561452b578182fd5b50508035926020909101359150565b6000806040838503121561454c578182fd5b505080516020909101519092909150565b60006020828403121561456e578081fd5b81516001600160401b03811681146134f6578182fd5b8060005b60058110156145a7578151845260209384019390910190600101614588565b50505050565b6000815180845260208085019450808401835b838110156145dc578151875295820195908201906001016145c0565b509495945050505050565b60008151808452815b8181101561460c576020818501810151868301820152016145f0565b8181111561461d5782602083870101525b50601f01601f19169290920160200192915050565b60609490941b6bffffffffffffffffffffffff1916845260148401929092526034830152605482015260740190565b90815260200190565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039390931683526020830191909152604082015260600190565b600060018060a01b03851682528360208301526060604083015261473b60608301846145e7565b95945050505050565b60a08101610a658284614584565b6040808252810183905260006001600160fb1b03841115614771578081fd5b6020840280866060850137808301905060608101828152606084830301602085015261479d81866145ad565b979650505050505050565b6000606082526147bb60608301866145ad565b82810360208401526147cd81866145ad565b905082810360408401526147e181856145ad565b9695505050505050565b901515815260200190565b9283526001600160a01b03919091166020830152604082015260600190565b9283526020830191909152604082015260600190565b9485526001600160401b0393909316602085015261ffff91909116604084015263ffffffff908116606084015216608082015260a00190565b6001600160e01b031991909116815260200190565b6000602082526134f660208301846145e7565b6020808252602c908201527f4a756e676c65416476656e747572653a204e6f7420616c6c6f77656420746f2060408201526b6d696e74206b6f6e6769756d60a01b606082015260800190565b6020808252601a908201527f4b6f6e67416476656e74757265733a20456d707479207465616d000000000000604082015260600190565b60208082526012908201527121b7b6b6b4ba3a34b7339034b99037bb32b960711b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252602c908201527f4a756e676c65416476656e747572653a204e6f7420616c6c6f77656420746f2060408201526b6275726e206b6f6e6769756d60a01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600790820152662ab9b2902b292360c91b604082015260600190565b6020808252600d908201526c2237b713ba103ab9b2902b292360991b604082015260600190565b602080825260079082015266085c185d5cd95960ca1b604082015260600190565b60208082526010908201526f11d85b59481b9bdd081cdd185c9d195960821b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526006908201526566757475726560d01b604082015260600190565b6020808252600c908201526b10b1b7b7b93234b730ba37b960a11b604082015260600190565b602080825260079082015266042d8cadccee8d60cb1b604082015260600190565b60208082526025908201527f4a756e676c65416476656e747572653a20496e64657820646f6573206e6f7420604082015264195e1a5cdd60da1b606082015260800190565b6020808252601d908201527f4a756e676c65416476656e747572653a207465616d206e6f7420736574000000604082015260600190565b60208082526006908201526510b7bbb732b960d11b604082015260600190565b918252602082015260400190565b8481526020810184905260408101839052610100810161473b6060830184614584565b6001600160401b0391909116815260200190565b6001600160401b039290921682526001600160a01b0316602082015260400190565b6001600160401b0395909516855263ffffffff938416602086015261ffff9290921660408501529091166060830152608082015260a00190565b6040518181016001600160401b0381118282101715614ccf57600080fd5b604052919050565b60006001600160401b03821115614cec578081fd5b5060200290565b60006001600160401b03821115614d08578081fd5b5060209081020190565b6001600160a01b0381168114614d2757600080fd5b50565b8015158114614d2757600080fdfe6b446311b91ce49327a43ee3d0f0361dbfae79e9b9af3f89d0d8420676a1abb0d7fe74ba2795604f471717a6182ac81070ad95ecee0b7d8ebcfbec785af7e796a26469706673582212202c60775dca0a6daaa5a441974e0dbc675bf751ff006642807d7d0596cfc9a7a064736f6c634300060c00330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _nanas (address): 0x0000000000000000000000000000000000000000
Arg [1] : _vx (address): 0x0000000000000000000000000000000000000000
Arg [2] : _charms (address): 0x0000000000000000000000000000000000000000
Arg [3] : _logic (address): 0x0000000000000000000000000000000000000000
Arg [4] : _extra (address): 0x0000000000000000000000000000000000000000
Arg [5] : _vrfCoordinator (address): 0x0000000000000000000000000000000000000000
Arg [6] : _link (address): 0x0000000000000000000000000000000000000000

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000000


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.