Source Code
Overview
S Balance
More Info
ContractCreator
Latest 6 from a total of 6 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Add Admin | 16409724 | 8 days ago | IN | 0 S | 0.00005266 | ||||
Add Admin | 16409706 | 8 days ago | IN | 0 S | 0.00005267 | ||||
Set Allow Battle... | 15973384 | 10 days ago | IN | 0 S | 0.00003178 | ||||
Add Admin | 15970335 | 10 days ago | IN | 0 S | 0.00005267 | ||||
Add Admin | 15970304 | 10 days ago | IN | 0 S | 0.00005267 | ||||
Add Admin | 15970191 | 10 days ago | IN | 0 S | 0.00005267 |
Loading...
Loading
Contract Name:
PepemonBattle
Compiler Version
v0.8.6+commit.11564f7e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; pragma experimental ABIEncoderV2; import "./lib/AdminRole.sol"; import "./PepemonCardDeck.sol"; import "./iface/IPepemonCardOracle.sol"; import "./iface/IConfigurable.sol"; import "./lib/ChainLinkRngOracle.sol"; contract PepemonBattle is AdminRole, IConfigurable { event BattleCreated( address indexed player1Addr, address indexed player2Addr, uint256 battleId, uint256 p1DeckId, uint256 p2DeckId ); mapping (uint => uint) public battleIdRNGSeed; uint constant _max_inte = 8; uint constant _max_cards_on_table = 5; uint constant _refreshTurn = 5; //Attacker can either be PLAYER_ONE or PLAYER_TWO enum Attacker { PLAYER_ONE, PLAYER_TWO } //Game can either be in FIRST_HALF or SECOND_HALF enum TurnHalves { FIRST_HALF, SECOND_HALF } //Battle contains: //battleId = ID of this battle //player1, player2 = players //currentTurn //attacker //turnHalves => first half or second half? struct Battle { uint256 battleId; Player player1; Player player2; uint256 currentTurn; Attacker attacker; TurnHalves turnHalves; } // Used to keep a local copy of players battle/support cards instead of reloading // from the oracle struct PlayersCards { uint256 player1SupportCardsCount; uint256 player2SupportCardsCount; IPepemonCardOracle.BattleCardStats player1Battlecard; IPepemonCardOracle.BattleCardStats player2Battlecard; uint256[] player1SupportCards; uint256[] player2SupportCards; } //playerAddr //deckId = Id of deck //hand = keeps track of current player's stats (such as health) //totalSupportCardIds = all IDs of support cards //playedCardCount = number of cards played already struct Player { address playerAddr; uint256 deckId; Hand hand; uint256[60] totalSupportCardIds; uint256 playedCardCount; } //health - health of player's battle card // battleCardId = card id of player // currentBCstats = all stats of the player's battle cards currently // supportCardInHandIds = IDs of the support cards in your current hand // the amount of support cards a player can play is determined by intelligence // tableSupportCardStats = Number of support cards that are currently played on the table // currentSuportCards = cards on the table, based on which turn ago they were played // Notice that the number of turns is limited by _refreshTurn struct Hand { int256 health; uint256 battleCardId; CurrentBattleCardStats currentBCstats; uint256[_max_inte] supportCardInHandIds; uint256 tableSupportCardStats; TableSupportCardStats[_max_cards_on_table] tableSupportCards; } //spd, inte, def, atk, sAtk, sDef - Current stats of battle card (with powerups included) //Each param can go into the negatives struct CurrentBattleCardStats { int256 spd; uint256 inte; int256 def; int256 atk; int256 sAtk; int256 sDef; } //links supportCardID with effectMany struct TableSupportCardStats { uint256 supportCardId; IPepemonCardOracle.EffectMany effectMany; } uint256 private _nextBattleId; bool private _allowBattleAgainstOneself; IPepemonCardOracle private _cardContract; PepemonCardDeck private _deckContract; ChainLinkRngOracle private _randNrGenContract; address public configAddress; constructor(address _configAddress) { configAddress = _configAddress; _nextBattleId = 1; _allowBattleAgainstOneself = false; } function setConfigAddress(address _configAddress) external onlyAdmin { configAddress = _configAddress; } function syncConfig() external override onlyAdmin { _cardContract = IPepemonCardOracle(PepemonConfig(configAddress).contractAddresses("PepemonCardOracle")); _deckContract = PepemonCardDeck(PepemonConfig(configAddress).contractAddresses("PepemonCardDeck")); _randNrGenContract = ChainLinkRngOracle(PepemonConfig(configAddress).contractAddresses("SampleChainLinkRngOracle")); } function setAllowBattleAgainstOneself(bool allow) public onlyAdmin { _allowBattleAgainstOneself = allow; } /** * @dev Create battle * @param p1Addr address player1 * @param p1DeckId uint256 * @param p2Addr address player2 * @param p2DeckId uint256 */ function createBattle( address p1Addr, uint256 p1DeckId, address p2Addr, uint256 p2DeckId ) public onlyAdmin returns (Battle memory, uint256 battleId) { require(_allowBattleAgainstOneself || p1Addr != p2Addr, "PepemonBattle: Cannot battle yourself"); (uint256 p1BattleCardId, ) = _deckContract.decks(p1DeckId); (uint256 p2BattleCardId, ) = _deckContract.decks(p2DeckId); IPepemonCardOracle.BattleCardStats memory p1BattleCard = _cardContract.getBattleCardById(p1BattleCardId); IPepemonCardOracle.BattleCardStats memory p2BattleCard = _cardContract.getBattleCardById(p2BattleCardId); Battle memory newBattle; // Initiate battle ID newBattle.battleId = _nextBattleId; // Initiate player1 newBattle.player1.hand.health = int256(uint256(p1BattleCard.hp)); newBattle.player1.hand.battleCardId = p1BattleCardId; newBattle.player1.playerAddr = p1Addr; newBattle.player1.deckId = p1DeckId; // Initiate player2 newBattle.player2.hand.health = int256(uint256(p2BattleCard.hp)); newBattle.player2.hand.battleCardId = p2BattleCardId; newBattle.player2.playerAddr = p2Addr; newBattle.player2.deckId = p2DeckId; // Set the RNG seed battleIdRNGSeed[_nextBattleId] = _randSeed(newBattle); //Emit event emit BattleCreated(p1Addr, p2Addr, _nextBattleId, p1DeckId, p2DeckId); return (newBattle, _nextBattleId++); } function getPlayersCards( uint256 player1BattleCardId, uint256 player2BattleCardId, uint256 player1DeckId, uint256 player2DeckId ) internal view returns (PlayersCards memory) { // Get Battle Cards for Player 1 and Player 2 IPepemonCardOracle.BattleCardStats memory player1Battlecard = _cardContract.getBattleCardById(player1BattleCardId); IPepemonCardOracle.BattleCardStats memory player2Battlecard = _cardContract.getBattleCardById(player2BattleCardId); // Get Support Cards for Player 1 and Player 2 uint256[] memory player1SupportCards = _deckContract.getAllSupportCardsInDeck(player1DeckId); uint256[] memory player2SupportCards = _deckContract.getAllSupportCardsInDeck(player2DeckId); // Get Support Card count for Player 1 and Player 2 uint256 player1SupportCardsCount = _deckContract.getSupportCardCountInDeck(player1DeckId); uint256 player2SupportCardsCount = _deckContract.getSupportCardCountInDeck(player2DeckId); // Create and return the PlayersCards struct instance return PlayersCards({ player1Battlecard: player1Battlecard, player1SupportCards: player1SupportCards, player1SupportCardsCount: player1SupportCardsCount, player2Battlecard: player2Battlecard, player2SupportCards: player2SupportCards, player2SupportCardsCount: player2SupportCardsCount }); } function goForBattle(Battle memory battle) public view returns (Battle memory, address winner) { // local cache for cards and decks info to reduce gas usage PlayersCards memory cards = getPlayersCards( battle.player1.hand.battleCardId, battle.player2.hand.battleCardId, battle.player1.deckId, battle.player2.deckId ); //Initialize battle by starting the first turn battle = goForNewTurn(battle, cards); address winnerAddr; // Battle goes! while (true) { // Resolve attacker in the current turn battle = resolveAttacker(battle); // Fight battle = fight(battle); // Check if battle ended (bool isEnded, address win) = checkIfBattleEnded(battle); if (isEnded) { winnerAddr = win; break; } // Resolve turn halves battle = updateTurnInfo(battle, cards); } return (battle, winnerAddr); } //If currently in first half -> go to second half //If currently in second half -> make a new turn function updateTurnInfo(Battle memory battle, PlayersCards memory cards) internal view returns (Battle memory) { // If the current half is first, go over second half // or go over next turn if (battle.turnHalves == TurnHalves.FIRST_HALF) { battle.turnHalves = TurnHalves.SECOND_HALF; } else { battle = goForNewTurn(battle, cards); } return battle; } //Things this function does: //Reset both players hand infos back to base stats (stats with no support card powerups) //Check if support cards need to be scrambled and redealt //Redeal support cards if necessary //Calculate support card's power //Finally, draw Pepemon's intelligence number of cards. function goForNewTurn(Battle memory battle, PlayersCards memory cards) internal view returns (Battle memory) { Player memory player1 = battle.player1; Player memory player2 = battle.player2; // Load base battle card stats (stats without any powerups) // and reset both players' hand infos to base stats player1.hand.currentBCstats = getCardStats(cards.player1Battlecard); player2.hand.currentBCstats = getCardStats(cards.player2Battlecard); uint256 p1SupportCardIdsLength = cards.player1SupportCardsCount; uint256 p2SupportCardIdsLength = cards.player2SupportCardsCount; //Refresh cards every 5 turns bool isRefreshTurn = (battle.currentTurn % _refreshTurn == 0); if (isRefreshTurn) { //Need to refresh decks // Shuffle player1 support cards uint[] memory scrambled = Arrays.shuffle(cards.player1SupportCards, _randMod(69, battle)); //Copy back scrambled cards to original list for (uint i = 0 ; i < p1SupportCardIdsLength; i++){ player1.totalSupportCardIds[i]=scrambled[i]; } //Reset played card count player1.playedCardCount = 0; //Shuffling player 2 support cards //Create a pseudorandom seed and shuffle the cards uint[] memory scrambled2 = Arrays.shuffle(cards.player2SupportCards, _randMod(420, battle)); //Copy the support cards back into the list for (uint256 i = 0; i < p2SupportCardIdsLength; i++) { player2.totalSupportCardIds[i]=scrambled2[i]; } //Reset player2 played card counts player2.playedCardCount = 0; } else { //Don't need to refresh cards now // Get temp support info of previous turn's hands and calculate their effect for the new turn player1.hand = calSupportCardsOnTable(player1.hand, player2.hand); player2.hand = calSupportCardsOnTable(player2.hand, player1.hand); } // Draw player1 support cards for the new turn uint256 remainingCards = p1SupportCardIdsLength - player1.playedCardCount; // limit number of cards to be taken to prevent taking invalid cards player1.hand.currentBCstats.inte = remainingCards < player1.hand.currentBCstats.inte ? remainingCards : player1.hand.currentBCstats.inte; for (uint256 i = 0; i < player1.hand.currentBCstats.inte; i++) { // "totalSupportCardIds" array has 60 elements, max intelligence is 8 (_max_inte), each 5 rounds playedCardCount is reset, // so in total, 40 (5*8) cards could end up being used, no out of bounds errors player1.hand.supportCardInHandIds[i] = player1.totalSupportCardIds[i + player1.playedCardCount]; } player1.playedCardCount += player1.hand.currentBCstats.inte; // Draw player2 support cards for the new turn remainingCards = p2SupportCardIdsLength - player2.playedCardCount; // limit number of cards to be taken to prevent taking invalid cards player2.hand.currentBCstats.inte = remainingCards < player2.hand.currentBCstats.inte ? remainingCards : player2.hand.currentBCstats.inte; for (uint256 i = 0; i < player2.hand.currentBCstats.inte; i++) { player2.hand.supportCardInHandIds[i] = player2.totalSupportCardIds[i + player2.playedCardCount]; } player2.playedCardCount += player2.hand.currentBCstats.inte; //Update current battle info battle.player1 = player1; battle.player2 = player2; // Increment current turn number of battle battle.currentTurn++; // Go for first half in turn battle.turnHalves = TurnHalves.FIRST_HALF; return battle; } //This method calculates the battle card's stats after taking into consideration all the support cards currently being played function calSupportCardsOnTable(Hand memory hand, Hand memory oppHand) internal pure returns (Hand memory) { for (uint256 i = 0; i < hand.tableSupportCardStats; i++) { //Loop through every support card currently played //Get the support card being considered now TableSupportCardStats memory tableSupportCardStat = hand.tableSupportCards[i]; //Get the effect of that support card IPepemonCardOracle.EffectMany memory effect = tableSupportCardStat.effectMany; //If there is at least 1 turn left if (effect.numTurns >= 1) { //If the effect is for me if (effect.effectFor == IPepemonCardOracle.EffectFor.ME) { // Change my card's stats using that support card // Currently effectTo of EffectMany can be ATTACK, DEFENSE, SPEED and INTELLIGENCE //Get the statistic changed and update it //Intelligence can't go into the negatives nor above _max_inte if (effect.effectTo == IPepemonCardOracle.EffectTo.ATTACK) { hand.currentBCstats.atk += effect.power; } else if (effect.effectTo == IPepemonCardOracle.EffectTo.DEFENSE) { hand.currentBCstats.def += effect.power; } else if (effect.effectTo == IPepemonCardOracle.EffectTo.SPEED) { hand.currentBCstats.spd += effect.power; } else if (effect.effectTo == IPepemonCardOracle.EffectTo.INTELLIGENCE) { int temp; temp = int256(hand.currentBCstats.inte) + effect.power; temp = temp > int(_max_inte) ? int(_max_inte) : temp; hand.currentBCstats.inte = (temp > 0 ? uint(temp) : 0); } } else { //The card affects the opp's pepemon //Update card stats of the opp's pepemon //Make sure INT stat can't go below zero nor above _max_inte if (effect.effectTo == IPepemonCardOracle.EffectTo.ATTACK) { oppHand.currentBCstats.atk += effect.power; } else if (effect.effectTo == IPepemonCardOracle.EffectTo.DEFENSE) { oppHand.currentBCstats.def += effect.power; } else if (effect.effectTo == IPepemonCardOracle.EffectTo.SPEED) { oppHand.currentBCstats.spd += effect.power; } else if (effect.effectTo == IPepemonCardOracle.EffectTo.INTELLIGENCE) { int temp; temp = int256(oppHand.currentBCstats.inte) + effect.power; temp = temp > int(_max_inte) ? int(_max_inte) : temp; oppHand.currentBCstats.inte = (temp > 0 ? uint(temp) : 0); } } // Decrease effect numTurns by 1 since 1 turn has already passed effect.numTurns--; // Delete this one from tableSupportCardStat if all turns of the card have been exhausted if (effect.numTurns == 0) { if (i < hand.tableSupportCardStats - 1) { hand.tableSupportCards[i] = hand.tableSupportCards[hand.tableSupportCardStats - 1]; } delete hand.tableSupportCards[hand.tableSupportCardStats - 1]; hand.tableSupportCardStats--; } } } return hand; } //This method gets the current attacker function resolveAttacker(Battle memory battle) internal view returns (Battle memory) { CurrentBattleCardStats memory p1CurrentBattleCardStats = battle.player1.hand.currentBCstats; CurrentBattleCardStats memory p2CurrentBattleCardStats = battle.player2.hand.currentBCstats; if (battle.turnHalves == TurnHalves.FIRST_HALF) { //Player with highest speed card goes first if (p1CurrentBattleCardStats.spd > p2CurrentBattleCardStats.spd) { battle.attacker = Attacker.PLAYER_ONE; } else if (p1CurrentBattleCardStats.spd < p2CurrentBattleCardStats.spd) { battle.attacker = Attacker.PLAYER_TWO; } else { //Tiebreak: intelligence if (p1CurrentBattleCardStats.inte > p2CurrentBattleCardStats.inte) { battle.attacker = Attacker.PLAYER_ONE; } else if (p1CurrentBattleCardStats.inte < p2CurrentBattleCardStats.inte) { battle.attacker = Attacker.PLAYER_TWO; } else { //Second tiebreak: use RNG uint256 rand = _randMod(69420, battle) % 2; battle.attacker = (rand == 0 ? Attacker.PLAYER_ONE : Attacker.PLAYER_TWO); } } } else { //For second half, switch players battle.attacker = (battle.attacker == Attacker.PLAYER_ONE ? Attacker.PLAYER_TWO : Attacker.PLAYER_ONE); } return battle; } //Create a random seed, using the chainlink number and the addresses of the combatants as entropy function _randSeed(Battle memory battle) private view returns (uint256) { //Get the chainlink random number uint chainlinkNumber = _randNrGenContract.getRandomNumber(); //Create a new pseudorandom number using the seed and battle info as entropy //This makes sure the RNG returns a different number every time uint256 randomNumber = uint(keccak256(abi.encodePacked(block.number, chainlinkNumber, battle.player1.playerAddr, battle.player2.playerAddr))); return randomNumber; } function _randMod(uint256 seed, Battle memory battle) private view returns (uint256) { uint256 randomNumber = uint(keccak256(abi.encodePacked(seed, battle.currentTurn, battleIdRNGSeed[battle.battleId]))); return randomNumber; } //Check if battle ended by looking at player's health function checkIfBattleEnded(Battle memory battle) public pure returns (bool, address) { if (battle.player1.hand.health <= 0) { return (true, battle.player1.playerAddr); } else if (battle.player2.hand.health <= 0) { return (true, battle.player2.playerAddr); } else { return (false, address(0)); } } function fight(Battle memory battle) public view returns (Battle memory) { Hand memory atkHand; Hand memory defHand; //Get attacker and defender for current turn if (battle.attacker == Attacker.PLAYER_ONE) { atkHand = battle.player1.hand; defHand = battle.player2.hand; } else { atkHand = battle.player2.hand; defHand = battle.player1.hand; } (atkHand, defHand) = calSupportCardsInHand(atkHand, defHand); //Give 2 point advantage if weakness, 2 point disadvantage if resistance atkHand.currentBCstats.atk += resistanceWeaknessCal(atkHand, defHand); // Fight //Calculate HP loss for defending player if (atkHand.currentBCstats.atk > defHand.currentBCstats.def) { //If attacker's attack > defender's defense, find difference. That is the defending player's HP loss defHand.health -= (atkHand.currentBCstats.atk - defHand.currentBCstats.def); } else { //Otherwise, defender loses 1 HP defHand.health -= 1; } //Write updated info back into battle if (battle.attacker == Attacker.PLAYER_ONE) { battle.player1.hand = atkHand; battle.player2.hand = defHand; } else { battle.player1.hand = defHand; battle.player2.hand = atkHand; } return battle; } //We calculate the effect of every card in the player's hand function calSupportCardsInHand(Hand memory atkHand, Hand memory defHand) public view returns (Hand memory, Hand memory) { // If this card is included in player's hand, adds an additional power equal to the total of // all normal offense/defense cards bool isPower0CardIncluded = false; // Total sum of normal support cards int256 totalNormalPower = 0; // Cal attacker hand for (uint256 i = 0; i < atkHand.currentBCstats.inte; i++) { //Loop through every card the attacker has in his hand uint256 id = atkHand.supportCardInHandIds[i]; //Get the support cardStats IPepemonCardOracle.SupportCardStats memory cardStats = _cardContract.getSupportCardById(id); if (cardStats.supportCardType == IPepemonCardOracle.SupportCardType.OFFENSE) { // Card type is OFFENSE. // Calc effects of EffectOne array IPepemonCardOracle.EffectOne memory effectOne = cardStats.effectOne; //Checks if that support card is triggered and by how much it is triggered by (bool isTriggered, uint256 multiplier) = checkReqCode(atkHand, defHand, effectOne.reqCode, true); if (isTriggered) { //use triggeredPower if triggered atkHand.currentBCstats.atk += effectOne.triggeredPower * int256(multiplier); totalNormalPower += effectOne.triggeredPower * int256(multiplier); } else{ //use basePower if not atkHand.currentBCstats.atk += effectOne.basePower; totalNormalPower += effectOne.basePower; } } else if (cardStats.supportCardType == IPepemonCardOracle.SupportCardType.STRONG_OFFENSE) { // Card type is STRONG OFFENSE. //Make sure unstackable cards can't be stacked if (cardStats.unstackable) { bool isNew = true; // Check if card is new to previous cards for (uint256 j = 0; j < i; j++) { if (id == atkHand.supportCardInHandIds[j]) { isNew = false; break; } } if (!isNew) { //If it isn't - skip card continue; } // Check if card is new to temp support info cards for (uint256 j = 0; j < atkHand.tableSupportCardStats; j++) { if (id == atkHand.tableSupportCards[j].supportCardId) { isNew = false; break; } } if (!isNew) { //If it isn't - skip card continue; } } // Calc effects of EffectOne array IPepemonCardOracle.EffectOne memory effectOne = cardStats.effectOne; (bool isTriggered, uint256 multiplier) = checkReqCode(atkHand, defHand, effectOne.reqCode, true); if (isTriggered) { //If triggered: use triggered power if (multiplier > 1) { atkHand.currentBCstats.atk += effectOne.triggeredPower * int256(multiplier); } else { if (effectOne.effectTo == IPepemonCardOracle.EffectTo.STRONG_ATTACK) { // If it's a use Special Attack instead of Attack card atkHand.currentBCstats.atk = atkHand.currentBCstats.sAtk; continue; } else if (effectOne.triggeredPower == 0) { // We have a card that says ATK is increased by amount // Equal to the total of all offense cards in the current turn isPower0CardIncluded = true; continue; } atkHand.currentBCstats.atk += effectOne.triggeredPower; } } else{ //If not triggered: use base power instead atkHand.currentBCstats.atk += effectOne.basePower; totalNormalPower += effectOne.basePower; } // If card lasts for >1 turns if (cardStats.effectMany.power != 0) { // Add card to table if <5 on table currently if (atkHand.tableSupportCardStats < _max_cards_on_table) { atkHand.tableSupportCards[atkHand.tableSupportCardStats++] = TableSupportCardStats({ supportCardId: id, effectMany: cardStats.effectMany }); } } } else { // Other card type is ignored. continue; } } if (isPower0CardIncluded) { //If we have a card that says ATK is increased by amount equal to total of all offense cards atkHand.currentBCstats.atk += totalNormalPower; } // Cal defense hand isPower0CardIncluded = false; totalNormalPower = 0; for (uint256 i = 0; i < defHand.currentBCstats.inte; i++) { uint256 id = defHand.supportCardInHandIds[i]; IPepemonCardOracle.SupportCardStats memory card = _cardContract.getSupportCardById(id); if (card.supportCardType == IPepemonCardOracle.SupportCardType.DEFENSE) { // Card type is DEFENSE // Calc effects of EffectOne array IPepemonCardOracle.EffectOne memory effectOne = card.effectOne; (bool isTriggered, uint256 multiplier) = checkReqCode(atkHand, defHand, effectOne.reqCode, false); if (isTriggered) { defHand.currentBCstats.def += effectOne.triggeredPower * int256(multiplier); totalNormalPower += effectOne.triggeredPower * int256(multiplier); } else{ //If not triggered, use base power instead defHand.currentBCstats.def += effectOne.basePower; totalNormalPower += effectOne.basePower; } } else if (card.supportCardType == IPepemonCardOracle.SupportCardType.STRONG_DEFENSE) { // Card type is STRONG DEFENSE if (card.unstackable) { bool isNew = true; // Check if card is new to previous cards for (uint256 j = 0; j < i; j++) { if (id == defHand.supportCardInHandIds[j]) { isNew = false; break; } } // Check if card is new to temp support info cards for (uint256 j = 0; j < defHand.tableSupportCardStats; j++) { if (id == defHand.tableSupportCards[j].supportCardId) { isNew = false; break; } } if (!isNew) { continue; } } // Calc effects of EffectOne array IPepemonCardOracle.EffectOne memory effectOne = card.effectOne; (bool isTriggered, uint256 num) = checkReqCode(atkHand, defHand, effectOne.reqCode, false); if (isTriggered) { if (num > 0) { defHand.currentBCstats.def += effectOne.triggeredPower * int256(num); } else { if (effectOne.effectTo == IPepemonCardOracle.EffectTo.STRONG_DEFENSE) { defHand.currentBCstats.def = defHand.currentBCstats.sDef; continue; } else if (effectOne.triggeredPower == 0) { // Equal to the total of all defense cards in the current turn isPower0CardIncluded = true; continue; } defHand.currentBCstats.def += effectOne.triggeredPower; } } else{ //If not triggered, use base stats instead defHand.currentBCstats.def += effectOne.basePower; totalNormalPower += effectOne.basePower; } // If card effect lasts >1 turn if (card.effectMany.power != 0) { // Add card to table if there are <5 cards on table right now if (defHand.tableSupportCardStats < _max_cards_on_table) { defHand.tableSupportCards[defHand.tableSupportCardStats++] = TableSupportCardStats({ supportCardId: id, effectMany: card.effectMany }); } } } else { // Other card type is ignored. continue; } } if (isPower0CardIncluded) { //If a "add total of defense" card is included defHand.currentBCstats.def += totalNormalPower; } return (atkHand, defHand); } //Strip important game information (like speed, intelligence, etc.) from battle card function getCardStats(IPepemonCardOracle.BattleCardStats memory x) internal pure returns (CurrentBattleCardStats memory){ CurrentBattleCardStats memory ret; ret.spd = int(uint(x.spd)); ret.inte = x.inte; ret.def = int(uint(x.def)); ret.atk = int(uint(x.atk)); ret.sAtk = int(uint(x.sAtk)); ret.sDef = int(uint(x.sDef)); return ret; } //Checks if the requirements are satisfied for a certain code //returns bool - is satisfied? // uint - the multiplier for the card's attack power // for most cases multiplier is 1 function checkReqCode( Hand memory atkHand, Hand memory defHand, uint256 reqCode, bool isAttacker ) internal view returns (bool, uint256) { bool isTriggered = false; uint256 multiplier = 1; if (reqCode == 0) { // No requirement isTriggered = true; } else if (reqCode == 1) { // Intelligence of offense pepemon <= 5. isTriggered = (atkHand.currentBCstats.inte <= 5 ); } else if (reqCode == 2) { // Number of defense cards of defense pepemon is 0. isTriggered = true; for (uint256 i = 0; i < defHand.currentBCstats.inte; i++) { IPepemonCardOracle.SupportCardType supportCardType = _cardContract.getSupportCardTypeById( defHand.supportCardInHandIds[i] ); if (supportCardType == IPepemonCardOracle.SupportCardType.DEFENSE) { isTriggered = false; break; } } } else if (reqCode == 3) { // Each +2 offense cards of offense pepemon. return countCards(atkHand, IPepemonCardOracle.SupportCardType.OFFENSE, 2); } else if (reqCode == 4) { // Each +3 offense cards of offense pepemon. return countCards(atkHand, IPepemonCardOracle.SupportCardType.OFFENSE, 3); } else if (reqCode == 5) { // Each offense card of offense pepemon. return countCards(atkHand, IPepemonCardOracle.SupportCardType.OFFENSE, 0); } else if (reqCode == 6) { // Each +3 defense card of defense pepemon. return countCards(defHand, IPepemonCardOracle.SupportCardType.DEFENSE, 3); } else if (reqCode == 7) { // Each +4 defense card of defense pepemon. return countCards(defHand, IPepemonCardOracle.SupportCardType.DEFENSE, 4); } else if (reqCode == 8) { // Intelligence of defense pepemon <= 5. isTriggered = (defHand.currentBCstats.inte <= 5 ); } else if (reqCode == 9) { // Intelligence of defense pepemon >= 7. isTriggered = (defHand.currentBCstats.inte >= 7 ); } else if (reqCode == 10) { // Offense pepemon is using strong attack for (uint256 i = 0; i < atkHand.currentBCstats.inte; i++) { IPepemonCardOracle.SupportCardStats memory card = _cardContract.getSupportCardById( atkHand.supportCardInHandIds[i] ); if (card.supportCardType == IPepemonCardOracle.SupportCardType.STRONG_OFFENSE) { isTriggered = true; break; } } multiplier = 1; } else if (reqCode == 11) { // The current HP is less than 50% of max HP. isTriggered = lessThanHalfHP(isAttacker ? atkHand : defHand); } return (isTriggered, multiplier); } function lessThanHalfHP(Hand memory hand) internal view returns (bool){ return hand.health * 2 <= int256(uint256(_cardContract.getBattleCardById(hand.battleCardId).hp)); } function countCards(Hand memory hand, IPepemonCardOracle.SupportCardType cardType, int basePower) internal view returns (bool, uint){ uint multiplier = 0; for (uint256 i = 0; i < hand.currentBCstats.inte; i++) { IPepemonCardOracle.SupportCardStats memory card = _cardContract.getSupportCardById( hand.supportCardInHandIds[i] ); if (card.supportCardType != cardType) { continue; } IPepemonCardOracle.EffectOne memory effectOne = card.effectOne; if (effectOne.basePower == basePower || basePower == 0) { multiplier++; } } return (multiplier>0, multiplier); } function resistanceWeaknessCal(Hand memory atkHand, Hand memory defHand) internal view returns (int){ int adjustment = 0; uint battleIdAtk = atkHand.battleCardId; uint battleIdDef = defHand.battleCardId; IPepemonCardOracle.BattleCardTypes atkType = _cardContract.getBattleCardById(battleIdAtk).element; IPepemonCardOracle.BattleCardTypes defType = _cardContract.getBattleCardById(battleIdDef).element; IPepemonCardOracle.BattleCardTypes weakness = _cardContract.getWeakResist(defType).weakness; IPepemonCardOracle.BattleCardTypes resistance = _cardContract.getWeakResist(defType).resistance; if (atkType == weakness) adjustment = 2; if (atkType == resistance) adjustment = -2; return adjustment; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface LinkTokenInterface { function allowance( address owner, address spender ) external view returns ( uint256 remaining ); function approve( address spender, uint256 value ) external returns ( bool success ); function balanceOf( address owner ) external view returns ( uint256 balance ); function decimals() external view returns ( uint8 decimalPlaces ); function decreaseApproval( address spender, uint256 addedValue ) external returns ( bool success ); function increaseApproval( address spender, uint256 subtractedValue ) external; function name() external view returns ( string memory tokenName ); function symbol() external view returns ( string memory tokenSymbol ); function totalSupply() external view returns ( uint256 totalTokensIssued ); function transfer( address to, uint256 value ) external returns ( bool success ); function transferAndCall( address to, uint256 value, bytes calldata data ) external returns ( bool success ); function transferFrom( address from, address to, uint256 value ) external returns ( bool success ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./interfaces/LinkTokenInterface.sol"; import "./VRFRequestIDBase.sol"; /** **************************************************************************** * @notice Interface for contracts using VRF randomness * ***************************************************************************** * @dev PURPOSE * * @dev Reggie the Random Oracle (not his real job) wants to provide randomness * @dev to Vera the verifier in such a way that Vera can be sure he's not * @dev making his output up to suit himself. Reggie provides Vera a public key * @dev to which he knows the secret key. Each time Vera provides a seed to * @dev Reggie, he gives back a value which is computed completely * @dev deterministically from the seed and the secret key. * * @dev Reggie provides a proof by which Vera can verify that the output was * @dev correctly computed once Reggie tells it to her, but without that proof, * @dev the output is indistinguishable to her from a uniform random sample * @dev from the output space. * * @dev The purpose of this contract is to make it easy for unrelated contracts * @dev to talk to Vera the verifier about the work Reggie is doing, to provide * @dev simple access to a verifiable source of randomness. * ***************************************************************************** * @dev USAGE * * @dev Calling contracts must inherit from VRFConsumerBase, and can * @dev initialize VRFConsumerBase's attributes in their constructor as * @dev shown: * * @dev contract VRFConsumer { * @dev constuctor(<other arguments>, address _vrfCoordinator, address _link) * @dev VRFConsumerBase(_vrfCoordinator, _link) public { * @dev <initialization with other arguments goes here> * @dev } * @dev } * * @dev The oracle will have given you an ID for the VRF keypair they have * @dev committed to (let's call it keyHash), and have told you the minimum LINK * @dev price for VRF service. Make sure your contract has sufficient LINK, and * @dev call requestRandomness(keyHash, fee, seed), where seed is the input you * @dev want to generate randomness from. * * @dev Once the VRFCoordinator has received and validated the oracle's response * @dev to your request, it will call your contract's fulfillRandomness method. * * @dev The randomness argument to fulfillRandomness is the actual random value * @dev generated from your seed. * * @dev The requestId argument is generated from the keyHash and the seed by * @dev makeRequestId(keyHash, seed). If your contract could have concurrent * @dev requests open, you can use the requestId to track which seed is * @dev associated with which randomness. See VRFRequestIDBase.sol for more * @dev details. (See "SECURITY CONSIDERATIONS" for principles to keep in mind, * @dev if your contract could have multiple requests in flight simultaneously.) * * @dev Colliding `requestId`s are cryptographically impossible as long as seeds * @dev differ. (Which is critical to making unpredictable randomness! See the * @dev next section.) * * ***************************************************************************** * @dev SECURITY CONSIDERATIONS * * @dev A method with the ability to call your fulfillRandomness method directly * @dev could spoof a VRF response with any random value, so it's critical that * @dev it cannot be directly called by anything other than this base contract * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). * * @dev For your users to trust that your contract's random behavior is free * @dev from malicious interference, it's best if you can write it so that all * @dev behaviors implied by a VRF response are executed *during* your * @dev fulfillRandomness method. If your contract must store the response (or * @dev anything derived from it) and use it later, you must ensure that any * @dev user-significant behavior which depends on that stored value cannot be * @dev manipulated by a subsequent VRF request. * * @dev Similarly, both miners and the VRF oracle itself have some influence * @dev over the order in which VRF responses appear on the blockchain, so if * @dev your contract could have multiple VRF requests in flight simultaneously, * @dev you must ensure that the order in which the VRF responses arrive cannot * @dev be used to manipulate your contract's user-significant behavior. * * @dev Since the ultimate input to the VRF is mixed with the block hash of the * @dev block in which the request is made, user-provided seeds have no impact * @dev on its economic security properties. They are only included for API * @dev compatability with previous versions of this contract. * * @dev Since the block hash of the block which contains the requestRandomness * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful * @dev miner could, in principle, fork the blockchain to evict the block * @dev containing the request, forcing the request to be included in a * @dev different block with a different hash, and therefore a different input * @dev to the VRF. However, such an attack would incur a substantial economic * @dev cost. This cost scales with the number of blocks the VRF oracle waits * @dev until it calls responds to a request. */ abstract contract VRFConsumerBase is VRFRequestIDBase { /** * @notice fulfillRandomness handles the VRF response. Your contract must * @notice implement it. See "SECURITY CONSIDERATIONS" above for important * @notice principles to keep in mind when implementing your fulfillRandomness * @notice method. * * @dev VRFConsumerBase expects its subcontracts to have a method with this * @dev signature, and will call it once it has verified the proof * @dev associated with the randomness. (It is triggered via a call to * @dev rawFulfillRandomness, below.) * * @param requestId The Id initially returned by requestRandomness * @param randomness the VRF output */ function fulfillRandomness( bytes32 requestId, uint256 randomness ) internal virtual; /** * @dev In order to keep backwards compatibility we have kept the user * seed field around. We remove the use of it because given that the blockhash * enters later, it overrides whatever randomness the used seed provides. * Given that it adds no security, and can easily lead to misunderstandings, * we have removed it from usage and can now provide a simpler API. */ uint256 constant private USER_SEED_PLACEHOLDER = 0; /** * @notice requestRandomness initiates a request for VRF output given _seed * * @dev The fulfillRandomness method receives the output, once it's provided * @dev by the Oracle, and verified by the vrfCoordinator. * * @dev The _keyHash must already be registered with the VRFCoordinator, and * @dev the _fee must exceed the fee specified during registration of the * @dev _keyHash. * * @dev The _seed parameter is vestigial, and is kept only for API * @dev compatibility with older versions. It can't *hurt* to mix in some of * @dev your own randomness, here, but it's not necessary because the VRF * @dev oracle will mix the hash of the block containing your request into the * @dev VRF seed it ultimately uses. * * @param _keyHash ID of public key against which randomness is generated * @param _fee The amount of LINK to send with the request * * @return requestId unique ID for this request * * @dev The returned requestId can be used to distinguish responses to * @dev concurrent requests. It is passed as the first argument to * @dev fulfillRandomness. */ function requestRandomness( bytes32 _keyHash, uint256 _fee ) internal returns ( bytes32 requestId ) { LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, USER_SEED_PLACEHOLDER)); // This is the seed passed to VRFCoordinator. The oracle will mix this with // the hash of the block containing this request to obtain the seed/input // which is finally passed to the VRF cryptographic machinery. uint256 vRFSeed = makeVRFInputSeed(_keyHash, USER_SEED_PLACEHOLDER, address(this), nonces[_keyHash]); // nonces[_keyHash] must stay in sync with // VRFCoordinator.nonces[_keyHash][this], which was incremented by the above // successful LINK.transferAndCall (in VRFCoordinator.randomnessRequest). // This provides protection against the user repeating their input seed, // which would result in a predictable/duplicate output, if multiple such // requests appeared in the same block. nonces[_keyHash] = nonces[_keyHash] + 1; return makeRequestId(_keyHash, vRFSeed); } LinkTokenInterface immutable internal LINK; address immutable private vrfCoordinator; // Nonces for each VRF key from which randomness has been requested. // // Must stay in sync with VRFCoordinator[_keyHash][this] mapping(bytes32 /* keyHash */ => uint256 /* nonce */) private nonces; /** * @param _vrfCoordinator address of VRFCoordinator contract * @param _link address of LINK token contract * * @dev https://docs.chain.link/docs/link-token-contracts */ constructor( address _vrfCoordinator, address _link ) { vrfCoordinator = _vrfCoordinator; LINK = LinkTokenInterface(_link); } // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF // proof. rawFulfillRandomness then calls fulfillRandomness, after validating // the origin of the call function rawFulfillRandomness( bytes32 requestId, uint256 randomness ) external { require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill"); fulfillRandomness(requestId, randomness); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract VRFRequestIDBase { /** * @notice returns the seed which is actually input to the VRF coordinator * * @dev To prevent repetition of VRF output due to repetition of the * @dev user-supplied seed, that seed is combined in a hash with the * @dev user-specific nonce, and the address of the consuming contract. The * @dev risk of repetition is mostly mitigated by inclusion of a blockhash in * @dev the final seed, but the nonce does protect against repetition in * @dev requests which are included in a single block. * * @param _userSeed VRF seed input provided by user * @param _requester Address of the requesting contract * @param _nonce User-specific nonce at the time of the request */ function makeVRFInputSeed( bytes32 _keyHash, uint256 _userSeed, address _requester, uint256 _nonce ) internal pure returns ( uint256 ) { return uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce))); } /** * @notice Returns the id for this request * @param _keyHash The serviceAgreement ID to be used for this request * @param _vRFInputSeed The seed to be passed directly to the VRF * @return The id for this request * * @dev Note that _vRFInputSeed is not the seed passed by the consuming * @dev contract, but the one generated by makeVRFInputSeed */ function makeRequestId( bytes32 _keyHash, uint256 _vRFInputSeed ) internal pure returns ( bytes32 ) { return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol) pragma solidity ^0.8.0; import "./ERC1155Receiver.sol"; /** * Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens. * * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be * stuck. * * @dev _Available since v3.1._ */ contract ERC1155Holder is ERC1155Receiver { function onERC1155Received( address, address, uint256, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] memory, uint256[] memory, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Receiver.sol) pragma solidity ^0.8.0; import "../IERC1155Receiver.sol"; import "../../../utils/introspection/ERC165.sol"; /** * @dev _Available since v3.1._ */ abstract contract ERC1155Receiver is ERC165, IERC1155Receiver { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _ownerOf(tokenId); require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner or approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom(address from, address to, uint256 tokenId) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _ownerOf(tokenId) != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId, 1); // Check that tokenId was not minted by `_beforeTokenTransfer` hook require(!_exists(tokenId), "ERC721: token already minted"); unchecked { // Will not overflow unless all 2**256 token ids are minted to the same owner. // Given that tokens are minted one by one, it is impossible in practice that // this ever happens. Might change if we allow batch minting. // The ERC fails to describe this case. _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId, 1); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * This is an internal function that does not check if the sender is authorized to operate on the token. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId, 1); // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook owner = ERC721.ownerOf(tokenId); // Clear approvals delete _tokenApprovals[tokenId]; unchecked { // Cannot overflow, as that would require more tokens to be burned/transferred // out than the owner initially received through minting and transferring in. _balances[owner] -= 1; } delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId, 1); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer(address from, address to, uint256 tokenId) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId, 1); // Check that tokenId was not transferred by `_beforeTokenTransfer` hook require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); // Clear approvals from the previous owner delete _tokenApprovals[tokenId]; unchecked { // `_balances[from]` cannot overflow for the same reason as described in `_burn`: // `from`'s balance is the number of token held, which is at least one before the current // transfer. // `_balances[to]` could overflow in the conditions described in `_mint`. That would require // all 2**256 token ids to be minted, which in practice is impossible. _balances[from] -= 1; _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId, 1); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`. * - When `from` is zero, the tokens will be minted for `to`. * - When `to` is zero, ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`. * - When `from` is zero, the tokens were minted for `to`. * - When `to` is zero, ``from``'s tokens were burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {} /** * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override. * * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such * that `ownerOf(tokenId)` is `a`. */ // solhint-disable-next-line func-name-mixedcase function __unsafe_increaseBalance(address account, uint256 amount) internal { _balances[account] += amount; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IConfigurable { function syncConfig() external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; pragma experimental ABIEncoderV2; /** This contract acts as the oracle, it contains battling information for both the Pepemon Battle and Support cards **/ interface IPepemonCardOracle { enum SupportCardType { OFFENSE, STRONG_OFFENSE, DEFENSE, STRONG_DEFENSE } enum EffectTo { ATTACK, STRONG_ATTACK, DEFENSE, STRONG_DEFENSE, SPEED, INTELLIGENCE } enum EffectFor { ME, ENEMY } enum BattleCardTypes{ FIRE, GRASS, WATER, LIGHTNING, WIND, POISON, GHOST, FAIRY, EARTH, UNKNOWN, NONE } struct BattleCardStats { uint256 battleCardId; BattleCardTypes element; uint16 hp; // hitpoints uint16 spd; // speed uint16 inte; // intelligence uint16 def; // defense uint16 atk; // attack uint16 sAtk; // special attack uint16 sDef; // special defense } struct SupportCardStats { uint256 supportCardId; SupportCardType supportCardType; EffectOne effectOne; EffectMany effectMany; // If true, duplicate copies of the card in the same turn will have no extra effect. bool unstackable; // This property is for EffectMany now. // If true, assume the card is already in effect // then the same card drawn and used within a number of turns does not extend or reset duration of the effect. bool unresettable; } struct EffectOne { // If power is 0, it is equal to the total of all normal offense/defense cards in the current turn. //basePower = power if req not met int16 basePower; //triggeredPower = power if req met int16 triggeredPower; EffectTo effectTo; EffectFor effectFor; uint16 reqCode; //requirement code } struct EffectMany { int16 power; uint16 numTurns; EffectTo effectTo; EffectFor effectFor; uint16 reqCode; //requirement code } //Struct for keeping track of weakness / resistance struct elementWR{ BattleCardTypes weakness; BattleCardTypes resistance; } // mappings function battleCardStats(uint256 x) view external returns (BattleCardStats memory); function supportCardStats(uint256 x) view external returns (SupportCardStats memory); function elementDecode(BattleCardTypes x) view external returns (string memory); function weakResist(BattleCardTypes x) view external returns (elementWR memory); // other functions function addBattleCard(BattleCardStats memory cardData) external; function updateBattleCard(BattleCardStats memory cardData) external; function getBattleCardById(uint256 _id) view external returns (BattleCardStats memory); function addSupportCard(SupportCardStats memory cardData) external; function updateSupportCard(SupportCardStats memory cardData) external; function getSupportCardById(uint256 _id) view external returns (SupportCardStats memory); function getWeakResist(BattleCardTypes element) view external returns (elementWR memory); function getSupportCardTypeById(uint256 _id) view external returns (SupportCardType); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IPepemonFactory { function safeTransferFrom( address _from, address _to, uint256 _id, uint256 _amount, bytes calldata _data ) external; function setApprovalForAll( address _operator, bool _approved ) external; function balanceOf( address _owner, uint256 _id ) external view returns (uint256); function airdrop( uint256 _id, address[] memory _addresses ) external; function batchMint( uint start, uint end, address to) external; function batchMintList( uint256[] calldata ids, address to) external; function addMinter( address account ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./Roles.sol"; contract AdminRole { using Roles for Roles.Role; event AdminAdded(address indexed account); event AdminRemoved(address indexed account); Roles.Role private admins; constructor() { _addAdmin(msg.sender); } modifier onlyAdmin() { require(isAdmin(msg.sender)); _; } function isAdmin(address account) public view returns (bool) { return admins.has(account); } function addAdmin(address account) public onlyAdmin { _addAdmin(account); } function renounceAdmin() public { _removeAdmin(msg.sender); } function _addAdmin(address account) internal { admins.add(account); emit AdminAdded(account); } function _removeAdmin(address account) internal { admins.remove(account); emit AdminRemoved(account); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library Arrays { //Shuffles an array of uints with random seed function shuffle(uint256[] memory _elements, uint256 _seed) internal pure returns (uint256[] memory) { for (uint256 i = 0; i < _elements.length; i++) { //Pick random index to swap current element with uint256 n = i + _seed % (_elements.length - i); //swap elements uint256 temp = _elements[n]; _elements[n] = _elements[i]; _elements[i] = temp; //Create new pseudorandom number using seed. _seed = uint(keccak256(abi.encodePacked(_seed))); } return _elements; } // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/0a3f880753112b425160086c97623b1ab38bfec6/contracts/utils/Arrays.sol /** * @dev Searches an `array` sorted in ascending order and returns the first * index that contains a value greater or equal than `element`. If no such index * exists (i.e. all values in the array are strictly less than `element`), the array * length is returned. Time complexity O(log n). * * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound]. */ function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) { uint256 low = 0; uint256 high = array.length; if (high == 0) { return 0; } while (low < high) { uint256 mid = average(low, high); // Note that mid will always be strictly less than high (i.e. it will be a valid array index) // because Math.average rounds towards zero (it does integer division with truncation). if (unsafeMemoryAccess(array, mid) < element) { // this cannot overflow because mid < high unchecked { low = mid + 1; } } else { high = mid; } } return low; } /** * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. * * WARNING: Only use if you are certain `pos` is lower than the array length. */ function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) { assembly { res := mload(add(add(arr, 0x20), mul(pos, 0x20))) } } // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/0a3f880753112b425160086c97623b1ab38bfec6/contracts/utils/math/Math.sol /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } function isSortedAscending(uint256[] memory arr) internal pure returns (bool) { uint256 length = arr.length - 1; for (uint256 i = 0; i < length; i++) { uint256 current = unsafeMemoryAccess(arr, i); uint256 next = unsafeMemoryAccess(arr, i + 1); if (current > next) { return false; } } return true; } function contains(uint256[] memory arr, uint256 value) internal pure returns (bool) { uint256 index = lowerBoundMemory(arr, value); if (index == arr.length || unsafeMemoryAccess(arr, index) != value) { return false; } return true; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol"; import "./AdminRole.sol"; abstract contract ChainLinkRngOracle is VRFConsumerBase, AdminRole { bytes32 immutable keyHash; bytes32 public lastRequestId; uint256 internal fee; address constant maticLink = 0xb0897686c545045aFc77CF20eC7A532E3120E0F1; address constant maticVrfCoordinator = 0x3d2341ADb2D31f1c5530cDC622016af293177AE0; bytes32 constant maticKeyHash = 0xf86195cf7690c55907b2b611ebb7343a6f649bff128701cc542f0569e2c549da; address constant mumbaiLink = 0x326C977E6efc84E512bB9C30f76E30c160eD06FB; address constant mumbaiVrfCoordinator = 0x8C7382F9D8f56b33781fE506E897a4F1e2d17255; bytes32 constant mumbaiKeyHash = 0x6e75b569a01ef56d18cab6a8e71e6600d6ce853834d4a5748b720d06f878b3a4; address constant fantomTestnetLink = 0xfaFedb041c0DD4fA2Dc0d87a6B0979Ee6FA7af5F; address constant fantomTestnetVrfCoordinator = 0xbd13f08b8352A3635218ab9418E340c60d6Eb418; bytes32 constant fantomTestnetKeyHash = 0x121a143066e0f2f08b620784af77cccb35c6242460b4a8ee251b4b416abaebd4; address constant fantomLink = 0x6F43FF82CCA38001B6699a8AC47A2d0E66939407; address constant fantomVrfCoordinator = 0xd5D517aBE5cF79B7e95eC98dB0f0277788aFF634; bytes32 constant fantomKeyHash = 0x5881eea62f9876043df723cf89f0c2bb6f950da25e9dfe66995c24f919c8f8ab; mapping(bytes32 => uint256) internal results; constructor() VRFConsumerBase(fantomTestnetVrfCoordinator, fantomTestnetLink) { keyHash = fantomTestnetKeyHash; fee = 1 ether / 1000; } //Get a new random number (paying link for it) //Only callable by admin function getNewRandomNumber() public onlyAdmin returns (bytes32 requestId) { require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet"); lastRequestId = requestRandomness(keyHash, fee); return lastRequestId; } /** * Callback function used by VRF Coordinator */ function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override { results[requestId] = randomness; } function fetchNumberByRequestId(bytes32 _requestId) public view returns (uint256) { return results[_requestId]; } //Get most recent random number and use that as randomness source function getRandomNumber() public view returns (uint256){ return fetchNumberByRequestId(lastRequestId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./AdminRole.sol"; import "../iface/IConfigurable.sol"; /** * @notice This contract stores the addresses of all and any other contracts used by Pepemon * @dev This contract must be added as an Admin on contracts before "syncContractConfig" can be called. */ contract PepemonConfig is AdminRole { struct ContractDisplayData { address contractAddress; string contractName; } string[] private contactsNames; mapping(string => address) public contractAddresses; /** * @dev Actual implementation for both setContractAddress and batchSetContractAddress, making a call to * a common 'internal' function uses less gas than calling a 'public' one */ function setContractAddressInternal(string calldata contractName, address contractAddress, bool callSync) internal { require(contractAddress != address(0)); // If its the first time adding the contract, store its name in the array if (contractAddresses[contractName] == address(0)) { contactsNames.push(contractName); } contractAddresses[contractName] = contractAddress; if (callSync) { IConfigurable(contractAddress).syncConfig(); } } /** * @notice Adds or updates contracts addresses associated by contract names * @param contractName Name of the contract that will be stored * @param contractAddress Address of the contract that will be stored * @param callSync When true, the function "syncConfig" of the contract being stored will be invoked */ function setContractAddress( string calldata contractName, address contractAddress, bool callSync ) external onlyAdmin { setContractAddressInternal(contractName, contractAddress, callSync); } /** * @notice Batch version of `setContractAddress` * @param contractNameList Names of the contracts that will be stored * @param contractAddressesList Addresses of the contracts that will be stored * @param callSyncList When true, the function "syncConfig" of the contracts being stored will be invoked */ function batchSetContractAddress( string[] calldata contractNameList, address[] calldata contractAddressesList, bool[] calldata callSyncList ) external onlyAdmin { uint256 len = contractNameList.length; require(len == contractAddressesList.length && len == callSyncList.length, "Mismatching batch length"); for (uint256 i = 0; i < len; ++i) { setContractAddressInternal(contractNameList[i], contractAddressesList[i], callSyncList[i]); } } /** * @dev Tries to call "syncConfig" from the address of the contract in `contractName`, this might fail if * the target contract does not have this contract (PepemonConfig) added as an Admin, or if `contractName` is not * associated with any contract */ function syncContractConfig(string calldata contractName) external onlyAdmin { require(contractAddresses[contractName] != address(0)); IConfigurable(contractAddresses[contractName]).syncConfig(); } /** * @dev Batch version of syncContractConfig */ function batchSyncContractConfig(string[] calldata contractNames) external onlyAdmin { uint256 len = contractNames.length; for (uint256 i = 0; i < len; ++i) { require(contractAddresses[contractNames[i]] != address(0)); IConfigurable(contractAddresses[contractNames[i]]).syncConfig(); } } /** * @dev Displays contracts names and addresses. */ function getContracts() external view returns (ContractDisplayData[] memory data) { uint256 len = contactsNames.length; data = new ContractDisplayData[](len); for (uint256 i = 0; i < len; ++i) { string memory contractName = contactsNames[i]; data[i].contractName = contractName; data[i].contractAddress = contractAddresses[contractName]; } return data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Roles * @dev Library for managing addresses assigned to a Role. */ library Roles { struct Role { mapping (address => bool) bearer; } /** * @dev give an account access to this role */ function add(Role storage role, address account) internal { require(account != address(0)); require(!has(role, account)); role.bearer[account] = true; } /** * @dev remove an account's access to this role */ function remove(Role storage role, address account) internal { require(account != address(0)); require(has(role, account)); role.bearer[account] = false; } /** * @dev check if an account has this role * @return bool */ function has(Role storage role, address account) internal view returns (bool) { require(account != address(0)); return role.bearer[account]; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; //pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "./iface/IPepemonFactory.sol"; import "./iface/IPepemonCardOracle.sol"; import "./lib/AdminRole.sol"; import "./lib/Arrays.sol"; import "./lib/PepemonConfig.sol"; import "./lib/AdminRole.sol"; import "./lib/ChainLinkRngOracle.sol"; contract PepemonCardDeck is ERC721, ERC1155Holder, AdminRole, IConfigurable { using SafeMath for uint256; struct Deck { uint256 battleCardId; uint256 supportCardCount; mapping(uint256 => SupportCardType) supportCardTypes; uint256[] supportCardTypeList; } struct SupportCardType { uint256 supportCardId; uint256 count; uint256 pointer; bool isEntity; } struct SupportCardRequest { uint256 supportCardId; uint256 amount; } uint256 public MAX_SUPPORT_CARDS; uint256 public MIN_SUPPORT_CARDS; // cards allowed to be picked on when creating the Starter Deck uint256[] public allowedInitialDeckBattleCards; uint256[] allowedInitialDeckSupportCards; uint256 initialDeckSupportCardAmount; // set this to 0 to disable minting test cards. uint256 maxMintTestCardId; uint256 minMintTestCardId; uint256 nextDeckId; address public configAddress; address public factoryAddress; address public randNrGenContract; mapping(uint256 => Deck) public decks; mapping(address => uint256[]) public playerToDecks; constructor(address _configAddress) ERC721("Pepedeck", "Pepedeck") { nextDeckId = 1; MAX_SUPPORT_CARDS = 60; MIN_SUPPORT_CARDS = 40; minMintTestCardId = 1; configAddress = _configAddress; } /** * @dev Override supportInterface . */ function supportsInterface( bytes4 interfaceId ) public view virtual override(ERC721, ERC1155Receiver) returns (bool) { return super.supportsInterface(interfaceId); } // MODIFIERS modifier sendersDeck(uint256 _deckId) { require(msg.sender == ownerOf(_deckId), "PepemonCardDeck: Not your deck"); _; } // PUBLIC METHODS function setConfigAddress(address _configAddress) external onlyAdmin { configAddress = _configAddress; } function syncConfig() external override onlyAdmin { factoryAddress = PepemonConfig(configAddress).contractAddresses("PepemonFactory"); } function setMaxSupportCards(uint256 _maxSupportCards) public onlyAdmin { MAX_SUPPORT_CARDS = _maxSupportCards; } function setMinSupportCards(uint256 _minSupportCards) public onlyAdmin { MIN_SUPPORT_CARDS = _minSupportCards; } function setRandNrGenContractAddress(address randOracleAddress) public onlyAdmin { randNrGenContract = randOracleAddress; } function setInitialDeckOptions( uint256[] calldata battleCardIds, uint256[] calldata supportCards, uint256 maxInitialSupportCards ) public onlyAdmin { require(Arrays.isSortedAscending(battleCardIds)); require(maxInitialSupportCards <= MAX_SUPPORT_CARDS); initialDeckSupportCardAmount = maxInitialSupportCards; allowedInitialDeckBattleCards = battleCardIds; allowedInitialDeckSupportCards = supportCards; } // ALLOW TEST MINTING function setMintingCards(uint256 minCardId, uint256 maxCardId) public onlyAdmin { maxMintTestCardId = maxCardId; minMintTestCardId = minCardId; } /** * @dev right now there are 40 different cards that can be minted, but the maximum is configurable with maxMintTestCard. * setting maxMintTestCard to 0 disables this card minting. */ function mintCards() public { require(maxMintTestCardId > 0, "Minting test cards is disabled"); IPepemonFactory(factoryAddress).batchMint(minMintTestCardId, maxMintTestCardId, msg.sender); } function mintInitialDeck(uint256 battleCardId) public { require(Arrays.contains(allowedInitialDeckBattleCards, battleCardId), "Invalid battlecard"); require(playerToDecks[msg.sender].length == 0, "Not your first deck"); // battlecard + support cards uint amount = initialDeckSupportCardAmount + 1; uint256[] memory cards = new uint256[](amount); // First step: Mint cards uint256 allowedCardsCount = allowedInitialDeckSupportCards.length; uint256 randomNumber = randSeed(); cards[0] = battleCardId; // begin from index 1 instead of 0 because battlecard was already added for (uint256 i = 1; i < amount; ++i) { randomNumber = uint256(keccak256(abi.encodePacked(i, randomNumber))); cards[i] = allowedInitialDeckSupportCards[randomNumber % allowedCardsCount]; } // mint cards directly for this contract instead of msg.sender, so that we dont have to // transfer it back and forth IPepemonFactory(factoryAddress).batchMintList(cards, address(this)); // Second step: Add cards into new the deck uint256 newDeckId = createDeckInternal(); // no need to call addBattleCardToDeck since the new deck never had a battlecard before, plus // the battlecard is already owned by this contract decks[newDeckId].battleCardId = battleCardId; // begin from index 1 again because battlecard is in index 0 for (uint256 i = 1; i < amount; ++i) { addSupportCardToDeckDirectly(newDeckId, cards[i], 1); } } function createDeck() public { createDeckInternal(); } function addBattleCardToDeck(uint256 deckId, uint256 battleCardId) public sendersDeck(deckId) { require( IPepemonFactory(factoryAddress).balanceOf(msg.sender, battleCardId) >= 1, "PepemonCardDeck: Don't own battle card" ); require(battleCardId != decks[deckId].battleCardId, "PepemonCardDeck: Card already in deck"); uint256 oldBattleCardId = decks[deckId].battleCardId; decks[deckId].battleCardId = battleCardId; IPepemonFactory(factoryAddress).safeTransferFrom(msg.sender, address(this), battleCardId, 1, ""); returnBattleCardFromDeck(oldBattleCardId); } function removeBattleCardFromDeck(uint256 _deckId) public sendersDeck(_deckId) { uint256 oldBattleCardId = decks[_deckId].battleCardId; decks[_deckId].battleCardId = 0; returnBattleCardFromDeck(oldBattleCardId); } function addSupportCardsToDeck( uint256 deckId, SupportCardRequest[] memory supportCards ) public sendersDeck(deckId) { for (uint256 i = 0; i < supportCards.length; i++) { addSupportCardToDeck(deckId, supportCards[i].supportCardId, supportCards[i].amount); } } function removeSupportCardsFromDeck( uint256 _deckId, SupportCardRequest[] memory _supportCards ) public sendersDeck(_deckId) { for (uint256 i = 0; i < _supportCards.length; i++) { removeSupportCardFromDeck(_deckId, _supportCards[i].supportCardId, _supportCards[i].amount); } } // INTERNALS function createDeckInternal() internal returns (uint256) { _safeMint(msg.sender, nextDeckId); playerToDecks[msg.sender].push(nextDeckId); uint256 playerDeck = nextDeckId; nextDeckId = nextDeckId.add(1); return playerDeck; } function addSupportCardToDeck(uint256 _deckId, uint256 _supportCardId, uint256 _amount) internal { require(MAX_SUPPORT_CARDS >= decks[_deckId].supportCardCount.add(_amount), "PepemonCardDeck: Deck overflow"); require( IPepemonFactory(factoryAddress).balanceOf(msg.sender, _supportCardId) >= _amount, "PepemonCardDeck: You don't have enough of this card" ); addSupportCardToDeckDirectly(_deckId, _supportCardId, _amount); IPepemonFactory(factoryAddress).safeTransferFrom(msg.sender, address(this), _supportCardId, _amount, ""); } function addSupportCardToDeckDirectly(uint256 _deckId, uint256 _supportCardId, uint256 _amount) internal { if (!decks[_deckId].supportCardTypes[_supportCardId].isEntity) { decks[_deckId].supportCardTypes[_supportCardId] = SupportCardType({ supportCardId: _supportCardId, count: _amount, pointer: decks[_deckId].supportCardTypeList.length, isEntity: true }); // Prepend the ID to the list decks[_deckId].supportCardTypeList.push(_supportCardId); } else { SupportCardType storage supportCard = decks[_deckId].supportCardTypes[_supportCardId]; supportCard.count = supportCard.count.add(_amount); } decks[_deckId].supportCardCount = decks[_deckId].supportCardCount.add(_amount); } function removeSupportCardFromDeck(uint256 _deckId, uint256 _supportCardId, uint256 _amount) internal { SupportCardType storage supportCardList = decks[_deckId].supportCardTypes[_supportCardId]; supportCardList.count = supportCardList.count.sub(_amount); decks[_deckId].supportCardCount = decks[_deckId].supportCardCount.sub(_amount); if (supportCardList.count == 0) { uint256 lastItemIndex = decks[_deckId].supportCardTypeList.length - 1; // update the pointer of the item to be swapped uint256 lastSupportCardId = decks[_deckId].supportCardTypeList[lastItemIndex]; decks[_deckId].supportCardTypes[lastSupportCardId].pointer = supportCardList.pointer; // swap the last item of the list with the one to be deleted decks[_deckId].supportCardTypeList[supportCardList.pointer] = decks[_deckId].supportCardTypeList[ lastItemIndex ]; decks[_deckId].supportCardTypeList.pop(); delete decks[_deckId].supportCardTypes[_supportCardId]; } IPepemonFactory(factoryAddress).safeTransferFrom(address(this), msg.sender, _supportCardId, _amount, ""); } function returnBattleCardFromDeck(uint256 _battleCardId) internal { if (_battleCardId != 0) { IPepemonFactory(factoryAddress).safeTransferFrom(address(this), msg.sender, _battleCardId, 1, ""); } } // VIEWS function getDeckCount(address player) public view returns (uint256) { return playerToDecks[player].length; } function getBattleCardInDeck(uint256 _deckId) public view returns (uint256) { return decks[_deckId].battleCardId; } function getCardTypesInDeck(uint256 _deckId) public view returns (uint256[] memory) { Deck storage deck = decks[_deckId]; uint256[] memory supportCardTypes = new uint256[](deck.supportCardTypeList.length); for (uint256 i = 0; i < deck.supportCardTypeList.length; i++) { supportCardTypes[i] = deck.supportCardTypeList[i]; } return supportCardTypes; } function getCountOfCardTypeInDeck(uint256 _deckId, uint256 _cardTypeId) public view returns (uint256) { return decks[_deckId].supportCardTypes[_cardTypeId].count; } function getSupportCardCountInDeck(uint256 deckId) public view returns (uint256) { return decks[deckId].supportCardCount; } /** * @dev Returns array of support cards for a deck * @param _deckId uint256 ID of the deck */ function getAllSupportCardsInDeck(uint256 _deckId) public view returns (uint256[] memory) { Deck storage deck = decks[_deckId]; uint256[] memory supportCards = new uint256[](deck.supportCardCount); uint256 idx = 0; for (uint256 i = 0; i < deck.supportCardTypeList.length; i++) { uint256 supportCardId = deck.supportCardTypeList[i]; uint256 count = deck.supportCardTypes[supportCardId].count; for (uint256 j = 0; j < count; j++) { supportCards[idx++] = supportCardId; } } return supportCards; } /** * @dev Shuffles deck * @param _deckId uint256 ID of the deck */ function shuffleDeck(uint256 _deckId, uint256 _seed) public view returns (uint256[] memory) { uint256[] memory totalSupportCards = getAllSupportCardsInDeck(_deckId); return Arrays.shuffle(totalSupportCards, _seed); } //Create a random seed function randSeed() private view returns (uint256) { //Get the chainlink random number uint chainlinkNumber = ChainLinkRngOracle(randNrGenContract).getRandomNumber(); //Create a new pseudorandom number using the seed and block info as entropy //This makes sure the RNG returns a different number every time uint256 randomNumber = uint(keccak256(abi.encodePacked(block.number, block.timestamp, chainlinkNumber))); return randomNumber; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
[{"inputs":[{"internalType":"address","name":"_configAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"AdminAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"AdminRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player1Addr","type":"address"},{"indexed":true,"internalType":"address","name":"player2Addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"battleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"p1DeckId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"p2DeckId","type":"uint256"}],"name":"BattleCreated","type":"event"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"battleIdRNGSeed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"atkHand","type":"tuple"},{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"defHand","type":"tuple"}],"name":"calSupportCardsInHand","outputs":[{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"","type":"tuple"},{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"battleId","type":"uint256"},{"components":[{"internalType":"address","name":"playerAddr","type":"address"},{"internalType":"uint256","name":"deckId","type":"uint256"},{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"hand","type":"tuple"},{"internalType":"uint256[60]","name":"totalSupportCardIds","type":"uint256[60]"},{"internalType":"uint256","name":"playedCardCount","type":"uint256"}],"internalType":"struct PepemonBattle.Player","name":"player1","type":"tuple"},{"components":[{"internalType":"address","name":"playerAddr","type":"address"},{"internalType":"uint256","name":"deckId","type":"uint256"},{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"hand","type":"tuple"},{"internalType":"uint256[60]","name":"totalSupportCardIds","type":"uint256[60]"},{"internalType":"uint256","name":"playedCardCount","type":"uint256"}],"internalType":"struct PepemonBattle.Player","name":"player2","type":"tuple"},{"internalType":"uint256","name":"currentTurn","type":"uint256"},{"internalType":"enum PepemonBattle.Attacker","name":"attacker","type":"uint8"},{"internalType":"enum PepemonBattle.TurnHalves","name":"turnHalves","type":"uint8"}],"internalType":"struct PepemonBattle.Battle","name":"battle","type":"tuple"}],"name":"checkIfBattleEnded","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"configAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"p1Addr","type":"address"},{"internalType":"uint256","name":"p1DeckId","type":"uint256"},{"internalType":"address","name":"p2Addr","type":"address"},{"internalType":"uint256","name":"p2DeckId","type":"uint256"}],"name":"createBattle","outputs":[{"components":[{"internalType":"uint256","name":"battleId","type":"uint256"},{"components":[{"internalType":"address","name":"playerAddr","type":"address"},{"internalType":"uint256","name":"deckId","type":"uint256"},{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"hand","type":"tuple"},{"internalType":"uint256[60]","name":"totalSupportCardIds","type":"uint256[60]"},{"internalType":"uint256","name":"playedCardCount","type":"uint256"}],"internalType":"struct PepemonBattle.Player","name":"player1","type":"tuple"},{"components":[{"internalType":"address","name":"playerAddr","type":"address"},{"internalType":"uint256","name":"deckId","type":"uint256"},{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"hand","type":"tuple"},{"internalType":"uint256[60]","name":"totalSupportCardIds","type":"uint256[60]"},{"internalType":"uint256","name":"playedCardCount","type":"uint256"}],"internalType":"struct PepemonBattle.Player","name":"player2","type":"tuple"},{"internalType":"uint256","name":"currentTurn","type":"uint256"},{"internalType":"enum PepemonBattle.Attacker","name":"attacker","type":"uint8"},{"internalType":"enum PepemonBattle.TurnHalves","name":"turnHalves","type":"uint8"}],"internalType":"struct PepemonBattle.Battle","name":"","type":"tuple"},{"internalType":"uint256","name":"battleId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"battleId","type":"uint256"},{"components":[{"internalType":"address","name":"playerAddr","type":"address"},{"internalType":"uint256","name":"deckId","type":"uint256"},{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"hand","type":"tuple"},{"internalType":"uint256[60]","name":"totalSupportCardIds","type":"uint256[60]"},{"internalType":"uint256","name":"playedCardCount","type":"uint256"}],"internalType":"struct PepemonBattle.Player","name":"player1","type":"tuple"},{"components":[{"internalType":"address","name":"playerAddr","type":"address"},{"internalType":"uint256","name":"deckId","type":"uint256"},{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"hand","type":"tuple"},{"internalType":"uint256[60]","name":"totalSupportCardIds","type":"uint256[60]"},{"internalType":"uint256","name":"playedCardCount","type":"uint256"}],"internalType":"struct PepemonBattle.Player","name":"player2","type":"tuple"},{"internalType":"uint256","name":"currentTurn","type":"uint256"},{"internalType":"enum PepemonBattle.Attacker","name":"attacker","type":"uint8"},{"internalType":"enum PepemonBattle.TurnHalves","name":"turnHalves","type":"uint8"}],"internalType":"struct PepemonBattle.Battle","name":"battle","type":"tuple"}],"name":"fight","outputs":[{"components":[{"internalType":"uint256","name":"battleId","type":"uint256"},{"components":[{"internalType":"address","name":"playerAddr","type":"address"},{"internalType":"uint256","name":"deckId","type":"uint256"},{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"hand","type":"tuple"},{"internalType":"uint256[60]","name":"totalSupportCardIds","type":"uint256[60]"},{"internalType":"uint256","name":"playedCardCount","type":"uint256"}],"internalType":"struct PepemonBattle.Player","name":"player1","type":"tuple"},{"components":[{"internalType":"address","name":"playerAddr","type":"address"},{"internalType":"uint256","name":"deckId","type":"uint256"},{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"hand","type":"tuple"},{"internalType":"uint256[60]","name":"totalSupportCardIds","type":"uint256[60]"},{"internalType":"uint256","name":"playedCardCount","type":"uint256"}],"internalType":"struct PepemonBattle.Player","name":"player2","type":"tuple"},{"internalType":"uint256","name":"currentTurn","type":"uint256"},{"internalType":"enum PepemonBattle.Attacker","name":"attacker","type":"uint8"},{"internalType":"enum PepemonBattle.TurnHalves","name":"turnHalves","type":"uint8"}],"internalType":"struct PepemonBattle.Battle","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"battleId","type":"uint256"},{"components":[{"internalType":"address","name":"playerAddr","type":"address"},{"internalType":"uint256","name":"deckId","type":"uint256"},{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"hand","type":"tuple"},{"internalType":"uint256[60]","name":"totalSupportCardIds","type":"uint256[60]"},{"internalType":"uint256","name":"playedCardCount","type":"uint256"}],"internalType":"struct PepemonBattle.Player","name":"player1","type":"tuple"},{"components":[{"internalType":"address","name":"playerAddr","type":"address"},{"internalType":"uint256","name":"deckId","type":"uint256"},{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"hand","type":"tuple"},{"internalType":"uint256[60]","name":"totalSupportCardIds","type":"uint256[60]"},{"internalType":"uint256","name":"playedCardCount","type":"uint256"}],"internalType":"struct PepemonBattle.Player","name":"player2","type":"tuple"},{"internalType":"uint256","name":"currentTurn","type":"uint256"},{"internalType":"enum PepemonBattle.Attacker","name":"attacker","type":"uint8"},{"internalType":"enum PepemonBattle.TurnHalves","name":"turnHalves","type":"uint8"}],"internalType":"struct PepemonBattle.Battle","name":"battle","type":"tuple"}],"name":"goForBattle","outputs":[{"components":[{"internalType":"uint256","name":"battleId","type":"uint256"},{"components":[{"internalType":"address","name":"playerAddr","type":"address"},{"internalType":"uint256","name":"deckId","type":"uint256"},{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"hand","type":"tuple"},{"internalType":"uint256[60]","name":"totalSupportCardIds","type":"uint256[60]"},{"internalType":"uint256","name":"playedCardCount","type":"uint256"}],"internalType":"struct PepemonBattle.Player","name":"player1","type":"tuple"},{"components":[{"internalType":"address","name":"playerAddr","type":"address"},{"internalType":"uint256","name":"deckId","type":"uint256"},{"components":[{"internalType":"int256","name":"health","type":"int256"},{"internalType":"uint256","name":"battleCardId","type":"uint256"},{"components":[{"internalType":"int256","name":"spd","type":"int256"},{"internalType":"uint256","name":"inte","type":"uint256"},{"internalType":"int256","name":"def","type":"int256"},{"internalType":"int256","name":"atk","type":"int256"},{"internalType":"int256","name":"sAtk","type":"int256"},{"internalType":"int256","name":"sDef","type":"int256"}],"internalType":"struct PepemonBattle.CurrentBattleCardStats","name":"currentBCstats","type":"tuple"},{"internalType":"uint256[8]","name":"supportCardInHandIds","type":"uint256[8]"},{"internalType":"uint256","name":"tableSupportCardStats","type":"uint256"},{"components":[{"internalType":"uint256","name":"supportCardId","type":"uint256"},{"components":[{"internalType":"int16","name":"power","type":"int16"},{"internalType":"uint16","name":"numTurns","type":"uint16"},{"internalType":"enum IPepemonCardOracle.EffectTo","name":"effectTo","type":"uint8"},{"internalType":"enum IPepemonCardOracle.EffectFor","name":"effectFor","type":"uint8"},{"internalType":"uint16","name":"reqCode","type":"uint16"}],"internalType":"struct IPepemonCardOracle.EffectMany","name":"effectMany","type":"tuple"}],"internalType":"struct PepemonBattle.TableSupportCardStats[5]","name":"tableSupportCards","type":"tuple[5]"}],"internalType":"struct PepemonBattle.Hand","name":"hand","type":"tuple"},{"internalType":"uint256[60]","name":"totalSupportCardIds","type":"uint256[60]"},{"internalType":"uint256","name":"playedCardCount","type":"uint256"}],"internalType":"struct PepemonBattle.Player","name":"player2","type":"tuple"},{"internalType":"uint256","name":"currentTurn","type":"uint256"},{"internalType":"enum PepemonBattle.Attacker","name":"attacker","type":"uint8"},{"internalType":"enum PepemonBattle.TurnHalves","name":"turnHalves","type":"uint8"}],"internalType":"struct PepemonBattle.Battle","name":"","type":"tuple"},{"internalType":"address","name":"winner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"allow","type":"bool"}],"name":"setAllowBattleAgainstOneself","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_configAddress","type":"address"}],"name":"setConfigAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"syncConfig","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162003d2838038062003d2883398101604081905262000034916200014c565b6200003f3362000074565b600680546001600160a01b0319166001600160a01b039290921691909117905560016002556003805460ff191690556200017e565b6200008f816000620000c660201b620013ac1790919060201c565b6040516001600160a01b038216907f44d6d25963f097ad14f29f06854a01f575648a1ef82f30e562ccd3889717e33990600090a250565b6001600160a01b038116620000da57600080fd5b620000e6828262000116565b15620000f157600080fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b60006001600160a01b0382166200012c57600080fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b6000602082840312156200015f57600080fd5b81516001600160a01b03811681146200017757600080fd5b9392505050565b613b9a806200018e6000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c806383a12de91161008c578063d6c3187111610066578063d6c31871146101c9578063d8963fc4146101f4578063daf9812014610207578063ee56b3911461022757600080fd5b806383a12de91461018d5780638bad0c0a146101a0578063c6b34e1c146101a857600080fd5b8063108a3b42146100d457806320de985c1461010b57806324d7806c1461012c578063704802751461014f5780637cdb32cd14610164578063839fcd5214610185575b600080fd5b6100e76100e236600461332f565b610255565b6040805192151583526001600160a01b039091166020830152015b60405180910390f35b61011e6101193660046133ad565b61029f565b6040516101029291906137f5565b61013f61013a366004613112565b610acf565b6040519015158152602001610102565b61016261015d366004613112565b610ae1565b005b61017761017236600461332f565b610aff565b6040516101029291906137b0565b610162610b9f565b61016261019b366004613112565b610de6565b610162610e1a565b6101bb6101b6366004613153565b610e25565b6040516101029291906137d8565b6006546101dc906001600160a01b031681565b6040516001600160a01b039091168152602001610102565b610162610202366004613248565b611237565b61021a61021536600461332f565b61125c565b60405161010291906137a1565b61024761023536600461352d565b60016020526000908152604090205481565b604051908152602001610102565b600080600083602001516040015160000151136102785750506020015151600191565b6040808401510151516000126102945750506040015151600191565b506000928392509050565b6102a7612b3b565b6102af612b3b565b60008060005b8660400151602001518110156106a1576000876060015182600881106102dd576102dd613acc565b6020020151600354604051634ca7d96360e11b8152600481018390529192506000916101009091046001600160a01b03169063994fb2c6906024016101c06040518083038186803b15801561033157600080fd5b505afa158015610345573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061036991906133e4565b905060008160200151600381111561038357610383613ab6565b141561043d576000816040015190506000806103aa8c8c856080015161ffff1660016113f8565b9150915081156104035780836020015160010b6103c79190613953565b8c604001516060018181516103dc91906138fa565b90525060208301516103f290829060010b613953565b6103fc90886138fa565b9650610435565b826000015160010b8c6040015160600181815161042091906138fa565b90525082516104329060010b886138fa565b96505b50505061068c565b60018160200151600381111561045557610455613ab6565b14156106855780608001511561051a57600160005b848110156104af578a60600151816008811061048857610488613acc565b602002015184141561049d57600091506104af565b806104a781613a63565b91505061046a565b50806104bd5750505061068f565b60005b8a6080015181101561050a578a60a0015181600581106104e2576104e2613acc565b6020020151518414156104f8576000915061050a565b8061050281613a63565b9150506104c0565b50806105185750505061068f565b505b60008160400151905060008061053b8c8c856080015161ffff1660016113f8565b9150915081156105ed57600181111561057e5780836020015160010b6105619190613953565b8c6040015160600181815161057691906138fa565b90525061061f565b60018360400151600581111561059657610596613ab6565b14156105b65750505050604088015160808101516060909101525061068f565b602083015160010b6105d05760019750505050505061068f565b826020015160010b8c6040015160600181815161057691906138fa565b826000015160010b8c6040015160600181815161060a91906138fa565b905250825161061c9060010b886138fa565b96505b60608401515160010b156104355760058c60800151101561043557604080518082019091528581526060850151602082015260a08d015160808e0180519061066682613a63565b90526005811061067857610678613acc565b602002015250505061068c565b505061068f565b50505b8061069981613a63565b9150506102b5565b5081156106c2578086604001516060018181516106be91906138fa565b9052505b506000905080805b856040015160200151811015610aa4576000866060015182600881106106f2576106f2613acc565b6020020151600354604051634ca7d96360e11b8152600481018390529192506000916101009091046001600160a01b03169063994fb2c6906024016101c06040518083038186803b15801561074657600080fd5b505afa15801561075a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077e91906133e4565b905060028160200151600381111561079857610798613ab6565b1415610852576000816040015190506000806107bf8c8c856080015161ffff1660006113f8565b9150915081156108185780836020015160010b6107dc9190613953565b8b604001516040018181516107f191906138fa565b905250602083015161080790829060010b613953565b61081190886138fa565b965061084a565b826000015160010b8b6040015160400181815161083591906138fa565b90525082516108479060010b886138fa565b96505b505050610a8f565b60038160200151600381111561086a5761086a613ab6565b1415610a885780608001511561092257600160005b848110156108c4578960600151816008811061089d5761089d613acc565b60200201518414156108b257600091506108c4565b806108bc81613a63565b91505061087f565b5060005b8960800151811015610912578960a0015181600581106108ea576108ea613acc565b6020020151518414156109005760009150610912565b8061090a81613a63565b9150506108c8565b508061092057505050610a92565b505b6000816040015190506000806109438c8c856080015161ffff1660006113f8565b9150915081156109f05780156109835780836020015160010b6109669190613953565b8b6040015160400181815161097b91906138fa565b905250610a22565b60038360400151600581111561099b5761099b613ab6565b14156109b9575050505060408781015160a081015191015250610a92565b602083015160010b6109d357600197505050505050610a92565b826020015160010b8b6040015160400181815161097b91906138fa565b826000015160010b8b60400151604001818151610a0d91906138fa565b9052508251610a1f9060010b886138fa565b96505b60608401515160010b1561084a5760058b60800151101561084a57604080518082019091528581526060850151602082015260a08c015160808d01805190610a6982613a63565b905260058110610a7b57610a7b613acc565b6020020152505050610a8f565b5050610a92565b50505b80610a9c81613a63565b9150506106ca565b508115610ac557808560400151604001818151610ac191906138fa565b9052505b5093949293505050565b6000610adb8183611713565b92915050565b610aea33610acf565b610af357600080fd5b610afc81611748565b50565b610b07612b82565b600080610b3e846020015160400151602001518560400151604001516020015186602001516020015187604001516020015161178a565b9050610b4a8482611ade565b935060005b610b5885611e42565b9450610b638561125c565b9450600080610b7187610255565b915091508115610b84579150610b979050565b610b8e8785611faf565b96505050610b4f565b939492505050565b610ba833610acf565b610bb157600080fd5b600654604051637733e61560e11b8152602060048201526011602482015270506570656d6f6e436172644f7261636c6560781b60448201526001600160a01b039091169063ee67cc2a9060640160206040518083038186803b158015610c1657600080fd5b505afa158015610c2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4e9190613136565b60038054610100600160a81b0319166101006001600160a01b0393841602179055600654604051637733e61560e11b815260206004820152600f60248201526e506570656d6f6e436172644465636b60881b604482015291169063ee67cc2a9060640160206040518083038186803b158015610cc957600080fd5b505afa158015610cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d019190613136565b600480546001600160a01b039283166001600160a01b0319909116178155600654604051637733e61560e11b815292169163ee67cc2a91610d74910160208082526018908201527f53616d706c65436861696e4c696e6b526e674f7261636c650000000000000000604082015260600190565b60206040518083038186803b158015610d8c57600080fd5b505afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613136565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b610def33610acf565b610df857600080fd5b600680546001600160a01b0319166001600160a01b0392909216919091179055565b610e2333611ff5565b565b610e2d612b82565b6000610e3833610acf565b610e4157600080fd5b60035460ff1680610e645750836001600160a01b0316866001600160a01b031614155b610ec25760405162461bcd60e51b815260206004820152602560248201527f506570656d6f6e426174746c653a2043616e6e6f7420626174746c6520796f756044820152643939b2b63360d91b606482015260840160405180910390fd5b6004805460405163a090195d60e01b81529182018790526000916001600160a01b039091169063a090195d90602401604080518083038186803b158015610f0857600080fd5b505afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f40919061355f565b506004805460405163a090195d60e01b81529182018790529192506000916001600160a01b03169063a090195d90602401604080518083038186803b158015610f8857600080fd5b505afa158015610f9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc0919061355f565b50600354604051632552294360e11b8152600481018590529192506000916101009091046001600160a01b031690634aa45286906024016101206040518083038186803b15801561101057600080fd5b505afa158015611024573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110489190613280565b600354604051632552294360e11b8152600481018590529192506000916101009091046001600160a01b031690634aa45286906024016101206040518083038186803b15801561109757600080fd5b505afa1580156110ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110cf9190613280565b90506110d9612b82565b600254816000018181525050826040015161ffff1681602001516040015160000181815250508481602001516040015160200181815250508a8160200151600001906001600160a01b031690816001600160a01b0316815250508981602001516020018181525050816040015161ffff168160400151604001516000018181525050838160400151604001516020018181525050888160400151600001906001600160a01b031690816001600160a01b03168152505087816040015160200181815250506111a681612037565b6002805460009081526001602090815260409182902093909355905481519081529182018c905281018990526001600160a01b03808b1691908d16907f120b95ba2da84b9e69c1acba6099b801de6f291523db8bdf56b0c268b6f2c42c9060600160405180910390a3600280548291600061122083613a63565b919050559650965050505050505b94509492505050565b61124033610acf565b61124957600080fd5b6003805460ff1916911515919091179055565b611264612b82565b61126c612b3b565b611274612b3b565b60008460800151600181111561128c5761128c613ab6565b14156112ad57836020015160400151915083604001516040015190506112c4565b836040015160400151915083602001516040015190505b6112ce828261029f565b90925090506112dd828261211d565b82604001516060018181516112f291906138fa565b9052506040808201518101519083015160600151131561133f5780604001516040015182604001516060015161132891906139d8565b815182906113379083906139d8565b905250611356565b60018160000181815161135291906139d8565b9052505b60008460800151600181111561136e5761136e613ab6565b141561138e576020840151604090810183905280850151018190526113a4565b6020840151604090810182905280850151018290525b509192915050565b6001600160a01b0381166113bf57600080fd5b6113c98282611713565b156113d357600080fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b6000808060018561140c5760019150611706565b856001141561142957600588604001516020015111159150611706565b856002141561152c576001915060005b87604001516020015181101561152657600354606089015160009161010090046001600160a01b031690634bcb961390846008811061147a5761147a613acc565b60200201516040518263ffffffff1660e01b815260040161149d91815260200190565b60206040518083038186803b1580156114b557600080fd5b505afa1580156114c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ed9190613265565b9050600281600381111561150357611503613ab6565b1415611513576000935050611526565b508061151e81613a63565b915050611439565b50611706565b856003141561154d5761154288600060026123c7565b93509350505061122e565b85600414156115635761154288600060036123c7565b856005141561157857611542886000806123c7565b856006141561158e5761154287600260036123c7565b85600714156115a45761154287600260046123c7565b85600814156115c157600587604001516020015111159150611706565b85600914156115de57600787604001516020015110159150611706565b85600a14156116e65760005b8860400151602001518110156116dc5760035460608a015160009161010090046001600160a01b03169063994fb2c690846008811061162b5761162b613acc565b60200201516040518263ffffffff1660e01b815260040161164e91815260200190565b6101c06040518083038186803b15801561166757600080fd5b505afa15801561167b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169f91906133e4565b90506001816020015160038111156116b9576116b9613ab6565b14156116c95760019350506116dc565b50806116d481613a63565b9150506115ea565b5060019050611706565b85600b141561170657611703856116fd5787612504565b88612504565b91505b9097909650945050505050565b60006001600160a01b03821661172857600080fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b6117536000826113ac565b6040516001600160a01b038216907f44d6d25963f097ad14f29f06854a01f575648a1ef82f30e562ccd3889717e33990600090a250565b611792612bd4565b600354604051632552294360e11b81526004810187905260009161010090046001600160a01b031690634aa45286906024016101206040518083038186803b1580156117dd57600080fd5b505afa1580156117f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118159190613280565b600354604051632552294360e11b8152600481018890529192506000916101009091046001600160a01b031690634aa45286906024016101206040518083038186803b15801561186457600080fd5b505afa158015611878573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189c9190613280565b600480546040516337260b2960e11b81529182018890529192506000916001600160a01b031690636e4c16529060240160006040518083038186803b1580156118e457600080fd5b505afa1580156118f8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611920919081019061319b565b600480546040516337260b2960e11b81529182018890529192506000916001600160a01b031690636e4c16529060240160006040518083038186803b15801561196857600080fd5b505afa15801561197c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526119a4919081019061319b565b60048054604051639895d74960e01b81529182018a90529192506000916001600160a01b031690639895d7499060240160206040518083038186803b1580156119ec57600080fd5b505afa158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190613546565b60048054604051639895d74960e01b81529182018a90529192506000916001600160a01b031690639895d7499060240160206040518083038186803b158015611a6c57600080fd5b505afa158015611a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa49190613546565b6040805160c08101825293845260208401919091528201959095526060810193909352608083019190915260a08201529695505050505050565b611ae6612b82565b602083015160408085015190840151611afe906125ae565b60408084015101526060840151611b14906125ae565b6040808301510152835160208501516060870151600090611b3790600590613a7e565b1590508015611c30576000611b5a8860800151611b5560458c612614565b612671565b905060005b84811015611bae57818181518110611b7957611b79613acc565b6020026020010151876060015182603c8110611b9757611b97613acc565b602002015280611ba681613a63565b915050611b5f565b5060006080870181905260a0890151611bcd90611b556101a48d612614565b905060005b84811015611c2157818181518110611bec57611bec613acc565b6020026020010151876060015182603c8110611c0a57611c0a613acc565b602002015280611c1981613a63565b915050611bd2565b50506000608086015250611c5c565b611c428560400151856040015161275c565b6040808701829052850151611c569161275c565b60408501525b6000856080015184611c6e9190613a17565b9050856040015160400151602001518110611c955785604001516040015160200151611c97565b805b60408088015101516020015260005b86604001516040015160200151811015611d145760608701516080880151611cce908361393b565b603c8110611cde57611cde613acc565b60200201518760400151606001518260088110611cfd57611cfd613acc565b602002015280611d0c81613a63565b915050611ca6565b508560400151604001516020015186608001818151611d33919061393b565b9052506080850151611d459084613a17565b9050846040015160400151602001518110611d6c5784604001516040015160200151611d6e565b805b60408087015101516020015260005b85604001516040015160200151811015611deb5760608601516080870151611da5908361393b565b603c8110611db557611db5613acc565b60200201518660400151606001518260088110611dd457611dd4613acc565b602002015280611de381613a63565b915050611d7d565b508460400151604001516020015185608001818151611e0a919061393b565b905250602089018690526040890185905260608901805190611e2b82613a63565b90525050600060a089015250959695505050505050565b611e4a612b82565b6020820151604090810151810151818401518201519091015160008460a001516001811115611e7b57611e7b613ab6565b1415611f5457805182511315611e9b57600060808501815b9052506113a4565b805182511215611ebf576080840160015b90816001811115611e9357611e93613ab6565b806020015182602001511115611eda57608084016000611eac565b806020015182602001511015611ef557608084016001611eac565b60006002611f0662010f2c87612614565b611f109190613a7e565b90508015611f1f576001611f22565b60005b85608001906001811115611f3857611f38613ab6565b90816001811115611f4b57611f4b613ab6565b905250506113a4565b600084608001516001811115611f6c57611f6c613ab6565b14611f78576000611f7b565b60015b84608001906001811115611f9157611f91613ab6565b90816001811115611fa457611fa4613ab6565b905250509192915050565b611fb7612b82565b60008360a001516001811115611fcf57611fcf613ab6565b1415611fe157600160a0840152611fee565b611feb8383611ade565b92505b5090919050565b612000600082612af3565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f90600090a250565b600080600560009054906101000a90046001600160a01b03166001600160a01b031663dbdff2c16040518163ffffffff1660e01b815260040160206040518083038186803b15801561208857600080fd5b505afa15801561209c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c09190613546565b602084810151516040958601515186514381850152808801949094526bffffffffffffffffffffffff19606092831b811683860152911b166074830152845180830360680181526088909201909452805193019290922092915050565b60208281015190820151600354604051632552294360e11b815260048101849052600093849390929091849161010090046001600160a01b031690634aa45286906024016101206040518083038186803b15801561217a57600080fd5b505afa15801561218e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b29190613280565b60200151600354604051632552294360e11b8152600481018590529192506000916101009091046001600160a01b031690634aa45286906024016101206040518083038186803b15801561220557600080fd5b505afa158015612219573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223d9190613280565b6020015160035460405163b230345360e01b81529192506000916101009091046001600160a01b03169063b23034539061227b908590600401613787565b604080518083038186803b15801561229257600080fd5b505afa1580156122a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ca91906134d2565b5160035460405163b230345360e01b81529192506000916101009091046001600160a01b03169063b230345390612305908690600401613787565b604080518083038186803b15801561231c57600080fd5b505afa158015612330573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235491906134d2565b60200151905081600a81111561236c5761236c613ab6565b84600a81111561237e5761237e613ab6565b141561238957600296505b80600a81111561239b5761239b613ab6565b84600a8111156123ad576123ad613ab6565b14156123b95760011996505b509498975050505050505050565b6000806000805b8660400151602001518110156124f557600354606088015160009161010090046001600160a01b03169063994fb2c690846008811061240f5761240f613acc565b60200201516040518263ffffffff1660e01b815260040161243291815260200190565b6101c06040518083038186803b15801561244b57600080fd5b505afa15801561245f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061248391906133e4565b905086600381111561249757612497613ab6565b816020015160038111156124ad576124ad613ab6565b146124b857506124e3565b6040810151805160010b8714806124cd575086155b156124e057836124dc81613a63565b9450505b50505b806124ed81613a63565b9150506123ce565b50801515969095509350505050565b6003546020820151604051632552294360e11b8152600481019190915260009161010090046001600160a01b031690634aa45286906024016101206040518083038186803b15801561255557600080fd5b505afa158015612569573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258d9190613280565b6040015161ffff16826000015160026125a69190613953565b131592915050565b6125b6612c16565b6125be612c16565b60608084015161ffff90811683526080808601518216602085015260a0808701518316604086015260c087015183169385019390935260e086015182169084015261010090940151909316928101929092525090565b6060810151815160009081526001602090815260408083205490519293849361265193889391019283526020830191909152604082015260600190565b60408051808303601f190181529190528051602090910120949350505050565b606060005b83518110156113a457600081855161268e9190613a17565b6126989085613a7e565b6126a2908361393b565b905060008582815181106126b8576126b8613acc565b602002602001015190508583815181106126d4576126d4613acc565b60200260200101518683815181106126ee576126ee613acc565b6020026020010181815250508086848151811061270d5761270d613acc565b6020026020010181815250508460405160200161272c91815260200190565b6040516020818303038152906040528051906020012060001c94505050808061275490613a63565b915050612676565b612764612b3b565b60005b83608001518110156113a45760008460a00151826005811061278b5761278b613acc565b602002015190506000816020015190506001816020015161ffff1610612ade576000816060015160018111156127c3576127c3613ab6565b14156128f3576000816040015160058111156127e1576127e1613ab6565b141561280c57806000015160010b866040015160600181815161280491906138fa565b905250612a10565b60028160400151600581111561282457612824613ab6565b141561284757806000015160010b866040015160400181815161280491906138fa565b60048160400151600581111561285f5761285f613ab6565b141561288257806000015160010b866040015160000181815161280491906138fa565b60058160400151600581111561289a5761289a613ab6565b14156128ee576000816000015160010b8760400151602001516128bd91906138fa565b9050600881136128cd57806128d0565b60085b9050600081136128e15760006128e3565b805b604088015160200152505b612a10565b60008160400151600581111561290b5761290b613ab6565b141561292e57806000015160010b856040015160600181815161280491906138fa565b60028160400151600581111561294657612946613ab6565b141561296957806000015160010b856040015160400181815161280491906138fa565b60048160400151600581111561298157612981613ab6565b14156129a457806000015160010b856040015160000181815161280491906138fa565b6005816040015160058111156129bc576129bc613ab6565b1415612a10576000816000015160010b8660400151602001516129df91906138fa565b9050600881136129ef57806129f2565b60085b905060008113612a03576000612a05565b805b604087015160200152505b60208101805190612a2082613a2e565b61ffff90811690915260208301511615159050612ade5760018660800151612a489190613a17565b831015612a96578560a0015160018760800151612a659190613a17565b60058110612a7557612a75613acc565b60200201518660a001518460058110612a9057612a90613acc565b60200201525b8560a0015160018760800151612aac9190613a17565b60058110612abc57612abc613acc565b60200201612ac8612c4c565b905260808601805190612ada82613a4c565b9052505b50508080612aeb90613a63565b915050612767565b6001600160a01b038116612b0657600080fd5b612b108282611713565b612b1957600080fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b6040518060c001604052806000815260200160008152602001612b5c612c16565b8152602001612b69612c90565b815260200160008152602001612b7d612caf565b905290565b6040518060c0016040528060008152602001612b9c612cdc565b8152602001612ba9612cdc565b81526020016000815260200160006001811115612bc857612bc8613ab6565b81526020016000905290565b6040518060c001604052806000815260200160008152602001612bf5612d15565b8152602001612c02612d15565b815260200160608152602001606081525090565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051806040016040528060008152602001612b7d6040805160a0810182526000808252602082018190529091820190815260200160008152600060209091015290565b6040518061010001604052806008906020820280368337509192915050565b6040518060a001604052806005905b612cc6612c4c565b815260200190600190039081612cbe5790505090565b6040805160a08101825260008082526020820152908101612cfb612b3b565b8152602001612d08612d62565b8152602001600081525090565b60408051610120810190915260008082526020820190815260006020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e09091015290565b604051806107800160405280603c906020820280368337509192915050565b600082601f830112612d9257600080fd5b612d9a61383b565b8083856103c086011115612dad57600080fd5b60005b6005811015612e6c5781870360c080821215612dcb57600080fd5b612dd3613812565b84358152602060a080601f1986011215612dec57600080fd5b612df461383b565b945081870135612e0381613b45565b8552604087810135612e1481613b54565b86840152606088810135612e2781613b38565b8083890152506080915081890135612e3e81613b2b565b908701529087013590612e5082613b54565b8501528181019390935286529401939190910190600101612db0565b509095945050505050565b600082601f830112612e8857600080fd5b60405161010080820182811067ffffffffffffffff82111715612ead57612ead613ae2565b6040528184828101871015612ec157600080fd5b600092505b6008831015612ee657803582526001929092019160209182019101612ec6565b509195945050505050565b8051612efc81613b1d565b919050565b8051600b8110612efc57600080fd5b805160048110612efc57600080fd5b600060a08284031215612f3157600080fd5b612f3961383b565b90508151612f4681613b45565b81526020820151612f5681613b54565b60208201526040820151612f6981613b38565b60408201526060820151612f7c81613b2b565b60608201526080820151612f8f81613b54565b608082015292915050565b60008183036105e0811215612fae57600080fd5b612fb661385e565b9150823582526020830135602083015260c0603f1982011215612fd857600080fd5b50612fe161385e565b60408301358152606083013560208201526080830135604082015260a0830135606082015260c0830135608082015260e083013560a08201528060408301525061302f836101008401612e77565b6060820152610200820135608082015261304d836102208401612d81565b60a082015292915050565b6000610dc0828403121561306b57600080fd5b61307361383b565b9050813561308081613b08565b8152602082810135818301526130998460408501612f9a565b60408301528361063f8401126130ae57600080fd5b6130b66138a5565b806106208501610da08601878111156130ce57600080fd5b60005b603c8110156130ee578235855293850193918501916001016130d1565b5082606087015280356080870152505050505092915050565b8051612efc81613b54565b60006020828403121561312457600080fd5b813561312f81613b08565b9392505050565b60006020828403121561314857600080fd5b815161312f81613b08565b6000806000806080858703121561316957600080fd5b843561317481613b08565b935060208501359250604085013561318b81613b08565b9396929550929360600135925050565b600060208083850312156131ae57600080fd5b825167ffffffffffffffff808211156131c657600080fd5b818501915085601f8301126131da57600080fd5b8151818111156131ec576131ec613ae2565b8060051b91506131fd8483016138c9565b8181528481019084860184860187018a101561321857600080fd5b600095505b8386101561323b57805183526001959095019491860191860161321d565b5098975050505050505050565b60006020828403121561325a57600080fd5b813561312f81613b1d565b60006020828403121561327757600080fd5b61312f82612f10565b6000610120828403121561329357600080fd5b61329b613881565b825181526132ab60208401612f01565b60208201526132bc60408401613107565b60408201526132cd60608401613107565b60608201526132de60808401613107565b60808201526132ef60a08401613107565b60a082015261330060c08401613107565b60c082015261331160e08401613107565b60e0820152610100613324818501613107565b908201529392505050565b6000611c00828403121561334257600080fd5b61334a61385e565b8235815261335b8460208501613058565b602082015261336e84610de08501613058565b6040820152611ba08301356060820152611bc083013561338d81613b2b565b6080820152611be08301356133a181613b2b565b60a08201529392505050565b600080610bc083850312156133c157600080fd5b6133cb8484612f9a565b91506133db846105e08501612f9a565b90509250929050565b60008183036101c08112156133f857600080fd5b61340061385e565b8351815261341060208501612f10565b602082015260a0603f198301121561342757600080fd5b61342f61383b565b9150604084015161343f81613b45565b8252606084015161344f81613b45565b6020830152608084015161346281613b38565b604083015260a084015161347581613b2b565b606083015260c084015161348881613b54565b6080830152604081018290526134a18560e08601612f1f565b60608201526134b36101808501612ef1565b60808201526134c56101a08501612ef1565b60a0820152949350505050565b6000604082840312156134e457600080fd5b6040516040810181811067ffffffffffffffff8211171561350757613507613ae2565b60405261351383612f01565b815261352160208401612f01565b60208201529392505050565b60006020828403121561353f57600080fd5b5035919050565b60006020828403121561355857600080fd5b5051919050565b6000806040838503121561357257600080fd5b505080516020909101519092909150565b8060005b600581101561360f578151805185526020808201519150815160010b8187015280820151604061ffff808316828a015281850151925060609150600683106135d1576135d1613ab6565b88820192909252830151906080906135e883613af8565b88820192909252929092015190911660a086015260c0909401939190910190600101613587565b50505050565b8060005b600881101561360f578151845260209384019390910190600101613619565b80518252602081015161364e6020840182613720565b506040810151613662610de0840182613720565b506060810151611ba0830152608081015161367c81613af8565b611bc083015260a081015161369081613af8565b80611be0840152505050565b80518252602081015160208301526040810151805160408401526020810151606084015260408101516080840152606081015160a0840152608081015160c084015260a081015160e08401525060608101516136fc610100840182613615565b50608081015161020083015260a081015161371b610220840182613583565b505050565b80516001600160a01b03168252602080820151818401526040808301519061374a9085018261369c565b506060820151610620840160005b603c81101561377557825182529183019190830190600101613758565b5050505060800151610da09190910152565b60208101600b831061379b5761379b613ab6565b91905290565b611c008101610adb8284613638565b611c2081016137bf8285613638565b6001600160a01b0392909216611c009190910152919050565b611c2081016137e78285613638565b82611c008301529392505050565b610bc08101613804828561369c565b61312f6105e083018461369c565b6040805190810167ffffffffffffffff8111828210171561383557613835613ae2565b60405290565b60405160a0810167ffffffffffffffff8111828210171561383557613835613ae2565b60405160c0810167ffffffffffffffff8111828210171561383557613835613ae2565b604051610120810167ffffffffffffffff8111828210171561383557613835613ae2565b604051610780810167ffffffffffffffff8111828210171561383557613835613ae2565b604051601f8201601f1916810167ffffffffffffffff811182821017156138f2576138f2613ae2565b604052919050565b600080821280156001600160ff1b038490038513161561391c5761391c613aa0565b600160ff1b839003841281161561393557613935613aa0565b50500190565b6000821982111561394e5761394e613aa0565b500190565b60006001600160ff1b038184138284138082168684048611161561397957613979613aa0565b600160ff1b600087128281168783058912161561399857613998613aa0565b600087129250878205871284841616156139b4576139b4613aa0565b878505871281841616156139ca576139ca613aa0565b505050929093029392505050565b60008083128015600160ff1b8501841216156139f6576139f6613aa0565b6001600160ff1b0384018313811615613a1157613a11613aa0565b50500390565b600082821015613a2957613a29613aa0565b500390565b600061ffff821680613a4257613a42613aa0565b6000190192915050565b600081613a5b57613a5b613aa0565b506000190190565b6000600019821415613a7757613a77613aa0565b5060010190565b600082613a9b57634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60028110610afc57610afc613ab6565b6001600160a01b0381168114610afc57600080fd5b8015158114610afc57600080fd5b60028110610afc57600080fd5b60068110610afc57600080fd5b8060010b8114610afc57600080fd5b61ffff81168114610afc57600080fdfea26469706673582212206bd6f2e4b1e64547079c5bff9fba8c4c1984d9f158221f9d05d45226ad5a473f64736f6c634300080600330000000000000000000000009460dfaad34bc55ee564a6851c58dfc390d7d4ac
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c806383a12de91161008c578063d6c3187111610066578063d6c31871146101c9578063d8963fc4146101f4578063daf9812014610207578063ee56b3911461022757600080fd5b806383a12de91461018d5780638bad0c0a146101a0578063c6b34e1c146101a857600080fd5b8063108a3b42146100d457806320de985c1461010b57806324d7806c1461012c578063704802751461014f5780637cdb32cd14610164578063839fcd5214610185575b600080fd5b6100e76100e236600461332f565b610255565b6040805192151583526001600160a01b039091166020830152015b60405180910390f35b61011e6101193660046133ad565b61029f565b6040516101029291906137f5565b61013f61013a366004613112565b610acf565b6040519015158152602001610102565b61016261015d366004613112565b610ae1565b005b61017761017236600461332f565b610aff565b6040516101029291906137b0565b610162610b9f565b61016261019b366004613112565b610de6565b610162610e1a565b6101bb6101b6366004613153565b610e25565b6040516101029291906137d8565b6006546101dc906001600160a01b031681565b6040516001600160a01b039091168152602001610102565b610162610202366004613248565b611237565b61021a61021536600461332f565b61125c565b60405161010291906137a1565b61024761023536600461352d565b60016020526000908152604090205481565b604051908152602001610102565b600080600083602001516040015160000151136102785750506020015151600191565b6040808401510151516000126102945750506040015151600191565b506000928392509050565b6102a7612b3b565b6102af612b3b565b60008060005b8660400151602001518110156106a1576000876060015182600881106102dd576102dd613acc565b6020020151600354604051634ca7d96360e11b8152600481018390529192506000916101009091046001600160a01b03169063994fb2c6906024016101c06040518083038186803b15801561033157600080fd5b505afa158015610345573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061036991906133e4565b905060008160200151600381111561038357610383613ab6565b141561043d576000816040015190506000806103aa8c8c856080015161ffff1660016113f8565b9150915081156104035780836020015160010b6103c79190613953565b8c604001516060018181516103dc91906138fa565b90525060208301516103f290829060010b613953565b6103fc90886138fa565b9650610435565b826000015160010b8c6040015160600181815161042091906138fa565b90525082516104329060010b886138fa565b96505b50505061068c565b60018160200151600381111561045557610455613ab6565b14156106855780608001511561051a57600160005b848110156104af578a60600151816008811061048857610488613acc565b602002015184141561049d57600091506104af565b806104a781613a63565b91505061046a565b50806104bd5750505061068f565b60005b8a6080015181101561050a578a60a0015181600581106104e2576104e2613acc565b6020020151518414156104f8576000915061050a565b8061050281613a63565b9150506104c0565b50806105185750505061068f565b505b60008160400151905060008061053b8c8c856080015161ffff1660016113f8565b9150915081156105ed57600181111561057e5780836020015160010b6105619190613953565b8c6040015160600181815161057691906138fa565b90525061061f565b60018360400151600581111561059657610596613ab6565b14156105b65750505050604088015160808101516060909101525061068f565b602083015160010b6105d05760019750505050505061068f565b826020015160010b8c6040015160600181815161057691906138fa565b826000015160010b8c6040015160600181815161060a91906138fa565b905250825161061c9060010b886138fa565b96505b60608401515160010b156104355760058c60800151101561043557604080518082019091528581526060850151602082015260a08d015160808e0180519061066682613a63565b90526005811061067857610678613acc565b602002015250505061068c565b505061068f565b50505b8061069981613a63565b9150506102b5565b5081156106c2578086604001516060018181516106be91906138fa565b9052505b506000905080805b856040015160200151811015610aa4576000866060015182600881106106f2576106f2613acc565b6020020151600354604051634ca7d96360e11b8152600481018390529192506000916101009091046001600160a01b03169063994fb2c6906024016101c06040518083038186803b15801561074657600080fd5b505afa15801561075a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077e91906133e4565b905060028160200151600381111561079857610798613ab6565b1415610852576000816040015190506000806107bf8c8c856080015161ffff1660006113f8565b9150915081156108185780836020015160010b6107dc9190613953565b8b604001516040018181516107f191906138fa565b905250602083015161080790829060010b613953565b61081190886138fa565b965061084a565b826000015160010b8b6040015160400181815161083591906138fa565b90525082516108479060010b886138fa565b96505b505050610a8f565b60038160200151600381111561086a5761086a613ab6565b1415610a885780608001511561092257600160005b848110156108c4578960600151816008811061089d5761089d613acc565b60200201518414156108b257600091506108c4565b806108bc81613a63565b91505061087f565b5060005b8960800151811015610912578960a0015181600581106108ea576108ea613acc565b6020020151518414156109005760009150610912565b8061090a81613a63565b9150506108c8565b508061092057505050610a92565b505b6000816040015190506000806109438c8c856080015161ffff1660006113f8565b9150915081156109f05780156109835780836020015160010b6109669190613953565b8b6040015160400181815161097b91906138fa565b905250610a22565b60038360400151600581111561099b5761099b613ab6565b14156109b9575050505060408781015160a081015191015250610a92565b602083015160010b6109d357600197505050505050610a92565b826020015160010b8b6040015160400181815161097b91906138fa565b826000015160010b8b60400151604001818151610a0d91906138fa565b9052508251610a1f9060010b886138fa565b96505b60608401515160010b1561084a5760058b60800151101561084a57604080518082019091528581526060850151602082015260a08c015160808d01805190610a6982613a63565b905260058110610a7b57610a7b613acc565b6020020152505050610a8f565b5050610a92565b50505b80610a9c81613a63565b9150506106ca565b508115610ac557808560400151604001818151610ac191906138fa565b9052505b5093949293505050565b6000610adb8183611713565b92915050565b610aea33610acf565b610af357600080fd5b610afc81611748565b50565b610b07612b82565b600080610b3e846020015160400151602001518560400151604001516020015186602001516020015187604001516020015161178a565b9050610b4a8482611ade565b935060005b610b5885611e42565b9450610b638561125c565b9450600080610b7187610255565b915091508115610b84579150610b979050565b610b8e8785611faf565b96505050610b4f565b939492505050565b610ba833610acf565b610bb157600080fd5b600654604051637733e61560e11b8152602060048201526011602482015270506570656d6f6e436172644f7261636c6560781b60448201526001600160a01b039091169063ee67cc2a9060640160206040518083038186803b158015610c1657600080fd5b505afa158015610c2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4e9190613136565b60038054610100600160a81b0319166101006001600160a01b0393841602179055600654604051637733e61560e11b815260206004820152600f60248201526e506570656d6f6e436172644465636b60881b604482015291169063ee67cc2a9060640160206040518083038186803b158015610cc957600080fd5b505afa158015610cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d019190613136565b600480546001600160a01b039283166001600160a01b0319909116178155600654604051637733e61560e11b815292169163ee67cc2a91610d74910160208082526018908201527f53616d706c65436861696e4c696e6b526e674f7261636c650000000000000000604082015260600190565b60206040518083038186803b158015610d8c57600080fd5b505afa158015610da0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc49190613136565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b610def33610acf565b610df857600080fd5b600680546001600160a01b0319166001600160a01b0392909216919091179055565b610e2333611ff5565b565b610e2d612b82565b6000610e3833610acf565b610e4157600080fd5b60035460ff1680610e645750836001600160a01b0316866001600160a01b031614155b610ec25760405162461bcd60e51b815260206004820152602560248201527f506570656d6f6e426174746c653a2043616e6e6f7420626174746c6520796f756044820152643939b2b63360d91b606482015260840160405180910390fd5b6004805460405163a090195d60e01b81529182018790526000916001600160a01b039091169063a090195d90602401604080518083038186803b158015610f0857600080fd5b505afa158015610f1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f40919061355f565b506004805460405163a090195d60e01b81529182018790529192506000916001600160a01b03169063a090195d90602401604080518083038186803b158015610f8857600080fd5b505afa158015610f9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc0919061355f565b50600354604051632552294360e11b8152600481018590529192506000916101009091046001600160a01b031690634aa45286906024016101206040518083038186803b15801561101057600080fd5b505afa158015611024573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110489190613280565b600354604051632552294360e11b8152600481018590529192506000916101009091046001600160a01b031690634aa45286906024016101206040518083038186803b15801561109757600080fd5b505afa1580156110ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110cf9190613280565b90506110d9612b82565b600254816000018181525050826040015161ffff1681602001516040015160000181815250508481602001516040015160200181815250508a8160200151600001906001600160a01b031690816001600160a01b0316815250508981602001516020018181525050816040015161ffff168160400151604001516000018181525050838160400151604001516020018181525050888160400151600001906001600160a01b031690816001600160a01b03168152505087816040015160200181815250506111a681612037565b6002805460009081526001602090815260409182902093909355905481519081529182018c905281018990526001600160a01b03808b1691908d16907f120b95ba2da84b9e69c1acba6099b801de6f291523db8bdf56b0c268b6f2c42c9060600160405180910390a3600280548291600061122083613a63565b919050559650965050505050505b94509492505050565b61124033610acf565b61124957600080fd5b6003805460ff1916911515919091179055565b611264612b82565b61126c612b3b565b611274612b3b565b60008460800151600181111561128c5761128c613ab6565b14156112ad57836020015160400151915083604001516040015190506112c4565b836040015160400151915083602001516040015190505b6112ce828261029f565b90925090506112dd828261211d565b82604001516060018181516112f291906138fa565b9052506040808201518101519083015160600151131561133f5780604001516040015182604001516060015161132891906139d8565b815182906113379083906139d8565b905250611356565b60018160000181815161135291906139d8565b9052505b60008460800151600181111561136e5761136e613ab6565b141561138e576020840151604090810183905280850151018190526113a4565b6020840151604090810182905280850151018290525b509192915050565b6001600160a01b0381166113bf57600080fd5b6113c98282611713565b156113d357600080fd5b6001600160a01b0316600090815260209190915260409020805460ff19166001179055565b6000808060018561140c5760019150611706565b856001141561142957600588604001516020015111159150611706565b856002141561152c576001915060005b87604001516020015181101561152657600354606089015160009161010090046001600160a01b031690634bcb961390846008811061147a5761147a613acc565b60200201516040518263ffffffff1660e01b815260040161149d91815260200190565b60206040518083038186803b1580156114b557600080fd5b505afa1580156114c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ed9190613265565b9050600281600381111561150357611503613ab6565b1415611513576000935050611526565b508061151e81613a63565b915050611439565b50611706565b856003141561154d5761154288600060026123c7565b93509350505061122e565b85600414156115635761154288600060036123c7565b856005141561157857611542886000806123c7565b856006141561158e5761154287600260036123c7565b85600714156115a45761154287600260046123c7565b85600814156115c157600587604001516020015111159150611706565b85600914156115de57600787604001516020015110159150611706565b85600a14156116e65760005b8860400151602001518110156116dc5760035460608a015160009161010090046001600160a01b03169063994fb2c690846008811061162b5761162b613acc565b60200201516040518263ffffffff1660e01b815260040161164e91815260200190565b6101c06040518083038186803b15801561166757600080fd5b505afa15801561167b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169f91906133e4565b90506001816020015160038111156116b9576116b9613ab6565b14156116c95760019350506116dc565b50806116d481613a63565b9150506115ea565b5060019050611706565b85600b141561170657611703856116fd5787612504565b88612504565b91505b9097909650945050505050565b60006001600160a01b03821661172857600080fd5b506001600160a01b03166000908152602091909152604090205460ff1690565b6117536000826113ac565b6040516001600160a01b038216907f44d6d25963f097ad14f29f06854a01f575648a1ef82f30e562ccd3889717e33990600090a250565b611792612bd4565b600354604051632552294360e11b81526004810187905260009161010090046001600160a01b031690634aa45286906024016101206040518083038186803b1580156117dd57600080fd5b505afa1580156117f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118159190613280565b600354604051632552294360e11b8152600481018890529192506000916101009091046001600160a01b031690634aa45286906024016101206040518083038186803b15801561186457600080fd5b505afa158015611878573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061189c9190613280565b600480546040516337260b2960e11b81529182018890529192506000916001600160a01b031690636e4c16529060240160006040518083038186803b1580156118e457600080fd5b505afa1580156118f8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611920919081019061319b565b600480546040516337260b2960e11b81529182018890529192506000916001600160a01b031690636e4c16529060240160006040518083038186803b15801561196857600080fd5b505afa15801561197c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526119a4919081019061319b565b60048054604051639895d74960e01b81529182018a90529192506000916001600160a01b031690639895d7499060240160206040518083038186803b1580156119ec57600080fd5b505afa158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190613546565b60048054604051639895d74960e01b81529182018a90529192506000916001600160a01b031690639895d7499060240160206040518083038186803b158015611a6c57600080fd5b505afa158015611a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa49190613546565b6040805160c08101825293845260208401919091528201959095526060810193909352608083019190915260a08201529695505050505050565b611ae6612b82565b602083015160408085015190840151611afe906125ae565b60408084015101526060840151611b14906125ae565b6040808301510152835160208501516060870151600090611b3790600590613a7e565b1590508015611c30576000611b5a8860800151611b5560458c612614565b612671565b905060005b84811015611bae57818181518110611b7957611b79613acc565b6020026020010151876060015182603c8110611b9757611b97613acc565b602002015280611ba681613a63565b915050611b5f565b5060006080870181905260a0890151611bcd90611b556101a48d612614565b905060005b84811015611c2157818181518110611bec57611bec613acc565b6020026020010151876060015182603c8110611c0a57611c0a613acc565b602002015280611c1981613a63565b915050611bd2565b50506000608086015250611c5c565b611c428560400151856040015161275c565b6040808701829052850151611c569161275c565b60408501525b6000856080015184611c6e9190613a17565b9050856040015160400151602001518110611c955785604001516040015160200151611c97565b805b60408088015101516020015260005b86604001516040015160200151811015611d145760608701516080880151611cce908361393b565b603c8110611cde57611cde613acc565b60200201518760400151606001518260088110611cfd57611cfd613acc565b602002015280611d0c81613a63565b915050611ca6565b508560400151604001516020015186608001818151611d33919061393b565b9052506080850151611d459084613a17565b9050846040015160400151602001518110611d6c5784604001516040015160200151611d6e565b805b60408087015101516020015260005b85604001516040015160200151811015611deb5760608601516080870151611da5908361393b565b603c8110611db557611db5613acc565b60200201518660400151606001518260088110611dd457611dd4613acc565b602002015280611de381613a63565b915050611d7d565b508460400151604001516020015185608001818151611e0a919061393b565b905250602089018690526040890185905260608901805190611e2b82613a63565b90525050600060a089015250959695505050505050565b611e4a612b82565b6020820151604090810151810151818401518201519091015160008460a001516001811115611e7b57611e7b613ab6565b1415611f5457805182511315611e9b57600060808501815b9052506113a4565b805182511215611ebf576080840160015b90816001811115611e9357611e93613ab6565b806020015182602001511115611eda57608084016000611eac565b806020015182602001511015611ef557608084016001611eac565b60006002611f0662010f2c87612614565b611f109190613a7e565b90508015611f1f576001611f22565b60005b85608001906001811115611f3857611f38613ab6565b90816001811115611f4b57611f4b613ab6565b905250506113a4565b600084608001516001811115611f6c57611f6c613ab6565b14611f78576000611f7b565b60015b84608001906001811115611f9157611f91613ab6565b90816001811115611fa457611fa4613ab6565b905250509192915050565b611fb7612b82565b60008360a001516001811115611fcf57611fcf613ab6565b1415611fe157600160a0840152611fee565b611feb8383611ade565b92505b5090919050565b612000600082612af3565b6040516001600160a01b038216907fa3b62bc36326052d97ea62d63c3d60308ed4c3ea8ac079dd8499f1e9c4f80c0f90600090a250565b600080600560009054906101000a90046001600160a01b03166001600160a01b031663dbdff2c16040518163ffffffff1660e01b815260040160206040518083038186803b15801561208857600080fd5b505afa15801561209c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c09190613546565b602084810151516040958601515186514381850152808801949094526bffffffffffffffffffffffff19606092831b811683860152911b166074830152845180830360680181526088909201909452805193019290922092915050565b60208281015190820151600354604051632552294360e11b815260048101849052600093849390929091849161010090046001600160a01b031690634aa45286906024016101206040518083038186803b15801561217a57600080fd5b505afa15801561218e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121b29190613280565b60200151600354604051632552294360e11b8152600481018590529192506000916101009091046001600160a01b031690634aa45286906024016101206040518083038186803b15801561220557600080fd5b505afa158015612219573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223d9190613280565b6020015160035460405163b230345360e01b81529192506000916101009091046001600160a01b03169063b23034539061227b908590600401613787565b604080518083038186803b15801561229257600080fd5b505afa1580156122a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ca91906134d2565b5160035460405163b230345360e01b81529192506000916101009091046001600160a01b03169063b230345390612305908690600401613787565b604080518083038186803b15801561231c57600080fd5b505afa158015612330573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235491906134d2565b60200151905081600a81111561236c5761236c613ab6565b84600a81111561237e5761237e613ab6565b141561238957600296505b80600a81111561239b5761239b613ab6565b84600a8111156123ad576123ad613ab6565b14156123b95760011996505b509498975050505050505050565b6000806000805b8660400151602001518110156124f557600354606088015160009161010090046001600160a01b03169063994fb2c690846008811061240f5761240f613acc565b60200201516040518263ffffffff1660e01b815260040161243291815260200190565b6101c06040518083038186803b15801561244b57600080fd5b505afa15801561245f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061248391906133e4565b905086600381111561249757612497613ab6565b816020015160038111156124ad576124ad613ab6565b146124b857506124e3565b6040810151805160010b8714806124cd575086155b156124e057836124dc81613a63565b9450505b50505b806124ed81613a63565b9150506123ce565b50801515969095509350505050565b6003546020820151604051632552294360e11b8152600481019190915260009161010090046001600160a01b031690634aa45286906024016101206040518083038186803b15801561255557600080fd5b505afa158015612569573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258d9190613280565b6040015161ffff16826000015160026125a69190613953565b131592915050565b6125b6612c16565b6125be612c16565b60608084015161ffff90811683526080808601518216602085015260a0808701518316604086015260c087015183169385019390935260e086015182169084015261010090940151909316928101929092525090565b6060810151815160009081526001602090815260408083205490519293849361265193889391019283526020830191909152604082015260600190565b60408051808303601f190181529190528051602090910120949350505050565b606060005b83518110156113a457600081855161268e9190613a17565b6126989085613a7e565b6126a2908361393b565b905060008582815181106126b8576126b8613acc565b602002602001015190508583815181106126d4576126d4613acc565b60200260200101518683815181106126ee576126ee613acc565b6020026020010181815250508086848151811061270d5761270d613acc565b6020026020010181815250508460405160200161272c91815260200190565b6040516020818303038152906040528051906020012060001c94505050808061275490613a63565b915050612676565b612764612b3b565b60005b83608001518110156113a45760008460a00151826005811061278b5761278b613acc565b602002015190506000816020015190506001816020015161ffff1610612ade576000816060015160018111156127c3576127c3613ab6565b14156128f3576000816040015160058111156127e1576127e1613ab6565b141561280c57806000015160010b866040015160600181815161280491906138fa565b905250612a10565b60028160400151600581111561282457612824613ab6565b141561284757806000015160010b866040015160400181815161280491906138fa565b60048160400151600581111561285f5761285f613ab6565b141561288257806000015160010b866040015160000181815161280491906138fa565b60058160400151600581111561289a5761289a613ab6565b14156128ee576000816000015160010b8760400151602001516128bd91906138fa565b9050600881136128cd57806128d0565b60085b9050600081136128e15760006128e3565b805b604088015160200152505b612a10565b60008160400151600581111561290b5761290b613ab6565b141561292e57806000015160010b856040015160600181815161280491906138fa565b60028160400151600581111561294657612946613ab6565b141561296957806000015160010b856040015160400181815161280491906138fa565b60048160400151600581111561298157612981613ab6565b14156129a457806000015160010b856040015160000181815161280491906138fa565b6005816040015160058111156129bc576129bc613ab6565b1415612a10576000816000015160010b8660400151602001516129df91906138fa565b9050600881136129ef57806129f2565b60085b905060008113612a03576000612a05565b805b604087015160200152505b60208101805190612a2082613a2e565b61ffff90811690915260208301511615159050612ade5760018660800151612a489190613a17565b831015612a96578560a0015160018760800151612a659190613a17565b60058110612a7557612a75613acc565b60200201518660a001518460058110612a9057612a90613acc565b60200201525b8560a0015160018760800151612aac9190613a17565b60058110612abc57612abc613acc565b60200201612ac8612c4c565b905260808601805190612ada82613a4c565b9052505b50508080612aeb90613a63565b915050612767565b6001600160a01b038116612b0657600080fd5b612b108282611713565b612b1957600080fd5b6001600160a01b0316600090815260209190915260409020805460ff19169055565b6040518060c001604052806000815260200160008152602001612b5c612c16565b8152602001612b69612c90565b815260200160008152602001612b7d612caf565b905290565b6040518060c0016040528060008152602001612b9c612cdc565b8152602001612ba9612cdc565b81526020016000815260200160006001811115612bc857612bc8613ab6565b81526020016000905290565b6040518060c001604052806000815260200160008152602001612bf5612d15565b8152602001612c02612d15565b815260200160608152602001606081525090565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051806040016040528060008152602001612b7d6040805160a0810182526000808252602082018190529091820190815260200160008152600060209091015290565b6040518061010001604052806008906020820280368337509192915050565b6040518060a001604052806005905b612cc6612c4c565b815260200190600190039081612cbe5790505090565b6040805160a08101825260008082526020820152908101612cfb612b3b565b8152602001612d08612d62565b8152602001600081525090565b60408051610120810190915260008082526020820190815260006020820181905260408201819052606082018190526080820181905260a0820181905260c0820181905260e09091015290565b604051806107800160405280603c906020820280368337509192915050565b600082601f830112612d9257600080fd5b612d9a61383b565b8083856103c086011115612dad57600080fd5b60005b6005811015612e6c5781870360c080821215612dcb57600080fd5b612dd3613812565b84358152602060a080601f1986011215612dec57600080fd5b612df461383b565b945081870135612e0381613b45565b8552604087810135612e1481613b54565b86840152606088810135612e2781613b38565b8083890152506080915081890135612e3e81613b2b565b908701529087013590612e5082613b54565b8501528181019390935286529401939190910190600101612db0565b509095945050505050565b600082601f830112612e8857600080fd5b60405161010080820182811067ffffffffffffffff82111715612ead57612ead613ae2565b6040528184828101871015612ec157600080fd5b600092505b6008831015612ee657803582526001929092019160209182019101612ec6565b509195945050505050565b8051612efc81613b1d565b919050565b8051600b8110612efc57600080fd5b805160048110612efc57600080fd5b600060a08284031215612f3157600080fd5b612f3961383b565b90508151612f4681613b45565b81526020820151612f5681613b54565b60208201526040820151612f6981613b38565b60408201526060820151612f7c81613b2b565b60608201526080820151612f8f81613b54565b608082015292915050565b60008183036105e0811215612fae57600080fd5b612fb661385e565b9150823582526020830135602083015260c0603f1982011215612fd857600080fd5b50612fe161385e565b60408301358152606083013560208201526080830135604082015260a0830135606082015260c0830135608082015260e083013560a08201528060408301525061302f836101008401612e77565b6060820152610200820135608082015261304d836102208401612d81565b60a082015292915050565b6000610dc0828403121561306b57600080fd5b61307361383b565b9050813561308081613b08565b8152602082810135818301526130998460408501612f9a565b60408301528361063f8401126130ae57600080fd5b6130b66138a5565b806106208501610da08601878111156130ce57600080fd5b60005b603c8110156130ee578235855293850193918501916001016130d1565b5082606087015280356080870152505050505092915050565b8051612efc81613b54565b60006020828403121561312457600080fd5b813561312f81613b08565b9392505050565b60006020828403121561314857600080fd5b815161312f81613b08565b6000806000806080858703121561316957600080fd5b843561317481613b08565b935060208501359250604085013561318b81613b08565b9396929550929360600135925050565b600060208083850312156131ae57600080fd5b825167ffffffffffffffff808211156131c657600080fd5b818501915085601f8301126131da57600080fd5b8151818111156131ec576131ec613ae2565b8060051b91506131fd8483016138c9565b8181528481019084860184860187018a101561321857600080fd5b600095505b8386101561323b57805183526001959095019491860191860161321d565b5098975050505050505050565b60006020828403121561325a57600080fd5b813561312f81613b1d565b60006020828403121561327757600080fd5b61312f82612f10565b6000610120828403121561329357600080fd5b61329b613881565b825181526132ab60208401612f01565b60208201526132bc60408401613107565b60408201526132cd60608401613107565b60608201526132de60808401613107565b60808201526132ef60a08401613107565b60a082015261330060c08401613107565b60c082015261331160e08401613107565b60e0820152610100613324818501613107565b908201529392505050565b6000611c00828403121561334257600080fd5b61334a61385e565b8235815261335b8460208501613058565b602082015261336e84610de08501613058565b6040820152611ba08301356060820152611bc083013561338d81613b2b565b6080820152611be08301356133a181613b2b565b60a08201529392505050565b600080610bc083850312156133c157600080fd5b6133cb8484612f9a565b91506133db846105e08501612f9a565b90509250929050565b60008183036101c08112156133f857600080fd5b61340061385e565b8351815261341060208501612f10565b602082015260a0603f198301121561342757600080fd5b61342f61383b565b9150604084015161343f81613b45565b8252606084015161344f81613b45565b6020830152608084015161346281613b38565b604083015260a084015161347581613b2b565b606083015260c084015161348881613b54565b6080830152604081018290526134a18560e08601612f1f565b60608201526134b36101808501612ef1565b60808201526134c56101a08501612ef1565b60a0820152949350505050565b6000604082840312156134e457600080fd5b6040516040810181811067ffffffffffffffff8211171561350757613507613ae2565b60405261351383612f01565b815261352160208401612f01565b60208201529392505050565b60006020828403121561353f57600080fd5b5035919050565b60006020828403121561355857600080fd5b5051919050565b6000806040838503121561357257600080fd5b505080516020909101519092909150565b8060005b600581101561360f578151805185526020808201519150815160010b8187015280820151604061ffff808316828a015281850151925060609150600683106135d1576135d1613ab6565b88820192909252830151906080906135e883613af8565b88820192909252929092015190911660a086015260c0909401939190910190600101613587565b50505050565b8060005b600881101561360f578151845260209384019390910190600101613619565b80518252602081015161364e6020840182613720565b506040810151613662610de0840182613720565b506060810151611ba0830152608081015161367c81613af8565b611bc083015260a081015161369081613af8565b80611be0840152505050565b80518252602081015160208301526040810151805160408401526020810151606084015260408101516080840152606081015160a0840152608081015160c084015260a081015160e08401525060608101516136fc610100840182613615565b50608081015161020083015260a081015161371b610220840182613583565b505050565b80516001600160a01b03168252602080820151818401526040808301519061374a9085018261369c565b506060820151610620840160005b603c81101561377557825182529183019190830190600101613758565b5050505060800151610da09190910152565b60208101600b831061379b5761379b613ab6565b91905290565b611c008101610adb8284613638565b611c2081016137bf8285613638565b6001600160a01b0392909216611c009190910152919050565b611c2081016137e78285613638565b82611c008301529392505050565b610bc08101613804828561369c565b61312f6105e083018461369c565b6040805190810167ffffffffffffffff8111828210171561383557613835613ae2565b60405290565b60405160a0810167ffffffffffffffff8111828210171561383557613835613ae2565b60405160c0810167ffffffffffffffff8111828210171561383557613835613ae2565b604051610120810167ffffffffffffffff8111828210171561383557613835613ae2565b604051610780810167ffffffffffffffff8111828210171561383557613835613ae2565b604051601f8201601f1916810167ffffffffffffffff811182821017156138f2576138f2613ae2565b604052919050565b600080821280156001600160ff1b038490038513161561391c5761391c613aa0565b600160ff1b839003841281161561393557613935613aa0565b50500190565b6000821982111561394e5761394e613aa0565b500190565b60006001600160ff1b038184138284138082168684048611161561397957613979613aa0565b600160ff1b600087128281168783058912161561399857613998613aa0565b600087129250878205871284841616156139b4576139b4613aa0565b878505871281841616156139ca576139ca613aa0565b505050929093029392505050565b60008083128015600160ff1b8501841216156139f6576139f6613aa0565b6001600160ff1b0384018313811615613a1157613a11613aa0565b50500390565b600082821015613a2957613a29613aa0565b500390565b600061ffff821680613a4257613a42613aa0565b6000190192915050565b600081613a5b57613a5b613aa0565b506000190190565b6000600019821415613a7757613a77613aa0565b5060010190565b600082613a9b57634e487b7160e01b600052601260045260246000fd5b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b60028110610afc57610afc613ab6565b6001600160a01b0381168114610afc57600080fd5b8015158114610afc57600080fd5b60028110610afc57600080fd5b60068110610afc57600080fd5b8060010b8114610afc57600080fd5b61ffff81168114610afc57600080fdfea26469706673582212206bd6f2e4b1e64547079c5bff9fba8c4c1984d9f158221f9d05d45226ad5a473f64736f6c63430008060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009460dfaad34bc55ee564a6851c58dfc390d7d4ac
-----Decoded View---------------
Arg [0] : _configAddress (address): 0x9460DfaAD34Bc55ee564A6851c58DFC390D7d4ac
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000009460dfaad34bc55ee564a6851c58dfc390d7d4ac
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.