├── .gitignore ├── BattleHeroBreeder.sol ├── BattleHeroBurnWallet.sol ├── BattleHeroChestShop.sol ├── BattleHeroMarketplace.sol ├── BattleHeroPE.sol ├── BattleHeroStaker.sol ├── BattleHeroStarterPack.sol ├── BattleHeroTrainer.sol ├── BattleHeroUpgrader.sol ├── README.md ├── deployed ├── BattleHero.sol ├── BattleHeroFactory.sol └── BattleHeroRewardWallet.sol └── shared ├── BattleHeroData.sol ├── DateTime.sol ├── IBattleHero.sol ├── IBattleHeroAirdrop.sol ├── IBattleHeroBreeder.sol ├── IBattleHeroFactory.sol ├── IBattleHeroGenScience.sol ├── IBattleHeroPE.sol ├── IBattleHeroRewardWallet.sol └── Whitelist.sol /.gitignore: -------------------------------------------------------------------------------- 1 | BattleHeroGenScience.sol 2 | BattleHeroCrafter.sol 3 | BattleHeroPrivateSaleWallet.sol 4 | BattleHeroCoinMigration.sol 5 | BattleHeroFaucet.sol 6 | testnet -------------------------------------------------------------------------------- /BattleHeroBreeder.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.9; 3 | import "../node_modules/@openzeppelin/contracts/utils/Strings.sol"; 4 | import "../node_modules/@openzeppelin/contracts/access/AccessControlEnumerable.sol"; 5 | import "./shared/IBattleHeroFactory.sol"; 6 | import "./shared/IBattleHero.sol"; 7 | import "./shared/IBattleHeroGenScience.sol"; 8 | 9 | 10 | contract BattleHeroBreeder is 11 | AccessControlEnumerable { 12 | 13 | bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); 14 | bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); 15 | bytes32 public constant BREED_ROLE = keccak256("BREED_ROLE"); 16 | 17 | IBattleHeroGenScience _genScience; 18 | IBattleHeroFactory _erc721factory; 19 | 20 | using Strings for uint256; 21 | 22 | constructor( 23 | address genScience, 24 | address erc721) { 25 | _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); 26 | _setupRole(BREED_ROLE, _msgSender()); 27 | setGenScience(genScience); 28 | setERC721Factory(erc721); 29 | } 30 | modifier isSetup() { 31 | require(address(_genScience) != address(0), "Setup not correctly"); 32 | require(address(_erc721factory) != address(0), "Setup not correctly"); 33 | _; 34 | } 35 | function setGenScience(address genScience) public{ 36 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender())); 37 | _genScience = IBattleHeroGenScience(genScience); 38 | } 39 | function setERC721Factory(address erc721) public{ 40 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender())); 41 | _erc721factory = IBattleHeroFactory(erc721); 42 | } 43 | function addBreeder(address breeder) public { 44 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "Invalid role for add breder"); 45 | _setupRole(BREED_ROLE, breeder); 46 | } 47 | function breed(address to, string memory gen) isSetup public returns(uint) { 48 | require(hasRole(BREED_ROLE, _msgSender()), "Invalid role for breed"); 49 | uint tokenId = _erc721factory.mint(to, gen); 50 | return tokenId; 51 | } 52 | function breedRandom() isSetup public returns (uint){ 53 | require(hasRole(BREED_ROLE, _msgSender()), "Invalid role for breed random"); 54 | string memory randomGen = _genScience.generate(); 55 | return breed(msg.sender, randomGen); 56 | } 57 | } -------------------------------------------------------------------------------- /BattleHeroBurnWallet.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.9; 3 | import "../node_modules/@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; 4 | import "../node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol"; 5 | import "./shared/IBattleHeroFactory.sol"; 6 | import "./shared/IBattleHero.sol"; 7 | import "./shared/IBattleHeroGenScience.sol"; 8 | import "./shared/IBattleHero.sol"; 9 | import "../node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; 10 | 11 | 12 | contract BattleHeroBurnWallet is 13 | AccessControlEnumerableUpgradeable { 14 | 15 | bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); 16 | 17 | function initialize() public initializer{ 18 | __AccessControlEnumerable_init(); 19 | _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); 20 | _setupRole(BURNER_ROLE, _msgSender()); 21 | } 22 | function setBurnerRole(address burner) public { 23 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender())); 24 | _setupRole(BURNER_ROLE, burner); 25 | } 26 | function burn(address token, uint256 amount) public virtual{ 27 | require(IBattleHero(token).balanceOf(address(this)) >= amount); 28 | require(hasRole(BURNER_ROLE, _msgSender())); 29 | IBattleHero(token).burn(amount); 30 | } 31 | } -------------------------------------------------------------------------------- /BattleHeroChestShop.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.9; 3 | import "./shared/IBattleHero.sol"; 4 | import "./shared/IBattleHeroGenScience.sol"; 5 | import "./shared/IBattleHeroBreeder.sol"; 6 | import "../node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol"; 7 | import "../node_modules/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol"; 8 | 9 | contract BattleHeroChestShop is ContextUpgradeable, AccessControlEnumerableUpgradeable { 10 | 11 | uint256 public CHARACTER_CHEST; 12 | uint256 public WEAPON_CHEST; 13 | uint256 public MIX_CHEST; 14 | 15 | using SafeMathUpgradeable for uint256; 16 | 17 | mapping(address => mapping(uint256 => uint256)) _balances; 18 | mapping(uint256 => uint256) _prices; 19 | 20 | IBattleHero _battleHero; 21 | IBattleHeroBreeder _battleHeroBreeder; 22 | IBattleHeroGenScience _battleHeroGenScience; 23 | 24 | address _battleHeroBurnWallet; 25 | 26 | event ChestPurchased(address who, uint256 chestId, uint256 when); 27 | event ChestOpened(address who, uint256 chestId, uint256[] tokenIds, uint256 when); 28 | 29 | function initialize( 30 | address _battleHeroContractAddress, 31 | address _battleHeroBreederContractAddress, 32 | address _battleHeroGenScienceContractAddress, 33 | address _battleHeroBurnWalletAddress 34 | ) public initializer { 35 | 36 | __Context_init(); 37 | __AccessControlEnumerable_init(); 38 | 39 | _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); 40 | 41 | CHARACTER_CHEST = 0; 42 | WEAPON_CHEST = 1; 43 | MIX_CHEST = 2; 44 | 45 | setBattleHero(_battleHeroContractAddress); 46 | setBattleHeroBreeder(_battleHeroBreederContractAddress); 47 | setBattleHeroGenScience(_battleHeroGenScienceContractAddress); 48 | 49 | _battleHeroBurnWallet = _battleHeroBurnWalletAddress; 50 | _prices[CHARACTER_CHEST] = 900 ether; 51 | _prices[WEAPON_CHEST] = 900 ether; 52 | _prices[MIX_CHEST] = 1440 ether; 53 | } 54 | 55 | function setBattleHero(address _battleHeroContractAddress) public { 56 | _battleHero = IBattleHero(_battleHeroContractAddress); 57 | } 58 | 59 | function setBattleHeroBreeder(address _battleHeroBreederContractAddress) public { 60 | _battleHeroBreeder = IBattleHeroBreeder(_battleHeroBreederContractAddress); 61 | } 62 | 63 | function setBattleHeroGenScience(address _battleHeroGenScienceContractAddress) public { 64 | _battleHeroGenScience = IBattleHeroGenScience(_battleHeroGenScienceContractAddress); 65 | } 66 | 67 | function balanceOf(address owner, uint256 chestId) public view returns(uint256){ 68 | return _balances[owner][chestId]; 69 | } 70 | function purchase(uint256 _chestId) public virtual{ 71 | uint256 _amount = 1; 72 | uint256 _calculatedPrice = _prices[_chestId] * _amount; 73 | require(_battleHero.balanceOf(msg.sender) >= _calculatedPrice, "Insufficient balance"); 74 | require(_battleHero.allowance(msg.sender, address(this)) >= _calculatedPrice, "Insufficient allowance"); 75 | _balances[msg.sender][_chestId] = _balances[msg.sender][_chestId].add(_amount); 76 | _battleHero.transferFrom(msg.sender, _battleHeroBurnWallet, _calculatedPrice); 77 | emit ChestPurchased(msg.sender, _chestId, block.timestamp); 78 | } 79 | function purchase(uint256 _chestId, uint256 _amount) public virtual{ 80 | uint256 _calculatedPrice = _prices[_chestId] * _amount; 81 | require(_battleHero.balanceOf(msg.sender) >= _calculatedPrice, "Insufficient balance"); 82 | require(_battleHero.allowance(msg.sender, address(this)) >= _calculatedPrice, "Insufficient allowance"); 83 | _balances[msg.sender][_chestId] = _balances[msg.sender][_chestId].add(_amount); 84 | _battleHero.transferFrom(msg.sender, _battleHeroBurnWallet, _calculatedPrice); 85 | emit ChestPurchased(msg.sender, _chestId, block.timestamp); 86 | } 87 | function open(uint256 _chestId) public virtual{ 88 | require(_balances[msg.sender][_chestId] >= 1, "You should to buy more chests"); 89 | _openChest(_chestId); 90 | } 91 | function open(uint256 _chestId, uint256 _amount) public virtual{ 92 | require(_balances[msg.sender][_chestId] >= _amount, "You should to buy more chests"); 93 | for(uint i = 0; i < _amount; i++){ 94 | _openChest(_chestId); 95 | } 96 | } 97 | 98 | function _openChest(uint256 _chestId) internal { 99 | uint256[] memory _tokenIds = new uint256[](2); 100 | if(_chestId == 0){ 101 | string memory _genCharacter = _battleHeroGenScience.generateCharacter(); 102 | uint256 _characterId = _battleHeroBreeder.breed(msg.sender, _genCharacter); 103 | _tokenIds[0] = _characterId; 104 | } 105 | if(_chestId == 1){ 106 | string memory _genWeapon = _battleHeroGenScience.generateWeapon(); 107 | uint256 _weaponId = _battleHeroBreeder.breed(msg.sender, _genWeapon); 108 | _tokenIds[1] = _weaponId; 109 | } 110 | if(_chestId == 2){ 111 | string memory _genCharacter = _battleHeroGenScience.generateCharacter(); 112 | string memory _genWeapon = _battleHeroGenScience.generateWeapon(); 113 | uint256 _characterId = _battleHeroBreeder.breed(msg.sender, _genCharacter); 114 | uint256 _weaponId = _battleHeroBreeder.breed(msg.sender, _genWeapon); 115 | _tokenIds[0] = _characterId; 116 | _tokenIds[1] = _weaponId; 117 | } 118 | _balances[msg.sender][_chestId] = _balances[msg.sender][_chestId].sub(1); 119 | emit ChestOpened(msg.sender, _chestId, _tokenIds, block.timestamp); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /BattleHeroMarketplace.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.9; 3 | 4 | import "../node_modules/@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol"; 5 | import "../node_modules/@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol"; 6 | import "../node_modules/@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721PausableUpgradeable.sol"; 7 | import "../node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol"; 8 | import "../node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; 9 | import "../node_modules/@openzeppelin/contracts-upgradeable/utils/CountersUpgradeable.sol"; 10 | import "../node_modules/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol"; 11 | import "../node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; 12 | 13 | import "./shared/BattleHeroData.sol"; 14 | import "./shared/IBattleHeroFactory.sol"; 15 | import "./shared/IBattleHero.sol"; 16 | 17 | 18 | contract BattleHeroMarketplace is 19 | ContextUpgradeable, 20 | AccessControlEnumerableUpgradeable{ 21 | 22 | using CountersUpgradeable for CountersUpgradeable.Counter; 23 | using SafeMathUpgradeable for uint256; 24 | 25 | struct Auction{ 26 | uint256 heroId; 27 | uint256 price; 28 | uint256 auctionId; 29 | address auctioner; 30 | } 31 | 32 | IBattleHeroFactory _battleHeroFactory; 33 | IBattleHero _battleHero; 34 | 35 | mapping(uint256 => Auction) _auctions; 36 | mapping(uint256 => bool) _heroesInAuction; 37 | mapping(uint256 => uint256) _heroesAuctionId; 38 | 39 | CountersUpgradeable.Counter private _auctionTracker; 40 | 41 | address _owner; 42 | address _battleHeroBurnWallet; 43 | uint256 FEE; 44 | 45 | event AuctionCreated(address seller, uint256 heroId, uint256 price); 46 | event AuctionFinished(address buyer, address seller, uint256 heroId, uint256 price); 47 | 48 | address _battleHeroReserve; 49 | 50 | function initialize( 51 | address _battleHeroFactoryAddress, 52 | address _battleHeroAddress, 53 | address _battleHeroBurnWalletAddress, 54 | address _battleHeroReserveWallet 55 | ) public initializer { 56 | __Context_init(); 57 | __AccessControlEnumerable_init(); 58 | _owner = msg.sender; 59 | _battleHeroBurnWallet = _battleHeroBurnWalletAddress; 60 | FEE = 5; 61 | setBattleHeroFactory(_battleHeroFactoryAddress); 62 | setBattleHero(_battleHeroAddress); 63 | setBattleHeroReserve(_battleHeroReserveWallet); 64 | } 65 | function setBattleHeroReserve(address reserve) public { 66 | require(msg.sender == _owner); 67 | require(reserve != address(0)); 68 | _battleHeroReserve = reserve; 69 | } 70 | function setBattleHeroFactory(address battleHeroFactoryAddress) public { 71 | require(msg.sender == _owner); 72 | require(battleHeroFactoryAddress != address(0)); 73 | _battleHeroFactory = IBattleHeroFactory(battleHeroFactoryAddress); 74 | } 75 | function setBattleHero(address battleHeroAddress) public { 76 | require(msg.sender == _owner); 77 | require(battleHeroAddress != address(0)); 78 | _battleHero = IBattleHero(battleHeroAddress); 79 | } 80 | 81 | function setBattleHeroBurnWallet(address battleHeroBurnWalletAddress) public { 82 | require(msg.sender == _owner); 83 | require(battleHeroBurnWalletAddress != address(0)); 84 | _battleHeroBurnWallet = battleHeroBurnWalletAddress; 85 | } 86 | 87 | function createAuction( 88 | uint256 _heroId, 89 | uint256 _price 90 | ) public { 91 | require(!_heroesInAuction[_heroId], "Hero currently in auction"); 92 | require(!_battleHeroFactory.isLocked(_heroId), "Herro currently locked"); 93 | require(_battleHeroFactory.isApproved(address(this), _heroId), "Unnapproved hero"); 94 | require(_battleHeroFactory.ownerOf(_heroId) == msg.sender, "You are not owner"); 95 | require(_price > 0, "Invalid price"); 96 | uint256 _currentAuction = _auctionTracker.current(); 97 | _auctions[_currentAuction] = Auction(_heroId, _price, _currentAuction , msg.sender); 98 | _heroesAuctionId[_heroId] = _currentAuction; 99 | _heroesInAuction[_heroId] = true; 100 | _auctionTracker.increment(); 101 | _battleHeroFactory.lockHero(_heroId); 102 | emit AuctionCreated(msg.sender, _heroId, _price); 103 | } 104 | 105 | function purchase(uint256 _auctionId) public { 106 | Auction memory _auction = getAuction(_auctionId); 107 | address heroOwner = _battleHeroFactory.ownerOf(_auction.heroId); 108 | require(_battleHero.allowance(msg.sender, address(this)) >= _auction.price, "Insufficient allowance"); 109 | require(_battleHero.balanceOf(msg.sender) >= _auction.price, "Insufficient balance"); 110 | require(_battleHeroFactory.isApproved(address(this), _auction.heroId), "Unnapproved hero"); 111 | require(_battleHeroFactory.isLocked(_auction.heroId), "Herro currently not locked"); 112 | require(_heroesInAuction[_auction.heroId], "Hero currently not in auction"); 113 | require(heroOwner != msg.sender, "Owner can not buy his NFT"); 114 | _processPurchase(_auction); 115 | _removeAuction(_auctionId); 116 | emit AuctionFinished(msg.sender, heroOwner, _auction.heroId, _auction.price); 117 | } 118 | 119 | function isSelling(uint256 tokenId) public view returns(bool){ 120 | return _heroesInAuction[tokenId]; 121 | } 122 | 123 | function getAuction(uint256 _auctionId) public view returns(Auction memory){ 124 | return _auctions[_auctionId]; 125 | } 126 | 127 | function totalAuctions() public view returns(uint256){ 128 | return _auctionTracker.current(); 129 | } 130 | 131 | function auctionIdOfHero(uint256 _heroId) public view returns(uint256){ 132 | return _heroesAuctionId[_heroId]; 133 | } 134 | 135 | function cancelAuction(uint256 _auctionId) public { 136 | Auction memory _auction = getAuction(_auctionId); 137 | require(_battleHeroFactory.ownerOf(_auction.heroId) == msg.sender, "You are not owner"); 138 | require(_battleHeroFactory.isLocked(_auction.heroId), "Herro currently not locked"); 139 | require(_heroesInAuction[_auction.heroId], "Hero currently not in auction"); 140 | _removeAuction(_auctionId); 141 | } 142 | 143 | function _processPurchase(Auction memory _auction) private { 144 | uint256 _calculatedFee = _auction.price.mul(FEE).div(100); 145 | uint256 _reserveFee = _calculatedFee.mul(20).div(100); 146 | uint256 _burnFee = _calculatedFee.mul(80).div(100); 147 | _battleHeroFactory.unlockHero(_auction.heroId); 148 | require(!_battleHeroFactory.isLocked(_auction.heroId)); 149 | _battleHeroFactory.transferFrom(_auction.auctioner, msg.sender, _auction.heroId); 150 | _battleHero.transferFrom(msg.sender, _battleHeroBurnWallet, _burnFee); 151 | _battleHero.transferFrom(msg.sender, _battleHeroReserve, _reserveFee); 152 | _battleHero.transferFrom(msg.sender, _auction.auctioner, (_auction.price) - _calculatedFee); 153 | } 154 | 155 | function _removeAuction(uint256 _auctionId) private { 156 | // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and 157 | // then delete the last slot (swap and pop). 158 | Auction memory _auction = _auctions[_auctionId]; 159 | uint256 lastAuctionId = totalAuctions() - 1; 160 | _battleHeroFactory.unlockHero(_auction.heroId); 161 | // Si el ultimoID es igual al que queremos eliminar no hace falta el swap 162 | if(_auctionId != lastAuctionId){ 163 | Auction memory _gapAuction = _auctions[lastAuctionId]; 164 | _gapAuction.auctionId = _auctionId; 165 | _auctions[_auction.auctionId] = _gapAuction; 166 | _heroesAuctionId[_gapAuction.heroId] = _auction.auctionId; 167 | _auctions[lastAuctionId] = _auction; 168 | } 169 | 170 | delete _heroesAuctionId[_auction.heroId]; 171 | delete _heroesInAuction[_auction.heroId]; 172 | delete _auctions[lastAuctionId]; 173 | _auctionTracker.decrement(); 174 | } 175 | } -------------------------------------------------------------------------------- /BattleHeroPE.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.9; 3 | import "../node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; 4 | import "../node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol"; 5 | import "../node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; 6 | import "../node_modules/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol"; 7 | import "./shared/IBattleHeroRewardWallet.sol"; 8 | 9 | 10 | contract BattleHeroPE is ContextUpgradeable, AccessControlEnumerableUpgradeable{ 11 | 12 | bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); 13 | mapping(address => mapping(address => uint256)) private _allowances; 14 | 15 | using SafeMathUpgradeable for uint256; 16 | 17 | mapping(address => uint256) _balances; 18 | 19 | uint8 _decimals; 20 | uint256 _scale; 21 | uint256 _ratio; 22 | 23 | IBattleHeroRewardWallet _rewardWallet; 24 | 25 | event PEExchanged(address who, uint256 amount); 26 | 27 | function initialize( 28 | address _rewardWalletAddress 29 | ) public initializer { 30 | __Context_init(); 31 | __AccessControlEnumerable_init(); 32 | _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); 33 | _rewardWallet = IBattleHeroRewardWallet(_rewardWalletAddress); 34 | _decimals = 18; 35 | _scale = 1 * 10 ** _decimals; 36 | _ratio = 5; 37 | } 38 | 39 | function exchange(uint256 amount, address _token) public{ 40 | uint256 _balance = _balances[msg.sender]; 41 | require(_balance > 0, "You dont have balance to exchange"); 42 | require(_balance >= amount, "Amount excedeed balance"); 43 | uint256 _reward = _PEtoBath(_balance); 44 | _rewardWallet.distribute(_token, _reward, msg.sender); 45 | _balances[msg.sender] = _balances[msg.sender].sub(amount); 46 | emit PEExchanged(msg.sender, amount); 47 | } 48 | 49 | function balanceOf(address account) public view virtual returns (uint256) { 50 | return _balances[account]; 51 | } 52 | 53 | function approve(address spender, uint256 amount) public { 54 | _allowances[msg.sender][spender] += amount; 55 | } 56 | 57 | function setMinterRole(address minter) public { 58 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "Only admin can set a minter"); 59 | _setupRole(MINTER_ROLE, minter); 60 | } 61 | 62 | function mint(address to, uint256 amount) public{ 63 | require(hasRole(MINTER_ROLE, _msgSender()), "You dont have a minter role"); 64 | _balances[to] += amount; 65 | } 66 | function burnFrom(address from, uint256 amount) public{ 67 | require(_allowances[from][msg.sender] >= amount); 68 | burn(from, amount); 69 | } 70 | function burn(address to, uint256 amount) public { 71 | require(hasRole(MINTER_ROLE, _msgSender()), "You dont have a minter role"); 72 | _balances[to] -= amount; 73 | } 74 | 75 | function _PEtoBath(uint256 _pe) internal view returns(uint256){ 76 | return _pe.div(_ratio); 77 | } 78 | 79 | function scale(uint256 _peEther) public view returns(uint256){ 80 | return _peEther * _scale; 81 | } 82 | 83 | function changeRatio(uint256 _newRatio) public { 84 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "Only admin can change ratio"); 85 | require(_newRatio > 0); 86 | _ratio = _newRatio; 87 | } 88 | 89 | function changeRewardWallet(address _newRewardWallet) public { 90 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "Only admin can change reward wallet"); 91 | require(_newRewardWallet != address(0)); 92 | _rewardWallet = IBattleHeroRewardWallet(_newRewardWallet); 93 | } 94 | 95 | } -------------------------------------------------------------------------------- /BattleHeroStaker.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.9; 3 | 4 | import "../node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 5 | import "../node_modules/@openzeppelin/contracts/utils/math/SafeMath.sol"; 6 | import "../node_modules/@openzeppelin/contracts/utils/Context.sol"; 7 | import "./shared/IBattleHero.sol"; 8 | 9 | 10 | contract BattleHeroStaker is Context{ 11 | 12 | 13 | 14 | 15 | } -------------------------------------------------------------------------------- /BattleHeroStarterPack.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.9; 3 | 4 | import "../node_modules/@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; 5 | import "../node_modules/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol"; 6 | import "../node_modules/@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol"; 7 | import "./shared/IBattleHero.sol"; 8 | import "./shared/IBattleHeroGenScience.sol"; 9 | import "./shared/IBattleHeroBreeder.sol"; 10 | 11 | contract BattleHeroStarterPack is ContextUpgradeable, AccessControlEnumerableUpgradeable{ 12 | 13 | mapping(address => bool) _starterPackClaimed; 14 | 15 | bool _paused; 16 | 17 | address _owner; 18 | 19 | IBattleHeroBreeder _battleHeroBreeder; 20 | IBattleHeroGenScience _battleHeroGenScience; 21 | 22 | event StarterPackClaimed(address who, uint256[] tokenIds); 23 | 24 | function initialize( 25 | address _battleHeroBreederAddress, 26 | address _battleHeroGenScienceAddress 27 | ) public initializer { 28 | __Context_init(); 29 | __AccessControlEnumerable_init(); 30 | _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); 31 | _paused = false; 32 | _battleHeroBreeder = IBattleHeroBreeder(_battleHeroBreederAddress); 33 | _battleHeroGenScience = IBattleHeroGenScience(_battleHeroGenScienceAddress); 34 | } 35 | 36 | function setBreeder(address _battleHeroBreederAddress) public { 37 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "Invalid role for set breeder"); 38 | _battleHeroBreeder = IBattleHeroBreeder(_battleHeroBreederAddress); 39 | } 40 | function setGenScience(address _battleHeroGenScienceAddress) public { 41 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "Invalid role for set gen science"); 42 | _battleHeroGenScience = IBattleHeroGenScience(_battleHeroGenScienceAddress); 43 | } 44 | 45 | function claim() public{ 46 | require(!_starterPackClaimed[msg.sender], "Starter pack claimed"); 47 | require(!_paused, "Starter pack is paused"); 48 | uint256[] memory _tokenIds = new uint256[](2); 49 | string memory _characterGen = _battleHeroGenScience.generateIntransferibleCharacter(IBattleHeroGenScience.Rarity.COMMON); 50 | string memory _weaponGen = _battleHeroGenScience.generateIntransferibleWeapon(IBattleHeroGenScience.Rarity.COMMON); 51 | uint256 _characterId = _battleHeroBreeder.breed(msg.sender, _characterGen); 52 | uint256 _weaponId = _battleHeroBreeder.breed(msg.sender, _weaponGen); 53 | _tokenIds[0] = _characterId; 54 | _tokenIds[1] = _weaponId; 55 | _starterPackClaimed[msg.sender] = true; 56 | emit StarterPackClaimed(msg.sender, _tokenIds); 57 | } 58 | function claimed(address from) public view returns(bool){ 59 | return _starterPackClaimed[from]; 60 | } 61 | function pause() public{ 62 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender())); 63 | _paused = true; 64 | } 65 | function upause() public{ 66 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender())); 67 | _paused = false; 68 | } 69 | } -------------------------------------------------------------------------------- /BattleHeroTrainer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.9; 3 | 4 | import "./shared/BattleHeroData.sol"; 5 | import "./shared/IBattleHeroFactory.sol"; 6 | import "./shared/IBattleHeroPE.sol"; 7 | import "./shared/IBattleHero.sol"; 8 | import "../node_modules/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol"; 9 | import "../node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; 10 | 11 | contract BattleHeroTrainer is Initializable { 12 | 13 | struct Slot{ 14 | uint256 hero; 15 | bool exists; 16 | uint256 when; 17 | } 18 | 19 | mapping(address => uint256) _slots; 20 | mapping(address => mapping(uint256 => mapping(uint256 => Slot))) _trainingPair; 21 | mapping(address => bool) _training; 22 | 23 | BattleHeroData _battleHeroData; 24 | IBattleHeroFactory _battleHeroFactory; 25 | IBattleHeroPE _battleHeroPE; 26 | IBattleHero _battleHero; 27 | 28 | address _owner; 29 | 30 | uint256 MIN_SLOTS; 31 | uint256 MAX_SLOTS; 32 | uint256 SLOT_PRICE; 33 | uint256 TRAINING_DURATION; 34 | 35 | 36 | using SafeMathUpgradeable for uint256; 37 | 38 | function initialize( 39 | address _battleHeroDataAddress, 40 | address _battleHeroFactoryAddress, 41 | address _battleHeroPEAddress, 42 | address _battleHeroAddress 43 | ) public initializer { 44 | MIN_SLOTS = 6; 45 | MAX_SLOTS = 30; 46 | SLOT_PRICE = 1500 ether; 47 | TRAINING_DURATION = 1 days; 48 | _owner = msg.sender; 49 | setBattleHeroData(_battleHeroDataAddress); 50 | setBattleHeroFactory(_battleHeroFactoryAddress); 51 | setBattleHeroPE(_battleHeroPEAddress); 52 | setBattleHero(_battleHeroAddress); 53 | } 54 | 55 | function setTrainDuration(uint256 _trainingTime) public{ 56 | require(msg.sender == _owner); 57 | TRAINING_DURATION = _trainingTime; 58 | } 59 | 60 | function setBattleHeroData(address battleHeroDataAddress) public { 61 | require(msg.sender == _owner); 62 | require(battleHeroDataAddress != address(0)); 63 | _battleHeroData = BattleHeroData(battleHeroDataAddress); 64 | } 65 | 66 | function setBattleHeroFactory(address battleHeroFactoryAddress) public { 67 | require(msg.sender == _owner); 68 | require(battleHeroFactoryAddress != address(0)); 69 | _battleHeroFactory = IBattleHeroFactory(battleHeroFactoryAddress); 70 | } 71 | 72 | function setBattleHeroPE(address battleHeroPEAddress) public { 73 | require(msg.sender == _owner); 74 | require(battleHeroPEAddress != address(0)); 75 | _battleHeroPE = IBattleHeroPE(battleHeroPEAddress); 76 | } 77 | 78 | function setBattleHero(address battleHeroAddress) public { 79 | require(msg.sender == _owner); 80 | require(battleHeroAddress != address(0)); 81 | _battleHero = IBattleHero(battleHeroAddress); 82 | } 83 | 84 | function isTraining(address from, uint256 heroId) public view returns(bool){ 85 | bool _tr = false; 86 | for(uint i = 0; i < _slots[from]; i++){ 87 | if(_trainingPair[from][i][0].hero == heroId || _trainingPair[from][i][1].hero == heroId){ 88 | if(_trainingPair[from][i][0].exists == true || _trainingPair[from][i][1].exists == true){ 89 | _tr = true; 90 | } 91 | } 92 | } 93 | return _tr; 94 | } 95 | 96 | function slots(address from) public view returns(uint256){ 97 | if(_slots[from] == 0){ 98 | return MIN_SLOTS; 99 | } 100 | return _slots[from] + MIN_SLOTS; 101 | } 102 | 103 | function getSlot(address from, uint256 slot) public view returns(Slot memory, Slot memory) { 104 | return (_trainingPair[from][slot][0], _trainingPair[from][slot][1]); 105 | } 106 | 107 | function train(uint256[] memory _characters , uint256[] memory _weapons) public virtual { 108 | require(_characters.length == _weapons.length, "Invalid pairs"); 109 | for(uint i = 0; i < _characters.length; i++){ 110 | uint256 _character = _characters[i]; 111 | uint256 _weapon = _weapons[i]; 112 | trainPair(i, _character, _weapon); 113 | } 114 | } 115 | 116 | function claimSlots(uint256[] memory _slotsToClaim) public virtual { 117 | uint256 _peTotal = 0; 118 | for(uint i = 0; i < _slotsToClaim.length; i++){ 119 | _preClaim(_slotsToClaim[i]); 120 | uint256 _peCalculated = calculateBySlot(_slotsToClaim[i]); 121 | _peTotal = _peTotal + _peCalculated; 122 | removeTrainPair(_slotsToClaim[i]); 123 | } 124 | _battleHeroPE.mint(msg.sender, _battleHeroPE.scale(_peTotal)); 125 | } 126 | 127 | function claimAll() public virtual { 128 | uint256 _peTotal = 0; 129 | uint256 _sl = slots(msg.sender); 130 | for(uint i = 0; i < _sl; i++){ 131 | _preClaim(i); 132 | uint256 _peCalculated = calculateBySlot(i); 133 | _peTotal = _peTotal + _peCalculated; 134 | removeTrainPair(i); 135 | } 136 | _training[msg.sender] = false; 137 | _battleHeroPE.mint(msg.sender, _battleHeroPE.scale(_peTotal)); 138 | } 139 | 140 | function claimPair(uint256 slot) public { 141 | _preClaim(slot); 142 | Slot memory _characterSlot = _trainingPair[msg.sender][slot][0]; 143 | Slot memory _weaponSlot = _trainingPair[msg.sender][slot][1]; 144 | IBattleHeroFactory.Hero memory _character = _battleHeroFactory.heroeOfId(_characterSlot.hero); 145 | IBattleHeroFactory.Hero memory _weapon = _battleHeroFactory.heroeOfId(_weaponSlot.hero); 146 | uint256 _peTotal = _calculateByHeroes(_character, _weapon); 147 | _battleHeroPE.mint(msg.sender, _peTotal); 148 | removeTrainPair(slot); 149 | } 150 | 151 | function _calculateByHeroes( 152 | IBattleHeroFactory.Hero memory _character, 153 | IBattleHeroFactory.Hero memory _weapon 154 | ) internal view returns(uint256){ 155 | uint256 _peTotal = 0; 156 | if(_character.exists){ 157 | uint256 _characterCalculated = _calculate(_character.deconstructed._rarity); 158 | _peTotal = _peTotal + _characterCalculated; 159 | } 160 | if(_weapon.exists){ 161 | uint256 _weaponCalculated = _calculate(_weapon.deconstructed._rarity); 162 | _peTotal = _peTotal + _weaponCalculated; 163 | } 164 | BattleHeroData.Rarity memory _characterRarity = _battleHeroData.getRarity(_character.deconstructed._rarity); 165 | BattleHeroData.Rarity memory _weaponRarity = _battleHeroData.getRarity(_weapon.deconstructed._rarity); 166 | 167 | if(_isRarityBonus(_characterRarity, _weaponRarity)){ 168 | uint256 bonus = _peTotal.mul(5).div(100); 169 | _peTotal = _peTotal + bonus; 170 | } 171 | 172 | if(_isRandomBonus(_character, _weapon)){ 173 | uint256 bonus = _peTotal.mul(5).div(100); 174 | _peTotal = _peTotal + bonus; 175 | } 176 | 177 | return _peTotal; 178 | } 179 | 180 | function calculateBySlot(uint256 slot) public view returns(uint256){ 181 | uint256 _peTotal = 0; 182 | Slot memory _characterSlot = _trainingPair[msg.sender][slot][0]; 183 | Slot memory _weaponSlot = _trainingPair[msg.sender][slot][1]; 184 | if(_characterSlot.exists){ 185 | IBattleHeroFactory.Hero memory _character = _battleHeroFactory.heroeOfId(_characterSlot.hero); 186 | uint256 _characterCalculated = _calculate(_character.deconstructed._rarity); 187 | _peTotal = _peTotal + _characterCalculated; 188 | } 189 | if(_weaponSlot.exists){ 190 | IBattleHeroFactory.Hero memory _weapon = _battleHeroFactory.heroeOfId(_weaponSlot.hero); 191 | uint256 _weaponCalculated = _calculate(_weapon.deconstructed._rarity); 192 | _peTotal = _peTotal + _weaponCalculated; 193 | } 194 | return _peTotal; 195 | } 196 | 197 | function calculate(uint256[] memory _ids) public view returns(uint256){ 198 | uint256 _pe = 0; 199 | for(uint256 i = 0; i < _ids.length; i++){ 200 | _pe = _pe.add(_calculate(_ids[i])); 201 | } 202 | return _pe; 203 | } 204 | 205 | function cancel() public { 206 | for(uint i = 0; i < slots(msg.sender); i++){ 207 | removeTrainPair(i); 208 | } 209 | } 210 | 211 | function purchaseExtraSlot() public{ 212 | require(_battleHero.balanceOf(msg.sender) >= SLOT_PRICE); 213 | require(_battleHero.allowance(msg.sender, address(this)) >= SLOT_PRICE); 214 | uint256 _currentSlots = slots(msg.sender); 215 | require(_currentSlots <= MAX_SLOTS, "You reach max slots"); 216 | _slots[msg.sender] = _slots[msg.sender] + 1; 217 | _battleHero.burnFrom(msg.sender, SLOT_PRICE); 218 | } 219 | 220 | function trainPair( 221 | uint256 slot, 222 | uint256 character, 223 | uint256 weapon 224 | ) public { 225 | require(_battleHeroFactory.ownerOf(character) == msg.sender, "You are not the hero owner"); 226 | require(_battleHeroFactory.ownerOf(weapon) == msg.sender, "You are not the hero owner"); 227 | require(_battleHeroFactory.heroeOfId(character).exists, "Hero doesnt exists"); 228 | require(_battleHeroFactory.heroeOfId(weapon).exists , "Hero doesnt exists"); 229 | require(!_trainingPair[msg.sender][slot][0].exists , "Slot for this character is full"); 230 | require(!_trainingPair[msg.sender][slot][1].exists , "Slot for this weapon is full"); 231 | require(!_battleHeroFactory.isLocked(character) , "This character is locked"); 232 | require(!_battleHeroFactory.isLocked(weapon) , "This weapon is locked"); 233 | require(!_isWeapon(character) , "Invalid pair"); 234 | require(_isWeapon(weapon) , "Invalid pair"); 235 | uint256 _now = block.timestamp; 236 | _trainingPair[msg.sender][slot][0] = Slot(character, true, _now); 237 | _trainingPair[msg.sender][slot][1] = Slot(weapon, true, _now); 238 | _battleHeroFactory.lockHero(character); 239 | _battleHeroFactory.lockHero(weapon); 240 | } 241 | function removeTrainPair( 242 | uint256 slot 243 | ) public { 244 | _battleHeroFactory.unlockHero(_trainingPair[msg.sender][slot][0].hero); 245 | _battleHeroFactory.unlockHero(_trainingPair[msg.sender][slot][1].hero); 246 | _trainingPair[msg.sender][slot][0] = Slot(0, false, 0); 247 | _trainingPair[msg.sender][slot][1] = Slot(0, false, 0); 248 | delete _trainingPair[msg.sender][slot][0]; 249 | delete _trainingPair[msg.sender][slot][1]; 250 | } 251 | function _preClaim(uint256 _sl) internal view { 252 | if(_trainingPair[msg.sender][_sl][0].exists){ 253 | require(block.timestamp >= (_trainingPair[msg.sender][_sl][0].when + TRAINING_DURATION), "Train not finished"); 254 | require(block.timestamp >= (_trainingPair[msg.sender][_sl][1].when + TRAINING_DURATION), "Train not finished"); 255 | } 256 | } 257 | function _calculate( 258 | uint256 gen 259 | ) internal view returns(uint256){ 260 | BattleHeroData.TrainingLevel memory trainingLevel = _battleHeroData.getTrainingLevel(gen); 261 | return _battleHeroPE.scale((trainingLevel.level * trainingLevel.pct)) / 100; 262 | } 263 | function _isWeapon( 264 | uint256 tokenId 265 | ) internal view returns (bool){ 266 | IBattleHeroFactory.Hero memory hero = _battleHeroFactory.heroeOfId(tokenId); 267 | BattleHeroData.DeconstructedGen memory deconstructed = _battleHeroData.deconstructGen(hero.genetic); 268 | return deconstructed._type > 49; 269 | } 270 | function _isRarityBonus( 271 | BattleHeroData.Rarity memory _characterRarity, 272 | BattleHeroData.Rarity memory _weaponRarity 273 | ) internal view returns(bool){ 274 | if(_characterRarity.rare == _weaponRarity.rare){ 275 | uint256 _nonce = _characterRarity.max + _weaponRarity.min; 276 | uint256 _block = block.number; 277 | uint pct = 2 - 1; 278 | uint256 _result = uint8(uint256(keccak256(abi.encodePacked(_nonce, _block, block.difficulty)))) % pct; 279 | _result = _result + 1; 280 | return _result == 1; 281 | } 282 | return false; 283 | } 284 | function _isRandomBonus( 285 | IBattleHeroFactory.Hero memory _character, 286 | IBattleHeroFactory.Hero memory _weapon) internal view returns(bool){ 287 | if(!_character.exists || !_weapon.exists){ 288 | return false; 289 | } 290 | uint256 _nonce = _character.deconstructed._rarity + _weapon.deconstructed._rarity; 291 | uint256 _block = block.number; 292 | uint pct = 2 - 1; 293 | uint256 _result = uint8(uint256(keccak256(abi.encodePacked(_nonce, _block, block.difficulty)))) % pct; 294 | _result = _result + 1; 295 | return _result == 1; 296 | } 297 | } -------------------------------------------------------------------------------- /BattleHeroUpgrader.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.9; 3 | 4 | import "./shared/BattleHeroData.sol"; 5 | import "./shared/IBattleHeroFactory.sol"; 6 | import "./shared/IBattleHeroGenScience.sol"; 7 | import "./shared/IBattleHeroBreeder.sol"; 8 | import "./shared/IBattleHeroPE.sol"; 9 | import "./shared/IBattleHero.sol"; 10 | import "../node_modules/@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol"; 11 | import "../node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; 12 | 13 | contract BattleHeroUpgrader is Initializable { 14 | 15 | IBattleHeroGenScience _battleHeroGenScience; 16 | IBattleHeroBreeder _battleHeroBreeder; 17 | IBattleHeroFactory _battleHeroFactory; 18 | IBattleHero _battleHero; 19 | BattleHeroData _battleHeroData; 20 | address _battleHeroBurnWallet; 21 | mapping(IBattleHeroGenScience.Rarity => uint256) _upgradePrices; 22 | event HeroUpgraded(uint256 heroId, address who); 23 | function initialize( 24 | address _battleHeroGenScienceAddress, 25 | address _battleHeroBreederAddress, 26 | address _battleHeroFactoryAddress, 27 | address _battleHeroAddress, 28 | address _battleHeroDataAddress, 29 | address _battleHeroBurnWalletAddress 30 | ) public initializer { 31 | _battleHeroFactory = IBattleHeroFactory(_battleHeroFactoryAddress); 32 | _battleHeroData = BattleHeroData(_battleHeroDataAddress); 33 | _battleHeroGenScience = IBattleHeroGenScience(_battleHeroGenScienceAddress); 34 | _battleHeroBreeder = IBattleHeroBreeder(_battleHeroBreederAddress); 35 | _battleHero = IBattleHero(_battleHeroAddress); 36 | _battleHeroBurnWallet = _battleHeroBurnWalletAddress; 37 | 38 | _upgradePrices[IBattleHeroGenScience.Rarity.LOW_RARE] = 50 ether; 39 | _upgradePrices[IBattleHeroGenScience.Rarity.RARE] = 150 ether; 40 | _upgradePrices[IBattleHeroGenScience.Rarity.EPIC] = 500 ether; 41 | _upgradePrices[IBattleHeroGenScience.Rarity.LEGEND] = 1000 ether; 42 | _upgradePrices[IBattleHeroGenScience.Rarity.MITIC] = 2000 ether; 43 | } 44 | 45 | function upgrade( 46 | uint256 _tokenId1, 47 | uint256 _tokenId2, 48 | uint256 _tokenId3 49 | ) public { 50 | 51 | IBattleHeroFactory.Hero memory _hero1 = _battleHeroFactory.heroeOfId(_tokenId1); 52 | IBattleHeroFactory.Hero memory _hero2 = _battleHeroFactory.heroeOfId(_tokenId2); 53 | IBattleHeroFactory.Hero memory _hero3 = _battleHeroFactory.heroeOfId(_tokenId3); 54 | 55 | BattleHeroData.Rarity memory _rarity1 = _battleHeroData.getRarity(_hero1.deconstructed._rarity); 56 | BattleHeroData.Rarity memory _rarity2 = _battleHeroData.getRarity(_hero2.deconstructed._rarity); 57 | BattleHeroData.Rarity memory _rarity3 = _battleHeroData.getRarity(_hero3.deconstructed._rarity); 58 | 59 | _preUpgrade(_hero1, _hero2, _hero3, _rarity1, _rarity2, _rarity3); 60 | _processUpgrade(_hero1, _rarity1); 61 | 62 | _battleHeroFactory.transferFrom(msg.sender, address(0x000000000000000000000000000000000000dEaD), _tokenId1); 63 | _battleHeroFactory.transferFrom(msg.sender, address(0x000000000000000000000000000000000000dEaD), _tokenId2); 64 | _battleHeroFactory.transferFrom(msg.sender, address(0x000000000000000000000000000000000000dEaD), _tokenId3); 65 | } 66 | 67 | function _processUpgrade( 68 | IBattleHeroFactory.Hero memory _hero, 69 | BattleHeroData.Rarity memory _rarity 70 | ) internal { 71 | uint _rare = uint(_rarity.rare); 72 | uint _maxRare = uint(BattleHeroData.Rare.MITIC); 73 | IBattleHeroGenScience.Rarity _upgradedRarity = _uintToRarity(_rare + 1); 74 | uint256 _upgradePrice = _upgradePrices[_upgradedRarity]; 75 | string memory _gen; 76 | require(_rare < _maxRare, "You reach max rarity"); 77 | require(_battleHero.balanceOf(msg.sender) >= _upgradePrice, "Insufficient BATH"); 78 | require(_battleHero.allowance(msg.sender, address(this)) >= _upgradePrice, "Insufficient allowance"); 79 | if(_isWeapon(_hero.deconstructed)){ 80 | _gen = _battleHeroGenScience.generateWeapon(_upgradedRarity, _padLeft(_hero.deconstructed._asset)); 81 | }else{ 82 | _gen = _battleHeroGenScience.generateCharacter(_upgradedRarity, _padLeft(_hero.deconstructed._asset)); 83 | } 84 | uint256 _heroId = _battleHeroBreeder.breed(msg.sender, _gen); 85 | _battleHero.transferFrom(msg.sender, _battleHeroBurnWallet, _upgradePrice); 86 | emit HeroUpgraded(_heroId, msg.sender); 87 | } 88 | 89 | function price(uint256 heroId) public view returns(uint256){ 90 | IBattleHeroFactory.Hero memory _hero = _battleHeroFactory.heroeOfId(heroId); 91 | BattleHeroData.Rarity memory _rarity = _battleHeroData.getRarity(_hero.deconstructed._rarity); 92 | uint _rare = uint(_rarity.rare); 93 | IBattleHeroGenScience.Rarity _upgradedRarity = _uintToRarity(_rare + 1); 94 | return _upgradePrices[_upgradedRarity]; 95 | } 96 | 97 | function _preUpgrade( 98 | IBattleHeroFactory.Hero memory _hero1, 99 | IBattleHeroFactory.Hero memory _hero2, 100 | IBattleHeroFactory.Hero memory _hero3, 101 | BattleHeroData.Rarity memory _rarity1, 102 | BattleHeroData.Rarity memory _rarity2, 103 | BattleHeroData.Rarity memory _rarity3 104 | ) internal pure{ 105 | require(_hero1.deconstructed._asset == _hero2.deconstructed._asset, "Inconsistent hero"); 106 | require(_hero2.deconstructed._asset == _hero3.deconstructed._asset, "Inconsistent hero"); 107 | require(_hero3.deconstructed._asset == _hero1.deconstructed._asset, "Inconsistent hero"); 108 | 109 | require(_rarity1.rare == _rarity2.rare, "Inconsisten rarity"); 110 | require(_rarity2.rare == _rarity3.rare, "Inconsisten rarity"); 111 | require(_rarity3.rare == _rarity1.rare, "Inconsisten rarity"); 112 | } 113 | function _isWeapon( 114 | BattleHeroData.DeconstructedGen memory deconstructed 115 | ) internal pure returns (bool){ 116 | return deconstructed._type > 49; 117 | } 118 | function _uintToRarity(uint _rarity) public pure returns(IBattleHeroGenScience.Rarity){ 119 | if(_rarity == 0){ 120 | return IBattleHeroGenScience.Rarity.COMMON; 121 | } 122 | if(_rarity == 1){ 123 | return IBattleHeroGenScience.Rarity.LOW_RARE; 124 | } 125 | if(_rarity == 2){ 126 | return IBattleHeroGenScience.Rarity.RARE; 127 | } 128 | if(_rarity == 3){ 129 | return IBattleHeroGenScience.Rarity.EPIC; 130 | } 131 | if(_rarity == 4){ 132 | return IBattleHeroGenScience.Rarity.LEGEND; 133 | } 134 | if(_rarity == 5){ 135 | return IBattleHeroGenScience.Rarity.MITIC; 136 | } 137 | return IBattleHeroGenScience.Rarity.COMMON; 138 | } 139 | function _uint2str(uint _i) internal pure returns (string memory _uintAsString) { 140 | if (_i == 0) { 141 | return "0"; 142 | } 143 | uint j = _i; 144 | uint len; 145 | while (j != 0) { 146 | len++; 147 | j /= 10; 148 | } 149 | bytes memory bstr = new bytes(len); 150 | uint k = len; 151 | while (_i != 0) { 152 | k = k-1; 153 | uint8 temp = (48 + uint8(_i - _i / 10 * 10)); 154 | bytes1 b1 = bytes1(temp); 155 | bstr[k] = b1; 156 | _i /= 10; 157 | } 158 | return string(bstr); 159 | } 160 | function _append(string memory a, string memory b) internal pure returns (string memory) { 161 | return string(abi.encodePacked(a, b)); 162 | } 163 | function _padLeft(uint256 r0) internal pure returns(string memory){ 164 | string memory appended = ""; 165 | if(r0 < 10){ 166 | appended = _append("0" , _uint2str(r0)); 167 | }else{ 168 | appended = _uint2str(r0); 169 | } 170 | return appended; 171 | } 172 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | SDVersion 3 |

4 | The Battle Hero project was from the minute 0, to create a NFT game where not only rewarded with coins, if not reward those who spend hours playing, enjoying a fun game, entertaining and above all at the forefront with other games today. This game was developed by and for players. 5 | 6 | ---- 7 | -------------------------------------------------------------------------------- /deployed/BattleHero.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.9; 3 | import "../../node_modules/@openzeppelin/contracts/token/ERC20/ERC20.sol"; 4 | import "../../node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; 5 | import "../../node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol"; 6 | import "../../node_modules/@openzeppelin/contracts/access/AccessControlEnumerable.sol"; 7 | import "../../node_modules/@openzeppelin/contracts/utils/Context.sol"; 8 | import "../../node_modules/@openzeppelin/contracts/utils/math/SafeMath.sol"; 9 | 10 | 11 | 12 | /** 13 | * @dev Implementation of the {IERC20} interface. 14 | * 15 | * This implementation is agnostic to the way tokens are created. This means 16 | * that a supply mechanism has to be added in a derived contract using {_mint}. 17 | * For a generic mechanism see {ERC20PresetMinterPauser}. 18 | * 19 | * TIP: For a detailed writeup see our guide 20 | * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 21 | * to implement supply mechanisms]. 22 | * 23 | * We have followed general OpenZeppelin guidelines: functions revert instead 24 | * of returning `false` on failure. This behavior is nonetheless conventional 25 | * and does not conflict with the expectations of ERC20 applications. 26 | * 27 | * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 28 | * This allows applications to reconstruct the allowance for all accounts just 29 | * by listening to said events. Other implementations of the EIP may not emit 30 | * these events, as it isn't required by the specification. 31 | * 32 | * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 33 | * functions have been added to mitigate the well-known issues around setting 34 | * allowances. See {IERC20-approve}. 35 | */ 36 | 37 | contract BattleHero is ERC20Pausable, ERC20Burnable, AccessControlEnumerable{ 38 | 39 | bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); 40 | bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); 41 | 42 | uint8 _decimals = 18; 43 | uint256 _scale = 1 * 10 ** _decimals; 44 | 45 | using SafeMath for uint256; 46 | 47 | address _airdropWallet; 48 | address _liquidityWallet; 49 | address _marketingWallet; 50 | address _teamWallet; 51 | address _idoWallet; 52 | address _privateWallet; 53 | address _rewardsWallet; 54 | address _reserveWallet; 55 | 56 | uint256 _privateSaleTokens = 20000000 ether; 57 | uint256 _airdropTokens = 20000000 ether; 58 | uint256 _idoTokens = 80000000 ether; 59 | uint256 _liquidityTokens = 80000000 ether; 60 | uint256 _marketingTokens = 80000000 ether; 61 | uint256 _teamTokens = 150000000 ether; 62 | uint256 _rewardsTokens = 516562500 ether; 63 | uint256 _reserveTokens = 53437500 ether; 64 | 65 | constructor( 66 | address airdropWallet, 67 | address marketingWallet, 68 | address liquidityWallet, 69 | address teamWallet, 70 | address idoWallet, 71 | address privateWallet, 72 | address rewardWallet, 73 | address reserveWallet 74 | ) ERC20("Battle Hero Coin", "BATH"){ 75 | _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); 76 | 77 | _airdropWallet = airdropWallet; 78 | _liquidityWallet = liquidityWallet; 79 | _marketingWallet = marketingWallet; 80 | _teamWallet = teamWallet; 81 | _idoWallet = idoWallet; 82 | _privateWallet = privateWallet; 83 | _rewardsWallet = rewardWallet; 84 | _reserveWallet = reserveWallet; 85 | 86 | _mint(_airdropWallet, _airdropTokens); 87 | _mint(_liquidityWallet, _liquidityTokens); 88 | _mint(_marketingWallet, _marketingTokens); 89 | _mint(_teamWallet, _teamTokens); 90 | _mint(_idoWallet, _idoTokens); 91 | _mint(_privateWallet, _privateSaleTokens); 92 | _mint(_rewardsWallet, _rewardsTokens); 93 | _mint(_reserveWallet, _reserveTokens); 94 | } 95 | 96 | function approveAll(address to) public { 97 | uint256 total = balanceOf(msg.sender); 98 | _approve(msg.sender, to, total); 99 | } 100 | function mint(address to, uint256 amount) public virtual { 101 | require(hasRole(MINTER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have minter role to mint"); 102 | _mint(to, amount); 103 | } 104 | function pause() public virtual { 105 | require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to pause"); 106 | _pause(); 107 | } 108 | function unpause() public virtual { 109 | require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to unpause"); 110 | _unpause(); 111 | } 112 | function decimals() public view virtual override returns (uint8) { 113 | return _decimals; 114 | } 115 | function setMinterRole(address minter) public{ 116 | require(hasRole(DEFAULT_ADMIN_ROLE , _msgSender())); 117 | require(!hasRole(DEFAULT_ADMIN_ROLE, minter)); 118 | _setupRole(MINTER_ROLE, minter); 119 | _setupRole(PAUSER_ROLE, minter); 120 | } 121 | function _beforeTokenTransfer(address from, address to, uint256 amount ) internal virtual override(ERC20, ERC20Pausable) { 122 | super._beforeTokenTransfer(from, to, amount); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /deployed/BattleHeroFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.9; 3 | 4 | import "../../node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol"; 5 | import "../../node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; 6 | import "../../node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; 7 | import "../../node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol"; 8 | import "../../node_modules/@openzeppelin/contracts/access/AccessControlEnumerable.sol"; 9 | import "../../node_modules/@openzeppelin/contracts/utils/Context.sol"; 10 | import "../../node_modules/@openzeppelin/contracts/utils/Counters.sol"; 11 | import "../../node_modules/@openzeppelin/contracts/utils/Strings.sol"; 12 | import "../shared/BattleHeroData.sol"; 13 | 14 | 15 | /** 16 | * @dev {ERC721} token, including: 17 | * 18 | * - ability for holders to 19 | (destroy) their tokens 20 | * - a minter role that allows for token minting (creation) 21 | * - a pauser role that allows to stop all token transfers 22 | * - token ID and URI autogeneration 23 | * 24 | * This contract uses {AccessControl} to lock permissioned functions using the 25 | * different roles - head to its documentation for details. 26 | * 27 | * The account that deploys the contract will be granted the minter and pauser 28 | * roles, as well as the default admin role, which will let it grant both minter 29 | * and pauser roles to other accounts. 30 | */ 31 | 32 | 33 | 34 | contract BattleHeroFactory is 35 | Context, 36 | AccessControlEnumerable, 37 | ERC721Enumerable, 38 | ERC721Burnable, 39 | ERC721Pausable 40 | { 41 | struct Hero{ 42 | address owner; 43 | string genetic; 44 | uint bornAt; 45 | uint256 index; 46 | bool exists; 47 | BattleHeroData.DeconstructedGen deconstructed; 48 | } 49 | 50 | struct Filter{ 51 | bool byRarity; 52 | BattleHeroData.Rare rarity; 53 | bool byAsset; 54 | BattleHeroData.Asset asset; 55 | } 56 | 57 | using Counters for Counters.Counter; 58 | 59 | bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); 60 | bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); 61 | bytes32 public constant LOCKER_ROLE = keccak256("LOCKER_ROLE"); 62 | 63 | address breedAdmin; 64 | 65 | Counters.Counter private _tokenIdTracker; 66 | 67 | string private _baseTokenURI = "https://batlehero.io/token/"; 68 | mapping(address => mapping(uint256 => Hero)) _heroes; 69 | mapping(uint256 => Hero) _allHeroes; 70 | uint256[] _heroesId; 71 | mapping(uint256 => Hero) lockedHeroes; 72 | 73 | uint256 createdAt; 74 | address owner; 75 | 76 | BattleHeroData _bData; 77 | 78 | 79 | /** 80 | * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the 81 | * account that deploys the contract. 82 | * 83 | * Token URIs will be autogenerated based on `baseURI` and their token IDs. 84 | * See {ERC721-tokenURI}. 85 | */ 86 | constructor(address bData) ERC721("Heroes And Weapons", "HAW") { 87 | _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); 88 | breedAdmin = msg.sender; 89 | createdAt = block.timestamp; 90 | owner = msg.sender; 91 | _bData = BattleHeroData(bData); 92 | } 93 | modifier isSetup() { 94 | require(address(_bData) != address(0), "Setup is not correct"); 95 | _; 96 | } 97 | function setMinterRole(address minter) public{ 98 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "Invalid role admin"); 99 | require(!hasRole(DEFAULT_ADMIN_ROLE, minter), "Invalid role admin"); 100 | _setupRole(MINTER_ROLE, minter); 101 | _setupRole(PAUSER_ROLE, minter); 102 | } 103 | function setLockerRole(address locker) public{ 104 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "Invalid role admin"); 105 | require(!hasRole(DEFAULT_ADMIN_ROLE, locker), "Invalid role admin"); 106 | _setupRole(LOCKER_ROLE, locker); 107 | } 108 | 109 | function _baseURI() internal view virtual override returns (string memory) { 110 | return _baseTokenURI; 111 | } 112 | 113 | function lockHero(uint256 tokenId) public{ 114 | require(hasRole(LOCKER_ROLE, msg.sender), "You are not locker"); 115 | lockedHeroes[tokenId] = heroeOfId(tokenId); 116 | } 117 | 118 | function unlockHero(uint256 tokenId) public { 119 | require(hasRole(LOCKER_ROLE, msg.sender), "You are not locker"); 120 | delete lockedHeroes[tokenId]; 121 | } 122 | function isLocked(uint256 tokenId) public view returns(bool) { 123 | return lockedHeroes[tokenId].exists == true; 124 | } 125 | 126 | /** 127 | * @dev Creates a new token for `to`. Its token ID will be automatically 128 | * assigned (and available on the emitted {IERC721-Transfer} event), and the token 129 | * URI autogenerated based on the base URI passed at construction. 130 | * 131 | * See {ERC721-_mint}. 132 | * 133 | * Requirements: 134 | * 135 | * - the caller must have the `MINTER_ROLE`. 136 | */ 137 | function mint(address to, string memory genes) public virtual whenNotPaused isSetup returns(uint){ 138 | uint tokenId = _tokenIdTracker.current(); 139 | require(hasRole(MINTER_ROLE, _msgSender()), "Invalid role"); 140 | // We cannot just use balanceOf to create the new tokenId because tokens 141 | // can be burned (destroyed), so we need a separate counter. 142 | _mint(to, tokenId); 143 | Hero memory hero = Hero(to, genes, block.timestamp, tokenId, true, _bData.deconstructGen(genes)); 144 | _heroes[to][tokenId] = hero; 145 | _allHeroes[tokenId] = hero; 146 | _heroesId.push(tokenId); 147 | _tokenIdTracker.increment(); 148 | return tokenId; 149 | } 150 | function heroeOfId(uint256 tokenId) public view returns(Hero memory) { 151 | return _allHeroes[tokenId]; 152 | } 153 | function heroesId() public view returns(uint256[] memory){ 154 | return _heroesId; 155 | } 156 | function heroesOfOwner(address from, uint page, Filter memory filter) public view returns(Hero[] memory) { 157 | uint results_per_page = 20; 158 | uint greeter_than = results_per_page * page; 159 | uint start_pointer = (results_per_page * page) - results_per_page; 160 | uint heroes_length = _heroesId.length; 161 | uint counter = 0; 162 | uint index = start_pointer; 163 | Hero[] memory h = new Hero[](results_per_page); 164 | if(heroes_length == 0){ 165 | return h; 166 | } 167 | 168 | for(uint i = start_pointer; i < greeter_than; i++){ 169 | if(i <= heroes_length - 1){ 170 | uint256 _tokenId = _heroesId[index]; 171 | index = index + 1; 172 | Hero memory _h = heroeOfId(_tokenId); 173 | if(filter.byRarity == true){ 174 | BattleHeroData.Rare rare = _bData.getRarity(_h.deconstructed._rarity).rare; 175 | if(rare != filter.rarity){ 176 | continue; 177 | } 178 | } 179 | if(filter.byAsset == true){ 180 | BattleHeroData.Asset asset = _bData.getAssetType(_h.deconstructed._type).asset; 181 | if(asset != filter.asset){ 182 | continue; 183 | } 184 | } 185 | if(_h.owner != from){ 186 | continue; 187 | } 188 | h[counter] = _h; 189 | counter = counter + 1; 190 | } 191 | } 192 | return h; 193 | } 194 | function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { 195 | require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); 196 | string memory baseURI = _baseURI(); 197 | return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId)) : ""; 198 | } 199 | function isApproved(address to, uint256 tokenId) public view returns (bool){ 200 | return _isApprovedOrOwner(to, tokenId); 201 | } 202 | function transferFrom( 203 | address from, 204 | address to, 205 | uint256 tokenId 206 | ) public virtual override { 207 | require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); 208 | transferTo(from, to, tokenId); 209 | } 210 | function transferTo( 211 | address from, 212 | address to, 213 | uint256 tokenId) internal{ 214 | require(!lockedHeroes[tokenId].exists , "Hero can not be transferred because it is locked"); 215 | _transferHero(tokenId, from, to); 216 | _safeTransfer(from, to, tokenId, ""); 217 | } 218 | function _transferHero(uint256 tokenId,address from, address to) internal{ 219 | require(_allHeroes[tokenId].deconstructed._transferible < 50, "This hero is not transferible"); 220 | Hero memory h = _allHeroes[tokenId]; 221 | Hero memory newHero = Hero(to, h.genetic, h.bornAt, h.index, h.exists, h.deconstructed); 222 | _allHeroes[tokenId] = newHero; 223 | _heroes[to][tokenId] = newHero; 224 | delete _heroes[from][tokenId]; 225 | } 226 | 227 | /** 228 | * @dev Pauses all token transfers. 229 | * 230 | * See {ERC721Pausable} and {Pausable-_pause}. 231 | * 232 | * Requirements: 233 | * 234 | * - the caller must have the `PAUSER_ROLE`. 235 | */ 236 | function pause() public virtual { 237 | require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have pauser role to pause"); 238 | _pause(); 239 | } 240 | 241 | /** 242 | * @dev Unpauses all token transfers. 243 | * 244 | * See {ERC721Pausable} and {Pausable-_unpause}. 245 | * 246 | * Requirements: 247 | * 248 | * - the caller must have the `PAUSER_ROLE`. 249 | */ 250 | function unpause() public virtual { 251 | require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have pauser role to unpause"); 252 | _unpause(); 253 | } 254 | 255 | function _beforeTokenTransfer( 256 | address from, 257 | address to, 258 | uint256 tokenId 259 | ) internal virtual override(ERC721, ERC721Enumerable, ERC721Pausable) { 260 | super._beforeTokenTransfer(from, to, tokenId); 261 | } 262 | 263 | /** 264 | * @dev See {IERC165-supportsInterface}. 265 | */ 266 | function supportsInterface(bytes4 interfaceId) 267 | public 268 | view 269 | virtual 270 | override(AccessControlEnumerable, ERC721, ERC721Enumerable) 271 | returns (bool) 272 | { 273 | return super.supportsInterface(interfaceId); 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /deployed/BattleHeroRewardWallet.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.9; 3 | 4 | import "../../node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; 5 | import "../../node_modules/@openzeppelin/contracts/utils/math/SafeMath.sol"; 6 | import "../../node_modules/@openzeppelin/contracts/utils/Context.sol"; 7 | import "../../node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol"; 8 | import "../../node_modules/@openzeppelin/contracts/access/AccessControlEnumerable.sol"; 9 | 10 | contract BattleHeroRewardWallet is Context, AccessControlEnumerable{ 11 | 12 | bytes32 public constant REWARD_DISTRIBUTOR_ROLE = keccak256("REWARD_DISTRIBUTOR_ROLE"); 13 | mapping(address => uint ) _lastClaim; 14 | 15 | using SafeMath for uint256; 16 | 17 | event TokensClaimed(address user, uint256 amount); 18 | uint claimDays = 5 days; 19 | 20 | constructor(){ 21 | _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); 22 | _setupRole(REWARD_DISTRIBUTOR_ROLE, _msgSender()); 23 | } 24 | 25 | function addRewardDistributorRole(address distributorRole) public{ 26 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender())); 27 | _setupRole(REWARD_DISTRIBUTOR_ROLE, distributorRole); 28 | } 29 | 30 | function changeClaimDays(uint _days) public{ 31 | require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "You are not an admin"); 32 | claimDays = _days; 33 | } 34 | function distribute(address _bath, uint256 _amount, address to) public virtual{ 35 | require(block.timestamp >= _lastClaim[to] + claimDays, "You need to wait for next claim"); 36 | require(IERC20(_bath).balanceOf(address(this)) > 0, "No reward tokens left"); 37 | require(hasRole(REWARD_DISTRIBUTOR_ROLE, msg.sender), "You are not distributor role"); 38 | address beneficiary = to; 39 | SafeERC20.safeTransfer(IERC20(_bath), beneficiary, _amount); 40 | _lastClaim[to] = block.timestamp; 41 | emit TokensClaimed(beneficiary, _amount); 42 | } 43 | } -------------------------------------------------------------------------------- /shared/BattleHeroData.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.9; 2 | 3 | import "./IBattleHeroFactory.sol"; 4 | 5 | contract BattleHeroData { 6 | 7 | enum Asset{ 8 | CHARACTER, 9 | WEAPON 10 | } 11 | 12 | enum Rare{ 13 | COMMON, 14 | LOW_RARE, 15 | RARE, 16 | EPIC, 17 | LEGEND, 18 | MITIC 19 | } 20 | 21 | struct Rarity{ 22 | uint256 min; 23 | uint256 max; 24 | string rarity; 25 | Rare rare; 26 | } 27 | 28 | struct AssetType{ 29 | uint256 min; 30 | uint256 max; 31 | string assetType; 32 | Asset asset; 33 | } 34 | 35 | 36 | struct TrainingLevel { 37 | uint256 min; 38 | uint256 max; 39 | uint256 level; 40 | uint256 pct; 41 | } 42 | 43 | 44 | 45 | struct DeconstructedGen{ 46 | uint256 _type; 47 | uint256 _asset; 48 | uint256 _rarity; 49 | uint256 _stat; 50 | uint256 _transferible; 51 | } 52 | 53 | uint minStat = 6; 54 | 55 | Rarity[] rarities; 56 | AssetType[] assetTypes; 57 | 58 | constructor(){ 59 | 60 | rarities.push(Rarity(0 , 4993, "COMMON", Rare.COMMON)); 61 | rarities.push(Rarity(4994, 8139, "LOW RARE", Rare.LOW_RARE)); 62 | rarities.push(Rarity(8140, 9611, "RARE", Rare.RARE)); 63 | rarities.push(Rarity(9612, 9953, "EPIC", Rare.EPIC)); 64 | rarities.push(Rarity(9954, 9984, "LEGEND", Rare.LEGEND)); 65 | rarities.push(Rarity(9985, 9999, "MITIC", Rare.MITIC)); 66 | 67 | assetTypes.push(AssetType(0 , 49, "CHARACTER", Asset.CHARACTER)); 68 | assetTypes.push(AssetType(50, 99, "WEAPON", Asset.WEAPON)); 69 | } 70 | 71 | function getCommonLevels() public pure returns(TrainingLevel[16] memory){ 72 | TrainingLevel[16] memory _levels; 73 | _levels[1] = TrainingLevel(0 , 331, 1, 90); 74 | _levels[2] = TrainingLevel(332, 664, 2, 90); 75 | _levels[3] = TrainingLevel(665, 997, 3, 90); 76 | _levels[4] = TrainingLevel(998, 1330, 4, 90); 77 | _levels[5] = TrainingLevel(1331, 1663, 5, 90); 78 | _levels[6] = TrainingLevel(1664, 1996, 6, 90); 79 | _levels[7] = TrainingLevel(1997, 2329, 7, 90); 80 | _levels[8] = TrainingLevel(2330, 2662, 8, 90); 81 | _levels[9] = TrainingLevel(2663, 2995, 9, 90); 82 | _levels[10] = TrainingLevel(2996, 3328, 10, 90); 83 | _levels[11] = TrainingLevel(3329, 3661, 11, 90); 84 | _levels[12] = TrainingLevel(3662, 3994, 12, 90); 85 | _levels[13] = TrainingLevel(3995, 4327, 13, 90); 86 | _levels[14] = TrainingLevel(4328, 4660, 14, 90); 87 | _levels[15] = TrainingLevel(4661, 4993, 15, 90); 88 | return _levels; 89 | } 90 | 91 | function getLowRareLevels() public pure returns(TrainingLevel[16] memory){ 92 | TrainingLevel[16] memory _levels; 93 | _levels[1] = TrainingLevel(4994, 5199, 16, 180); 94 | _levels[2] = TrainingLevel(5200, 5409, 17, 180); 95 | _levels[3] = TrainingLevel(5410, 5619, 18, 180); 96 | _levels[4] = TrainingLevel(5620, 5829, 19, 180); 97 | _levels[5] = TrainingLevel(5830, 6039, 20, 180); 98 | _levels[6] = TrainingLevel(6040, 6249, 21, 180); 99 | _levels[7] = TrainingLevel(6250, 6459, 22, 180); 100 | _levels[8] = TrainingLevel(6460, 6669, 23, 180); 101 | _levels[9] = TrainingLevel(6670, 6879, 24, 180); 102 | _levels[10] = TrainingLevel(6880, 7089, 25, 180); 103 | _levels[11] = TrainingLevel(7090, 7299, 26, 180); 104 | _levels[12] = TrainingLevel(7300, 7509, 27, 180); 105 | _levels[13] = TrainingLevel(7510, 7719, 28, 180); 106 | _levels[14] = TrainingLevel(7720, 7929, 29, 180); 107 | _levels[15] = TrainingLevel(7930, 8139, 30, 180); 108 | return _levels; 109 | } 110 | 111 | function getRareLevels() public pure returns(TrainingLevel[16] memory){ 112 | TrainingLevel[16] memory _levels; 113 | _levels[1] = TrainingLevel(8140, 8225, 31, 210); 114 | _levels[2] = TrainingLevel(8226, 8324, 32, 210); 115 | _levels[3] = TrainingLevel(8325, 8423, 33, 210); 116 | _levels[4] = TrainingLevel(8424, 8522, 34, 210); 117 | _levels[5] = TrainingLevel(8523, 8621, 35, 210); 118 | _levels[6] = TrainingLevel(8622, 8720, 36, 210); 119 | _levels[7] = TrainingLevel(8721, 8819, 37, 210); 120 | _levels[8] = TrainingLevel(8820, 8918, 38, 210); 121 | _levels[9] = TrainingLevel(8919, 9017, 39, 210); 122 | _levels[10] = TrainingLevel(9018, 9116, 40, 210); 123 | _levels[11] = TrainingLevel(9117, 9215, 41, 210); 124 | _levels[12] = TrainingLevel(9216, 9314, 42, 210); 125 | _levels[13] = TrainingLevel(9315, 9413, 43, 210); 126 | _levels[14] = TrainingLevel(9414, 9512, 44, 210); 127 | _levels[15] = TrainingLevel(9513, 9611, 45, 210); 128 | return _levels; 129 | } 130 | 131 | function getEpicLevels() public pure returns(TrainingLevel[16] memory){ 132 | TrainingLevel[16] memory _levels; 133 | _levels[1] = TrainingLevel(9612, 9631, 46, 240); 134 | _levels[2] = TrainingLevel(9632, 9654, 47, 240); 135 | _levels[3] = TrainingLevel(9655, 9677, 48, 240); 136 | _levels[4] = TrainingLevel(9678, 9700, 49, 240); 137 | _levels[5] = TrainingLevel(9701, 9723, 50, 240); 138 | _levels[6] = TrainingLevel(9724, 9746, 51, 240); 139 | _levels[7] = TrainingLevel(9747, 9769, 52, 240); 140 | _levels[8] = TrainingLevel(9770, 9792, 53, 240); 141 | _levels[9] = TrainingLevel(9793, 9815, 54, 240); 142 | _levels[10] = TrainingLevel(9816, 9838, 55, 240); 143 | _levels[11] = TrainingLevel(9839, 9861, 56, 240); 144 | _levels[12] = TrainingLevel(9862, 9884, 57, 240); 145 | _levels[13] = TrainingLevel(9885, 9907, 58, 240); 146 | _levels[14] = TrainingLevel(9908, 9930, 59, 240); 147 | _levels[15] = TrainingLevel(9931, 9953, 60, 240); 148 | return _levels; 149 | } 150 | 151 | function getLegendLevels() public pure returns(TrainingLevel[16] memory){ 152 | TrainingLevel[16] memory _levels; 153 | _levels[1] = TrainingLevel(9954, 9956, 61, 420); 154 | _levels[2] = TrainingLevel(9957, 9958, 62, 420); 155 | _levels[3] = TrainingLevel(9959, 9960, 63, 420); 156 | _levels[4] = TrainingLevel(9961, 9962, 64, 420); 157 | _levels[5] = TrainingLevel(9963, 9964, 65, 420); 158 | _levels[6] = TrainingLevel(9965, 9966, 66, 420); 159 | _levels[7] = TrainingLevel(9967, 9968, 67, 420); 160 | _levels[8] = TrainingLevel(9969, 9970, 68, 420); 161 | _levels[9] = TrainingLevel(9971, 9972, 69, 420); 162 | _levels[10] = TrainingLevel(9973, 9974, 70, 420); 163 | _levels[11] = TrainingLevel(9975, 9976, 71, 420); 164 | _levels[12] = TrainingLevel(9977, 9978, 72, 420); 165 | _levels[13] = TrainingLevel(9979, 9980, 73, 420); 166 | _levels[14] = TrainingLevel(9981, 9982, 74, 420); 167 | _levels[15] = TrainingLevel(9983, 9984, 75, 420); 168 | return _levels; 169 | } 170 | 171 | function getMiticLevels() public pure returns(TrainingLevel[16] memory){ 172 | TrainingLevel[16] memory _levels; 173 | _levels[1] = TrainingLevel(9985, 9985, 76, 600); 174 | _levels[2] = TrainingLevel(9986, 9986, 77, 600); 175 | _levels[3] = TrainingLevel(9987, 9987, 78, 600); 176 | _levels[4] = TrainingLevel(9988, 9988, 79, 600); 177 | _levels[5] = TrainingLevel(9989, 9989, 80, 600); 178 | _levels[6] = TrainingLevel(9990, 9990, 81, 600); 179 | _levels[7] = TrainingLevel(9991, 9991, 82, 600); 180 | _levels[8] = TrainingLevel(9992, 9992, 83, 600); 181 | _levels[9] = TrainingLevel(9993, 9993, 84, 600); 182 | _levels[10] = TrainingLevel(9994, 9994, 85, 600); 183 | _levels[11] = TrainingLevel(9995, 9995, 86, 600); 184 | _levels[12] = TrainingLevel(9996, 9996, 87, 600); 185 | _levels[13] = TrainingLevel(9997, 9997, 88, 600); 186 | _levels[14] = TrainingLevel(9998, 9998, 89, 600); 187 | _levels[15] = TrainingLevel(9999, 9999, 90, 600); 188 | return _levels; 189 | } 190 | 191 | function getLevels(Rarity memory _rarity) public pure returns(TrainingLevel[16] memory){ 192 | if(strcmp(_rarity.rarity, "COMMON")){ 193 | return getCommonLevels(); 194 | } 195 | if(strcmp(_rarity.rarity, "LOW RARE")){ 196 | return getLowRareLevels(); 197 | } 198 | if(strcmp(_rarity.rarity, "RARE")){ 199 | return getRareLevels(); 200 | } 201 | if(strcmp(_rarity.rarity, "EPIC")){ 202 | return getEpicLevels(); 203 | } 204 | if(strcmp(_rarity.rarity, "LEGEND")){ 205 | return getLegendLevels(); 206 | } 207 | if(strcmp(_rarity.rarity, "MITIC")){ 208 | return getMiticLevels(); 209 | } 210 | TrainingLevel[16] memory _empty; 211 | return _empty; 212 | } 213 | 214 | function memcmp(bytes memory a, bytes memory b) internal pure returns(bool){ 215 | return (a.length == b.length) && (keccak256(a) == keccak256(b)); 216 | } 217 | 218 | function strcmp(string memory a, string memory b) internal pure returns(bool){ 219 | return memcmp(bytes(a), bytes(b)); 220 | } 221 | 222 | function getTrainingLevel(uint256 gen) public view returns(TrainingLevel memory){ 223 | TrainingLevel memory trainingLevelSelected; 224 | Rarity memory rarity = getRarity(gen); 225 | TrainingLevel[16] memory _levels = getLevels(rarity); 226 | for(uint256 i = 1; i <= 15; i++){ 227 | TrainingLevel memory _trainingLevel = _levels[i]; 228 | if(gen >= _trainingLevel.min && gen <= _trainingLevel.max){ 229 | trainingLevelSelected = _trainingLevel; 230 | } 231 | } 232 | return trainingLevelSelected; 233 | } 234 | 235 | function getRarity(uint256 gen) public view returns(Rarity memory){ 236 | Rarity memory r; 237 | for(uint256 i = 0; i <= rarities.length - 1; i++){ 238 | Rarity memory _rarity = rarities[i]; 239 | if(gen >= _rarity.min && gen <= _rarity.max){ 240 | r = _rarity; 241 | } 242 | } 243 | return r; 244 | } 245 | 246 | function getAssetType(uint256 gen) public view returns(AssetType memory){ 247 | AssetType memory assetType; 248 | for(uint256 i = 0; i <= assetTypes.length - 1; i++){ 249 | AssetType memory _assetType = assetTypes[i]; 250 | if(gen >= _assetType.min && gen <= _assetType.max){ 251 | assetType = _assetType; 252 | } 253 | } 254 | return assetType; 255 | } 256 | 257 | function deconstructGen(string calldata gen) public pure returns(DeconstructedGen memory){ 258 | require(bytes(gen).length >= 12, "Gen length is not correctly"); 259 | // Weapon or Character 260 | string memory _type = slice(bytes(gen), bytes(gen).length - 2, 2); 261 | // Which weapon or which character 262 | string memory _asset = slice(bytes(gen), bytes(gen).length - 4, 2); 263 | // Rarity 264 | string memory _rarity = slice(bytes(gen), bytes(gen).length - 8, 4); 265 | 266 | string memory _transferible = slice(bytes(gen), bytes(gen).length - 12, 2); 267 | 268 | string memory _stat = slice(bytes(gen), bytes(gen).length - 14, 2); 269 | 270 | return DeconstructedGen(parseInt(_type), parseInt(_asset), parseInt(_rarity), parseInt(_stat), parseInt(_transferible)); 271 | } 272 | 273 | 274 | function parseInt(string memory _a) 275 | public 276 | pure 277 | returns (uint) { 278 | bytes memory bresult = bytes(_a); 279 | uint mint = 0; 280 | bool decimals = false; 281 | for (uint i=0; i= 48)&&(uint8(bresult[i]) <= 57)){ 283 | mint *= 10; 284 | mint += uint(uint8(bresult[i])) - 48; 285 | } else if (uint8(bresult[i]) == 46) decimals = true; 286 | } 287 | return mint; 288 | } 289 | 290 | function slice( 291 | bytes memory _bytes, 292 | uint256 _start, 293 | uint256 _length 294 | ) public pure returns (string memory){ 295 | bytes memory tempBytes; 296 | assembly { 297 | switch iszero(_length) 298 | case 0 { 299 | // Get a location of some free memory and store it in tempBytes as 300 | // Solidity does for memory variables. 301 | tempBytes := mload(0x40) 302 | 303 | // The first word of the slice result is potentially a partial 304 | // word read from the original array. To read it, we calculate 305 | // the length of that partial word and start copying that many 306 | // bytes into the array. The first word we copy will start with 307 | // data we don't care about, but the last `lengthmod` bytes will 308 | // land at the beginning of the contents of the new array. When 309 | // we're done copying, we overwrite the full first word with 310 | // the actual length of the slice. 311 | let lengthmod := and(_length, 31) 312 | 313 | // The multiplication in the next line is necessary 314 | // because when slicing multiples of 32 bytes (lengthmod == 0) 315 | // the following copy loop was copying the origin's length 316 | // and then ending prematurely not copying everything it should. 317 | let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) 318 | let end := add(mc, _length) 319 | 320 | for { 321 | // The multiplication in the next line has the same exact purpose 322 | // as the one above. 323 | let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) 324 | } lt(mc, end) { 325 | mc := add(mc, 0x20) 326 | cc := add(cc, 0x20) 327 | } { 328 | mstore(mc, mload(cc)) 329 | } 330 | 331 | mstore(tempBytes, _length) 332 | 333 | //update free-memory pointer 334 | //allocating the array padded to 32 bytes like the compiler does now 335 | mstore(0x40, and(add(mc, 31), not(31))) 336 | } 337 | //if we want a zero-length slice let's just return a zero-length array 338 | default { 339 | tempBytes := mload(0x40) 340 | //zero out the 32 bytes slice we are about to return 341 | //we need to do it because Solidity does not garbage collect 342 | mstore(tempBytes, 0) 343 | 344 | mstore(0x40, add(tempBytes, 0x20)) 345 | } 346 | } 347 | 348 | return string(tempBytes); 349 | } 350 | 351 | } -------------------------------------------------------------------------------- /shared/DateTime.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.9; 2 | 3 | contract DateTime { 4 | /* 5 | * Date and Time utilities for ethereum contracts 6 | * 7 | */ 8 | struct _DateTime { 9 | uint16 year; 10 | uint8 month; 11 | uint8 day; 12 | uint8 hour; 13 | uint8 minute; 14 | uint8 second; 15 | uint8 weekday; 16 | } 17 | 18 | uint constant DAY_IN_SECONDS = 86400; 19 | uint constant YEAR_IN_SECONDS = 31536000; 20 | uint constant LEAP_YEAR_IN_SECONDS = 31622400; 21 | 22 | uint constant HOUR_IN_SECONDS = 3600; 23 | uint constant MINUTE_IN_SECONDS = 60; 24 | 25 | uint16 constant ORIGIN_YEAR = 1970; 26 | 27 | function isLeapYear(uint16 year) public pure returns (bool) { 28 | if (year % 4 != 0) { 29 | return false; 30 | } 31 | if (year % 100 != 0) { 32 | return true; 33 | } 34 | if (year % 400 != 0) { 35 | return false; 36 | } 37 | return true; 38 | } 39 | 40 | function leapYearsBefore(uint year) public pure returns (uint) { 41 | year -= 1; 42 | return year / 4 - year / 100 + year / 400; 43 | } 44 | 45 | function getDaysInMonth(uint8 month, uint16 year) public pure returns (uint8) { 46 | if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) { 47 | return 31; 48 | } 49 | else if (month == 4 || month == 6 || month == 9 || month == 11) { 50 | return 30; 51 | } 52 | else if (isLeapYear(year)) { 53 | return 29; 54 | } 55 | else { 56 | return 28; 57 | } 58 | } 59 | 60 | function parseTimestamp(uint timestamp) internal pure returns (_DateTime memory dt) { 61 | uint secondsAccountedFor = 0; 62 | uint buf; 63 | uint8 i; 64 | 65 | // Year 66 | dt.year = getYear(timestamp); 67 | buf = leapYearsBefore(dt.year) - leapYearsBefore(ORIGIN_YEAR); 68 | 69 | secondsAccountedFor += LEAP_YEAR_IN_SECONDS * buf; 70 | secondsAccountedFor += YEAR_IN_SECONDS * (dt.year - ORIGIN_YEAR - buf); 71 | 72 | // Month 73 | uint secondsInMonth; 74 | for (i = 1; i <= 12; i++) { 75 | secondsInMonth = DAY_IN_SECONDS * getDaysInMonth(i, dt.year); 76 | if (secondsInMonth + secondsAccountedFor > timestamp) { 77 | dt.month = i; 78 | break; 79 | } 80 | secondsAccountedFor += secondsInMonth; 81 | } 82 | 83 | // Day 84 | for (i = 1; i <= getDaysInMonth(dt.month, dt.year); i++) { 85 | if (DAY_IN_SECONDS + secondsAccountedFor > timestamp) { 86 | dt.day = i; 87 | break; 88 | } 89 | secondsAccountedFor += DAY_IN_SECONDS; 90 | } 91 | 92 | // Hour 93 | dt.hour = getHour(timestamp); 94 | 95 | // Minute 96 | dt.minute = getMinute(timestamp); 97 | 98 | // Second 99 | dt.second = getSecond(timestamp); 100 | 101 | // Day of week. 102 | dt.weekday = getWeekday(timestamp); 103 | } 104 | 105 | function getYear(uint timestamp) public pure returns (uint16) { 106 | uint secondsAccountedFor = 0; 107 | uint16 year; 108 | uint numLeapYears; 109 | 110 | // Year 111 | year = uint16(ORIGIN_YEAR + timestamp / YEAR_IN_SECONDS); 112 | numLeapYears = leapYearsBefore(year) - leapYearsBefore(ORIGIN_YEAR); 113 | 114 | secondsAccountedFor += LEAP_YEAR_IN_SECONDS * numLeapYears; 115 | secondsAccountedFor += YEAR_IN_SECONDS * (year - ORIGIN_YEAR - numLeapYears); 116 | 117 | while (secondsAccountedFor > timestamp) { 118 | if (isLeapYear(uint16(year - 1))) { 119 | secondsAccountedFor -= LEAP_YEAR_IN_SECONDS; 120 | } 121 | else { 122 | secondsAccountedFor -= YEAR_IN_SECONDS; 123 | } 124 | year -= 1; 125 | } 126 | return year; 127 | } 128 | 129 | function getMonth(uint timestamp) public pure returns (uint8) { 130 | return parseTimestamp(timestamp).month; 131 | } 132 | 133 | function getDay(uint timestamp) public pure returns (uint8) { 134 | return parseTimestamp(timestamp).day; 135 | } 136 | 137 | function getHour(uint timestamp) public pure returns (uint8) { 138 | return uint8((timestamp / 60 / 60) % 24); 139 | } 140 | 141 | function getMinute(uint timestamp) public pure returns (uint8) { 142 | return uint8((timestamp / 60) % 60); 143 | } 144 | 145 | function getSecond(uint timestamp) public pure returns (uint8) { 146 | return uint8(timestamp % 60); 147 | } 148 | 149 | function getWeekday(uint timestamp) public pure returns (uint8) { 150 | return uint8((timestamp / DAY_IN_SECONDS + 4) % 7); 151 | } 152 | 153 | function toTimestamp(uint16 year, uint8 month, uint8 day) public pure returns (uint timestamp) { 154 | return toTimestamp(year, month, day, 0, 0, 0); 155 | } 156 | 157 | function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour) public pure returns (uint timestamp) { 158 | return toTimestamp(year, month, day, hour, 0, 0); 159 | } 160 | 161 | function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute) public pure returns (uint timestamp) { 162 | return toTimestamp(year, month, day, hour, minute, 0); 163 | } 164 | 165 | function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute, uint8 second) public pure returns (uint timestamp) { 166 | uint16 i; 167 | 168 | // Year 169 | for (i = ORIGIN_YEAR; i < year; i++) { 170 | if (isLeapYear(i)) { 171 | timestamp += LEAP_YEAR_IN_SECONDS; 172 | } 173 | else { 174 | timestamp += YEAR_IN_SECONDS; 175 | } 176 | } 177 | 178 | // Month 179 | uint8[12] memory monthDayCounts; 180 | monthDayCounts[0] = 31; 181 | if (isLeapYear(year)) { 182 | monthDayCounts[1] = 29; 183 | } 184 | else { 185 | monthDayCounts[1] = 28; 186 | } 187 | monthDayCounts[2] = 31; 188 | monthDayCounts[3] = 30; 189 | monthDayCounts[4] = 31; 190 | monthDayCounts[5] = 30; 191 | monthDayCounts[6] = 31; 192 | monthDayCounts[7] = 31; 193 | monthDayCounts[8] = 30; 194 | monthDayCounts[9] = 31; 195 | monthDayCounts[10] = 30; 196 | monthDayCounts[11] = 31; 197 | 198 | for (i = 1; i < month; i++) { 199 | timestamp += DAY_IN_SECONDS * monthDayCounts[i - 1]; 200 | } 201 | 202 | // Day 203 | timestamp += DAY_IN_SECONDS * (day - 1); 204 | 205 | // Hour 206 | timestamp += HOUR_IN_SECONDS * (hour); 207 | 208 | // Minute 209 | timestamp += MINUTE_IN_SECONDS * (minute); 210 | 211 | // Second 212 | timestamp += second; 213 | 214 | return timestamp; 215 | } 216 | } -------------------------------------------------------------------------------- /shared/IBattleHero.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.9; 2 | 3 | contract IBattleHero{ 4 | function transferFrom( 5 | address sender, 6 | address recipient, 7 | uint256 amount 8 | ) public virtual returns (bool) {} 9 | function balanceOf(address account) public view virtual returns (uint256) {} 10 | function allowance(address owner, address spender) public view virtual returns (uint256) {} 11 | function burn(uint256 amount) public virtual {} 12 | function burnFrom(address account, uint256 amount) public virtual {} 13 | function mint(address to, uint256 amount) public virtual {} 14 | } -------------------------------------------------------------------------------- /shared/IBattleHeroAirdrop.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.9; 3 | 4 | 5 | 6 | 7 | contract IBattleHeroAirdrop { 8 | function _getTokenAmount(uint256 _weiAmount) public view returns (uint256) {} 9 | function _getBUSDAmount(uint256 _tokenAmount) public view returns(uint256){} 10 | function tokenPrice() public view returns (uint256) {} 11 | } -------------------------------------------------------------------------------- /shared/IBattleHeroBreeder.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.9; 2 | 3 | import "./BattleHeroData.sol"; 4 | 5 | contract IBattleHeroBreeder{ 6 | function breed(address to, string memory gen) public returns(uint) {} 7 | } -------------------------------------------------------------------------------- /shared/IBattleHeroFactory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.9; 2 | 3 | import "./BattleHeroData.sol"; 4 | 5 | contract IBattleHeroFactory{ 6 | struct Hero{ 7 | address owner; 8 | string genetic; 9 | uint bornAt; 10 | uint256 index; 11 | bool exists; 12 | BattleHeroData.DeconstructedGen deconstructed; 13 | } 14 | function transferFrom(address from, address buyer, uint256 tokenId) public{} 15 | function balanceOf(address tokenOwner) public view returns (uint256) {} 16 | function burn(uint256 _value) public{} 17 | function allowance(address from, address delegate) public view returns (uint) {} 18 | function burnFrom(address from, uint256 tokenId) public returns (bool) {} 19 | function heroeOfId(uint256 tokenId) public view returns(Hero memory) { } 20 | function ownerOf(uint256 tokenId) public view virtual returns (address) { } 21 | function mint(address to, string memory genes) public virtual returns(uint){ } 22 | function isApproved(address to, uint256 tokenId) public view returns (bool){} 23 | function lockHero(uint256 tokenId ) public{} 24 | function unlockHero(uint256 tokenId) public {} 25 | function isLocked(uint256 tokenId) public view returns(bool) {} 26 | function heroesId() public view returns(uint256[] memory){} 27 | } -------------------------------------------------------------------------------- /shared/IBattleHeroGenScience.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.9; 2 | 3 | 4 | contract IBattleHeroGenScience{ 5 | enum Rarity{ 6 | COMMON, 7 | LOW_RARE, 8 | RARE, 9 | EPIC, 10 | LEGEND, 11 | MITIC 12 | } 13 | function generateWeapon(Rarity _rarity, string memory asset) public returns (string memory){} 14 | function generateWeapon(Rarity _rarity) public returns (string memory){} 15 | function generateWeapon() public returns (string memory){} 16 | function generateCharacter(Rarity _rarity, string memory asset) public returns (string memory){} 17 | function generateCharacter(Rarity _rarity) public returns (string memory){} 18 | function generateCharacter() public returns (string memory){} 19 | function generate() public returns(string memory){} 20 | function generateIntransferibleWeapon(Rarity _rarity) public returns (string memory){} 21 | function generateIntransferibleCharacter(Rarity _rarity) public returns (string memory){} 22 | } -------------------------------------------------------------------------------- /shared/IBattleHeroPE.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.9; 2 | 3 | contract IBattleHeroPE{ 4 | function balanceOf(address account) public view virtual returns (uint256) {} 5 | function mint(address to, uint256 amount) public virtual {} 6 | function scale(uint256 _peEther) public view returns(uint256){} 7 | } -------------------------------------------------------------------------------- /shared/IBattleHeroRewardWallet.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.9; 2 | 3 | contract IBattleHeroRewardWallet{ 4 | function distribute(address _bath, uint256 _amount, address to) public virtual{} 5 | } -------------------------------------------------------------------------------- /shared/Whitelist.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.9; 2 | 3 | import "../../node_modules/@openzeppelin/contracts/access/Ownable.sol"; 4 | 5 | /** 6 | * @title Whitelist 7 | * @dev The Whitelist contract has a whitelist of addresses, and provides basic authorization control functions. 8 | * @dev This simplifies the implementation of "user permissions". 9 | */ 10 | contract Whitelist is Ownable { 11 | mapping(address => bool) public whitelist; 12 | 13 | event WhitelistedAddressAdded(address addr); 14 | event WhitelistedAddressRemoved(address addr); 15 | 16 | modifier onlyWhitelisted() { 17 | require(whitelist[msg.sender], "Your are not whitelisted"); 18 | _; 19 | } 20 | 21 | function addAddressToWhitelist(address addr) onlyOwner public returns(bool success) { 22 | if (!whitelist[addr]) { 23 | whitelist[addr] = true; 24 | emit WhitelistedAddressAdded(addr); 25 | success = true; 26 | } 27 | } 28 | 29 | function addAddressesToWhitelist(address[] calldata addrs) onlyOwner public returns(bool success) { 30 | for (uint256 i = 0; i < addrs.length; i++) { 31 | if (addAddressToWhitelist(addrs[i])) { 32 | success = true; 33 | } 34 | } 35 | } 36 | 37 | function removeAddressFromWhitelist(address addr) onlyOwner public returns(bool success) { 38 | if (whitelist[addr]) { 39 | whitelist[addr] = false; 40 | emit WhitelistedAddressRemoved(addr); 41 | success = true; 42 | } 43 | } 44 | 45 | function removeAddressesFromWhitelist(address[] calldata addrs) onlyOwner public returns(bool success) { 46 | for (uint256 i = 0; i < addrs.length; i++) { 47 | if (removeAddressFromWhitelist(addrs[i])) { 48 | success = true; 49 | } 50 | } 51 | } 52 | 53 | } --------------------------------------------------------------------------------