GPTLens / data_full /CVE_clean /2018-12885.sol
Aishwarya Solanki
initial commit
ee7776a
pragma solidity 0.4.23;
library SafeMath {
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
contract Ownable {
address internal contractOwner;
constructor () internal {
if(contractOwner == address(0)){
contractOwner = msg.sender;
}
}
modifier onlyOwner() {
require(msg.sender == contractOwner);
_;
}
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
contractOwner = newOwner;
}
}
contract Pausable is Ownable {
bool private paused = false;
modifier whenNotPaused() {
if(paused == true && msg.value > 0){
msg.sender.transfer(msg.value);
}
require(!paused);
_;
}
function triggerPause() onlyOwner external {
paused = !paused;
}
}
contract ChampFactory is Pausable{
event NewChamp(uint256 champID, address owner);
using SafeMath for uint;
struct Champ {
uint256 id;
uint256 attackPower;
uint256 defencePower;
uint256 cooldownTime;
uint256 readyTime;
uint256 winCount;
uint256 lossCount;
uint256 position;
uint256 price;
uint256 withdrawCooldown;
uint256 eq_sword;
uint256 eq_shield;
uint256 eq_helmet;
bool forSale;
}
struct AddressInfo {
uint256 withdrawal;
uint256 champsCount;
uint256 itemsCount;
string name;
}
struct Item {
uint8 itemType;
uint8 itemRarity;
uint256 attackPower;
uint256 defencePower;
uint256 cooldownReduction;
uint256 price;
uint256 onChampId;
bool onChamp;
bool forSale;
}
mapping (address => AddressInfo) public addressInfo;
mapping (uint256 => address) public champToOwner;
mapping (uint256 => address) public itemToOwner;
mapping (uint256 => string) public champToName;
Champ[] public champs;
Item[] public items;
uint256[] public leaderboard;
uint256 internal createChampFee = 5 finney;
uint256 internal lootboxFee = 5 finney;
uint256 internal pendingWithdrawal = 0;
uint256 private randNonce = 0;
uint256 public champsForSaleCount;
uint256 public itemsForSaleCount;
modifier onlyOwnerOfChamp(uint256 _champId) {
require(msg.sender == champToOwner[_champId]);
_;
}
modifier onlyNotOwnerOfChamp(uint256 _champId) {
require(msg.sender != champToOwner[_champId]);
_;
}
modifier isPaid(uint256 _price){
require(msg.value >= _price);
_;
}
modifier contractMinBalanceReached(){
require( (address(this).balance).sub(pendingWithdrawal) > 1000000 );
_;
}
modifier isChampWithdrawReady(uint256 _id){
require(champs[_id].withdrawCooldown < block.timestamp);
_;
}
modifier distributeInput(address _affiliateAddress){
uint256 contractOwnerWithdrawal = (msg.value / 100) * 50;
addressInfo[contractOwner].withdrawal += contractOwnerWithdrawal;
pendingWithdrawal += contractOwnerWithdrawal;
if(_affiliateAddress != address(0) && _affiliateAddress != msg.sender){
uint256 affiliateBonus = (msg.value / 100) * 25;
addressInfo[_affiliateAddress].withdrawal += affiliateBonus;
pendingWithdrawal += affiliateBonus;
}
_;
}
function getChampsByOwner(address _owner) external view returns(uint256[]) {
uint256[] memory result = new uint256[](addressInfo[_owner].champsCount);
uint256 counter = 0;
for (uint256 i = 0; i < champs.length; i++) {
if (champToOwner[i] == _owner) {
result[counter] = i;
counter++;
}
}
return result;
}
function getChampsCount() external view returns(uint256){
return champs.length;
}
function getChampReward(uint256 _position) public view returns(uint256) {
if(_position <= 800){
uint256 rewardPercentage = uint256(2000).sub(2 * (_position - 1));
uint256 availableWithdrawal = address(this).balance.sub(pendingWithdrawal);
return availableWithdrawal / 1000000 * rewardPercentage;
}else{
return uint256(0);
}
}
function randMod(uint256 _modulus) internal returns(uint256) {
randNonce++;
return uint256(keccak256(randNonce, blockhash(block.number - 1))) % _modulus;
}
function createChamp(address _affiliateAddress) external payable
whenNotPaused
isPaid(createChampFee)
distributeInput(_affiliateAddress)
{
uint256 id = champs.push(Champ(0, 2 + randMod(4), 1 + randMod(4), uint256(1 days) - uint256(randMod(9) * 1 hours), 0, 0, 0, leaderboard.length + 1, 0, uint256(block.timestamp), 0,0,0, false)) - 1;
champs[id].id = id;
leaderboard.push(id);
champToOwner[id] = msg.sender;
addressInfo[msg.sender].champsCount++;
emit NewChamp(id, msg.sender);
}
function setCreateChampFee(uint256 _fee) external onlyOwner {
createChampFee = _fee;
}
function changeChampsName(uint _champId, string _name) external
onlyOwnerOfChamp(_champId){
champToName[_champId] = _name;
}
function changePlayersName(string _name) external {
addressInfo[msg.sender].name = _name;
}
function withdrawChamp(uint _id) external
onlyOwnerOfChamp(_id)
contractMinBalanceReached
isChampWithdrawReady(_id)
whenNotPaused {
Champ storage champ = champs[_id];
require(champ.position <= 800);
champ.withdrawCooldown = block.timestamp + 1 days;
uint256 withdrawal = getChampReward(champ.position);
addressInfo[msg.sender].withdrawal += withdrawal;
pendingWithdrawal += withdrawal;
}
function withdrawToAddress(address _address) external
whenNotPaused {
address playerAddress = _address;
if(playerAddress == address(0)){ playerAddress = msg.sender; }
uint256 share = addressInfo[playerAddress].withdrawal;
require(share > 0);
addressInfo[playerAddress].withdrawal = 0;
pendingWithdrawal = pendingWithdrawal.sub(share);
playerAddress.transfer(share);
}
}
contract Items is ChampFactory {
event NewItem(uint256 itemID, address owner);
constructor () internal {
items.push(Item(0, 0, 0, 0, 0, 0, 0, false, false));
}
modifier onlyOwnerOfItem(uint256 _itemId) {
require(_itemId != 0);
require(msg.sender == itemToOwner[_itemId]);
_;
}
modifier onlyNotOwnerOfItem(uint256 _itemId) {
require(msg.sender != itemToOwner[_itemId]);
_;
}
function hasChampSomethingOn(uint _champId, uint8 _type) internal view returns(bool){
Champ storage champ = champs[_champId];
if(_type == 1){
return (champ.eq_sword == 0) ? false : true;
}
if(_type == 2){
return (champ.eq_shield == 0) ? false : true;
}
if(_type == 3){
return (champ.eq_helmet == 0) ? false : true;
}
}
function getItemsByOwner(address _owner) external view returns(uint256[]) {
uint256[] memory result = new uint256[](addressInfo[_owner].itemsCount);
uint256 counter = 0;
for (uint256 i = 0; i < items.length; i++) {
if (itemToOwner[i] == _owner) {
result[counter] = i;
counter++;
}
}
return result;
}
function takeOffItem(uint _champId, uint8 _type) public
onlyOwnerOfChamp(_champId) {
uint256 itemId;
Champ storage champ = champs[_champId];
if(_type == 1){
itemId = champ.eq_sword;
if (itemId > 0) {
champ.eq_sword = 0;
}
}
if(_type == 2){
itemId = champ.eq_shield;
if(itemId > 0) {
champ.eq_shield = 0;
}
}
if(_type == 3){
itemId = champ.eq_helmet;
if(itemId > 0) {
champ.eq_helmet = 0;
}
}
if(itemId > 0){
items[itemId].onChamp = false;
}
}
function putOn(uint256 _champId, uint256 _itemId) external
onlyOwnerOfChamp(_champId)
onlyOwnerOfItem(_itemId) {
Champ storage champ = champs[_champId];
Item storage item = items[_itemId];
if(item.onChamp){
takeOffItem(item.onChampId, item.itemType);
}
item.onChamp = true;
item.onChampId = _champId;
if(item.itemType == 1){
if(champ.eq_sword > 0){
takeOffItem(champ.id, 1);
}
champ.eq_sword = _itemId;
}
if(item.itemType == 2){
if(champ.eq_shield > 0){
takeOffItem(champ.id, 2);
}
champ.eq_shield = _itemId;
}
if(item.itemType == 3){
if(champ.eq_helmet > 0){
takeOffItem(champ.id, 3);
}
champ.eq_helmet = _itemId;
}
}
function openLootbox(address _affiliateAddress) external payable
whenNotPaused
isPaid(lootboxFee)
distributeInput(_affiliateAddress) {
uint256 pointToCooldownReduction;
uint256 randNum = randMod(1001);
uint256 pointsToShare;
uint256 itemID;
Item memory item = Item({
itemType: uint8(uint256(randMod(3) + 1)),
itemRarity: uint8(0),
attackPower: 0,
defencePower: 0,
cooldownReduction: 0,
price: 0,
onChampId: 0,
onChamp: false,
forSale: false
});
if(450 > randNum){
pointsToShare = 25 + randMod(9);
item.itemRarity = uint8(1);
}else if(720 > randNum){
pointsToShare = 42 + randMod(17);
item.itemRarity = uint8(2);
}else if(910 > randNum){
pointsToShare = 71 + randMod(25);
item.itemRarity = uint8(3);
}else if(980 > randNum){
pointsToShare = 119 + randMod(33);
item.itemRarity = uint8(4);
}else{
pointsToShare = 235 + randMod(41);
item.itemRarity = uint8(5);
}
if(item.itemType == uint8(1)){
item.attackPower = pointsToShare / 10 * 7;
pointsToShare -= item.attackPower;
item.defencePower = pointsToShare / 10 * randMod(6);
pointsToShare -= item.defencePower;
item.cooldownReduction = pointsToShare * uint256(1 minutes);
item.itemType = uint8(1);
}
if(item.itemType == uint8(2)){
item.defencePower = pointsToShare / 10 * 7;
pointsToShare -= item.defencePower;
item.attackPower = pointsToShare / 10 * randMod(6);
pointsToShare -= item.attackPower;
item.cooldownReduction = pointsToShare * uint256(1 minutes);
item.itemType = uint8(2);
}
if(item.itemType == uint8(3)){
pointToCooldownReduction = pointsToShare / 10 * 7;
item.cooldownReduction = pointToCooldownReduction * uint256(1 minutes);
pointsToShare -= pointToCooldownReduction;
item.attackPower = pointsToShare / 10 * randMod(6);
pointsToShare -= item.attackPower;
item.defencePower = pointsToShare;
item.itemType = uint8(3);
}
itemID = items.push(item) - 1;
itemToOwner[itemID] = msg.sender;
addressInfo[msg.sender].itemsCount++;
emit NewItem(itemID, msg.sender);
}
function setLootboxFee(uint _fee) external onlyOwner {
lootboxFee = _fee;
}
}
contract ItemMarket is Items {
event TransferItem(address from, address to, uint256 itemID);
modifier itemIsForSale(uint256 _id){
require(items[_id].forSale);
_;
}
modifier itemIsNotForSale(uint256 _id){
require(items[_id].forSale == false);
_;
}
modifier ifItemForSaleThenCancelSale(uint256 _itemID){
Item storage item = items[_itemID];
if(item.forSale){
_cancelItemSale(item);
}
_;
}
modifier distributeSaleInput(address _owner) {
uint256 contractOwnerCommision;
uint256 playerShare;
if(msg.value > 100){
contractOwnerCommision = (msg.value / 100);
playerShare = msg.value - contractOwnerCommision;
}else{
contractOwnerCommision = 0;
playerShare = msg.value;
}
addressInfo[_owner].withdrawal += playerShare;
addressInfo[contractOwner].withdrawal += contractOwnerCommision;
pendingWithdrawal += playerShare + contractOwnerCommision;
_;
}
function getItemsForSale() view external returns(uint256[]){
uint256[] memory result = new uint256[](itemsForSaleCount);
if(itemsForSaleCount > 0){
uint256 counter = 0;
for (uint256 i = 0; i < items.length; i++) {
if (items[i].forSale == true) {
result[counter]=i;
counter++;
}
}
}
return result;
}
function _cancelItemSale(Item storage item) private {
item.forSale = false;
itemsForSaleCount--;
}
function transferItem(address _from, address _to, uint256 _itemID) internal
ifItemForSaleThenCancelSale(_itemID) {
Item storage item = items[_itemID];
if(item.onChamp && _to != champToOwner[item.onChampId]){
takeOffItem(item.onChampId, item.itemType);
}
addressInfo[_to].itemsCount++;
addressInfo[_from].itemsCount--;
itemToOwner[_itemID] = _to;
emit TransferItem(_from, _to, _itemID);
}
function giveItem(address _to, uint256 _itemID) public
onlyOwnerOfItem(_itemID) {
transferItem(msg.sender, _to, _itemID);
}
function cancelItemSale(uint256 _id) public
itemIsForSale(_id)
onlyOwnerOfItem(_id){
Item storage item = items[_id];
_cancelItemSale(item);
}
function setItemForSale(uint256 _id, uint256 _price) external
onlyOwnerOfItem(_id)
itemIsNotForSale(_id) {
Item storage item = items[_id];
item.forSale = true;
item.price = _price;
itemsForSaleCount++;
}
function buyItem(uint256 _id) external payable
whenNotPaused
onlyNotOwnerOfItem(_id)
itemIsForSale(_id)
isPaid(items[_id].price)
distributeSaleInput(itemToOwner[_id])
{
transferItem(itemToOwner[_id], msg.sender, _id);
}
}
contract ItemForge is ItemMarket {
event Forge(uint256 forgedItemID);
function forgeItems(uint256 _parentItemID, uint256 _childItemID) external
onlyOwnerOfItem(_parentItemID)
onlyOwnerOfItem(_childItemID)
ifItemForSaleThenCancelSale(_parentItemID)
ifItemForSaleThenCancelSale(_childItemID) {
require(_parentItemID != _childItemID);
Item storage parentItem = items[_parentItemID];
Item storage childItem = items[_childItemID];
if(childItem.onChamp){
takeOffItem(childItem.onChampId, childItem.itemType);
}
parentItem.attackPower = (parentItem.attackPower > childItem.attackPower) ? parentItem.attackPower : childItem.attackPower;
parentItem.defencePower = (parentItem.defencePower > childItem.defencePower) ? parentItem.defencePower : childItem.defencePower;
parentItem.cooldownReduction = (parentItem.cooldownReduction > childItem.cooldownReduction) ? parentItem.cooldownReduction : childItem.cooldownReduction;
parentItem.itemRarity = uint8(6);
transferItem(msg.sender, address(0), _childItemID);
emit Forge(_parentItemID);
}
}
contract ChampAttack is ItemForge {
event Attack(uint256 winnerChampID, uint256 defeatedChampID, bool didAttackerWin);
modifier isChampReady(uint256 _champId) {
require (champs[_champId].readyTime <= block.timestamp);
_;
}
modifier notSelfAttack(uint256 _champId, uint256 _targetId) {
require(_champId != _targetId);
_;
}
modifier targetExists(uint256 _targetId){
require(champToOwner[_targetId] != address(0));
_;
}
function getChampStats(uint256 _champId) public view returns(uint256,uint256,uint256){
Champ storage champ = champs[_champId];
Item storage sword = items[champ.eq_sword];
Item storage shield = items[champ.eq_shield];
Item storage helmet = items[champ.eq_helmet];
uint256 totalAttackPower = champ.attackPower + sword.attackPower + shield.attackPower + helmet.attackPower;
uint256 totalDefencePower = champ.defencePower + sword.defencePower + shield.defencePower + helmet.defencePower;
uint256 totalCooldownReduction = sword.cooldownReduction + shield.cooldownReduction + helmet.cooldownReduction;
return (totalAttackPower, totalDefencePower, totalCooldownReduction);
}
function subAttack(uint256 _playerAttackPoints, uint256 _x) internal pure returns (uint256) {
return (_playerAttackPoints <= _x + 2) ? 2 : _playerAttackPoints - _x;
}
function subDefence(uint256 _playerDefencePoints, uint256 _x) internal pure returns (uint256) {
return (_playerDefencePoints <= _x) ? 1 : _playerDefencePoints - _x;
}
function _attackCompleted(Champ storage _winnerChamp, Champ storage _defeatedChamp, uint256 _pointsGiven, uint256 _pointsToAttackPower) private {
_winnerChamp.attackPower += _pointsToAttackPower;
_winnerChamp.defencePower += _pointsGiven - _pointsToAttackPower;
_defeatedChamp.attackPower = subAttack(_defeatedChamp.attackPower, _pointsToAttackPower);
_defeatedChamp.defencePower = subDefence(_defeatedChamp.defencePower, _pointsGiven - _pointsToAttackPower);
_winnerChamp.winCount++;
_defeatedChamp.lossCount++;
if(_winnerChamp.position > _defeatedChamp.position) {
uint256 winnerPosition = _winnerChamp.position;
uint256 loserPosition = _defeatedChamp.position;
_defeatedChamp.position = winnerPosition;
_winnerChamp.position = loserPosition;
leaderboard[winnerPosition - 1] = _defeatedChamp.id;
leaderboard[loserPosition - 1] = _winnerChamp.id;
}
}
function _getPoints(uint256 _pointsGiven) private returns (uint256 pointsGiven, uint256 pointsToAttackPower){
return (_pointsGiven, randMod(_pointsGiven+1));
}
function attack(uint256 _champId, uint256 _targetId) external
onlyOwnerOfChamp(_champId)
isChampReady(_champId)
notSelfAttack(_champId, _targetId)
targetExists(_targetId) {
Champ storage myChamp = champs[_champId];
Champ storage enemyChamp = champs[_targetId];
uint256 pointsGiven;
uint256 pointsToAttackPower;
uint256 myChampAttackPower;
uint256 enemyChampDefencePower;
uint256 myChampCooldownReduction;
(myChampAttackPower,,myChampCooldownReduction) = getChampStats(_champId);
(,enemyChampDefencePower,) = getChampStats(_targetId);
if (myChampAttackPower > enemyChampDefencePower) {
if(myChampAttackPower - enemyChampDefencePower < 5){
(pointsGiven, pointsToAttackPower) = _getPoints(3);
}else if(myChampAttackPower - enemyChampDefencePower < 10){
(pointsGiven, pointsToAttackPower) = _getPoints(2);
}else{
(pointsGiven, pointsToAttackPower) = _getPoints(1);
}
_attackCompleted(myChamp, enemyChamp, pointsGiven, pointsToAttackPower);
emit Attack(myChamp.id, enemyChamp.id, true);
} else {
(pointsGiven, pointsToAttackPower) = _getPoints(1);
_attackCompleted(enemyChamp, myChamp, pointsGiven, pointsToAttackPower);
emit Attack(enemyChamp.id, myChamp.id, false);
}
myChamp.readyTime = uint256(block.timestamp + myChamp.cooldownTime - myChampCooldownReduction);
}
}
contract ChampMarket is ChampAttack {
event TransferChamp(address from, address to, uint256 champID);
modifier champIsForSale(uint256 _id){
require(champs[_id].forSale);
_;
}
modifier champIsNotForSale(uint256 _id){
require(champs[_id].forSale == false);
_;
}
modifier ifChampForSaleThenCancelSale(uint256 _champID){
Champ storage champ = champs[_champID];
if(champ.forSale){
_cancelChampSale(champ);
}
_;
}
function getChampsForSale() view external returns(uint256[]){
uint256[] memory result = new uint256[](champsForSaleCount);
if(champsForSaleCount > 0){
uint256 counter = 0;
for (uint256 i = 0; i < champs.length; i++) {
if (champs[i].forSale == true) {
result[counter]=i;
counter++;
}
}
}
return result;
}
function _cancelChampSale(Champ storage champ) private {
champ.forSale = false;
champsForSaleCount--;
}
function transferChamp(address _from, address _to, uint256 _champId) internal ifChampForSaleThenCancelSale(_champId){
Champ storage champ = champs[_champId];
addressInfo[_to].champsCount++;
addressInfo[_from].champsCount--;
champToOwner[_champId] = _to;
if(champ.eq_sword != 0) { transferItem(_from, _to, champ.eq_sword); }
if(champ.eq_shield != 0) { transferItem(_from, _to, champ.eq_shield); }
if(champ.eq_helmet != 0) { transferItem(_from, _to, champ.eq_helmet); }
emit TransferChamp(_from, _to, _champId);
}
function cancelChampSale(uint256 _id) public
champIsForSale(_id)
onlyOwnerOfChamp(_id) {
Champ storage champ = champs[_id];
_cancelChampSale(champ);
}
function giveChamp(address _to, uint256 _champId) external
onlyOwnerOfChamp(_champId) {
transferChamp(msg.sender, _to, _champId);
}
function setChampForSale(uint256 _id, uint256 _price) external
onlyOwnerOfChamp(_id)
champIsNotForSale(_id) {
Champ storage champ = champs[_id];
champ.forSale = true;
champ.price = _price;
champsForSaleCount++;
}
function buyChamp(uint256 _id) external payable
whenNotPaused
onlyNotOwnerOfChamp(_id)
champIsForSale(_id)
isPaid(champs[_id].price)
distributeSaleInput(champToOwner[_id]) {
transferChamp(champToOwner[_id], msg.sender, _id);
}
}
contract MyCryptoChampCore is ChampMarket {
}