// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <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 GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
// SPDX-License-Identifier: MIT
// Degen'$ Farm: Collectible NFT game (https://degens.farm)
pragma solidity ^0.7.4;
pragma experimental ABIEncoderV2;
import "./DegensFarmBase.sol";
contract DegenFarm is DegenFarmBase {
uint8 constant public CREATURE_TYPE_COUNT= 20; // how much creatures types may be used
uint256 constant public FARMING_DURATION = 168 hours;
uint256 constant public TOOL_UNSTAKE_DELAY = 1 weeks;
uint16 constant public NORMIE_COUNT_IN_TYPE = 100;
uint16 constant public CHAD_COUNT_IN_TYPE = 20;
uint16 constant public MAX_LANDS = 2500;
constructor (
address _land,
address _creatures,
address _inventory,
address _bagstoken,
address _dungtoken,
IEggs _eggs
)
DegenFarmBase(_land, _creatures, _inventory, _bagstoken, _dungtoken, _eggs)
{
require(CREATURE_TYPE_COUNT <= CREATURE_TYPE_COUNT_MAX, "CREATURE_TYPE_COUNT is greater than CREATURE_TYPE_COUNT_MAX");
// Mainnet amulet addresses
amulets[0] = 0xD533a949740bb3306d119CC777fa900bA034cd52; // Cow $CRV
amulets[1] = 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984; // Horse $UNI
amulets[2] = 0xfA5047c9c78B8877af97BDcb85Db743fD7313d4a; // Rabbit $ROOK
amulets[3] = 0xDADA00A9C23390112D08a1377cc59f7d03D9df55; // Chicken $DUNG
amulets[4] = 0x6B3595068778DD592e39A122f4f5a5cF09C90fE2; // Pig $SUSHI
amulets[5] = 0x0D8775F648430679A709E98d2b0Cb6250d2887EF; // Cat $BAT
amulets[6] = 0x3472A5A71965499acd81997a54BBA8D852C6E53d; // Dog $BADGER
amulets[7] = 0x0d438F3b5175Bebc262bF23753C1E53d03432bDE; // Goose $WNXM
amulets[8] = 0x3155BA85D5F96b2d030a4966AF206230e46849cb; // Goat $RUNE
amulets[9] = 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9; // Sheep $AAVE
amulets[10] = 0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F; // Snake $SNX
amulets[11] = 0x967da4048cD07aB37855c090aAF366e4ce1b9F48; // Fish $OCEAN
amulets[12] = 0x0F5D2fB29fb7d3CFeE444a200298f468908cC942; // Frog $MANA
amulets[13] = 0x514910771AF9Ca656af840dff83E8264EcF986CA; // Worm $LINK
amulets[14] = 0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32; // Lama $LDO
amulets[15] = 0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C; // Mouse $BNT
amulets[16] = 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2; // Camel $MKR
amulets[17] = 0x111111111117dC0aa78b770fA6A738034120C302; // Donkey $1INCH
amulets[18] = 0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e; // Bee $YFI
amulets[19] = 0xc00e94Cb662C3520282E6f5717214004A7f26888; // Duck $COMP
}
function getCreatureTypeCount() override internal view returns (uint16) {
return CREATURE_TYPE_COUNT;
}
function getFarmingDuration() override internal view returns (uint) {
return FARMING_DURATION;
}
function getNormieCountInType() override internal view returns (uint16) {
return NORMIE_COUNT_IN_TYPE;
}
function getChadCountInType() override internal view returns (uint16) {
return CHAD_COUNT_IN_TYPE;
}
function getMaxLands() override internal view returns (uint16) {
return MAX_LANDS;
}
function getToolUnstakeDelay() override internal view returns (uint) {
return TOOL_UNSTAKE_DELAY;
}
}
// SPDX-License-Identifier: MIT
// Degen'$ Farm: Collectible NFT game (https://degens.farm)
pragma solidity ^0.7.4;
pragma experimental ABIEncoderV2;
import "./IERC20.sol";
import "./IERC1155.sol";
import "./ERC1155Receiver.sol";
import "./IERC721.sol";
import "./Ownable.sol";
interface IEggs is IERC721 {
function mint(address to, uint256 tokenId) external;
function burn(uint256 tokenId) external;
function getUsersTokens(address _owner) external view returns (uint256[] memory);
}
interface ICreatures is IERC721 {
function mint(
address to,
uint256 tokenId,
uint8 _animalType,
uint8 _rarity,
uint32 index
) external;
function getTypeAndRarity(uint256 _tokenId) external view returns(uint8, uint8);
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
}
interface ILand is IERC721 {
function mint(
address to,
uint256 tokenId,
uint randomSeed
) external;
function burn(uint256 tokenId) external;
}
interface IDung is IERC20 {
function mint(
address to,
uint256 amount
) external;
}
interface IInventory is IERC1155 {
function getToolBoost(uint8 _item) external view returns (uint16);
}
interface IAmuletPriceProvider {
function getLastPrice(address _amulet) external view returns (uint256);
}
interface IOperatorManage {
function addOperator(address _newOperator) external;
function removeOperator(address _oldOperator) external;
function withdrawERC20(IERC20 _tokenContract, address _admin) external;
function setSigner(address _newSigner) external;
}
abstract contract DegenFarmBase is ERC1155Receiver, Ownable {
enum AnimalType {
Cow, Horse, Rabbit, Chicken, Pig, Cat, Dog, Goose, Goat, Sheep,
Snake, Fish, Frog, Worm, Lama, Mouse, Camel, Donkey, Bee, Duck,
GenesisEgg // 20
}
enum Rarity {
Normie, // 0
Chad, // 1
Degen, // 2
Unique // 3
}
enum Result {Fail, Dung, Chad, Degen}
// External contract addresses used with this farm
struct AddressRegistry {
address land;
address creatures;
address inventory;
address bagstoken;
address dungtoken;
}
// Degens Farm data for creature type
struct CreaturesCount {
uint16 totalNormie;
uint16 leftNormie;
uint16 totalChad;
uint16 leftChadToDiscover;
uint16 totalDegen;
uint16 leftDegenToDiscover;
uint16 chadFarmAttempts;
uint16 degenFarmAttempts;
}
// Land count record
struct LandCount {
uint16 total;
uint16 left;
}
// Record represent one farming act
struct FarmRecord {
uint256 creatureId;
uint256 landId;
uint256 harvestTime;
uint256 amuletsPrice1;
uint256 amuletsPrice2;
Result harvest;
uint256 harvestId; // new NFT tokenId
bool[COMMON_AMULET_COUNT] commonAmuletInitialHold;
}
// Bonus for better harvest
struct Bonus {
uint256 commonAmuletHold; // common amulet hold
uint256 creatureAmuletBullTrend;
uint256 inventoryHold;
uint256 creatureAmuletBalance;
}
uint8 constant public CREATURE_TYPE_COUNT_MAX = 20; //how much creatures types may be used
// Creature probability multiplier, scaled with 100. 3.00 - 300, 3.05 - 305 etc
uint32 constant public CREATURE_P_MULT = 230;
uint16 public MAX_ALL_NORMIES = getCreatureTypeCount() * getNormieCountInType();
uint256 constant public NFT_ID_MULTIPLIER = 10000; //must be set more then all Normies count
uint256 constant public FARM_DUNG_AMOUNT = 250e33; //per one harvest
uint256 constant public BONUS_POINTS_AMULET_HOLD = 10;
uint256 constant public COMMON_AMULET_COUNT = 2;
uint256 constant public TOOL_TYPE_COUNT = 6;
// Common Amulet addresses
address[COMMON_AMULET_COUNT] public COMMON_AMULETS = [
0x126c121f99e1E211dF2e5f8De2d96Fa36647c855, // $DEGEN token
0xa0246c9032bC3A600820415aE600c6388619A14D // $FARM token
];
bool public REVEAL_ENABLED = false;
bool public FARMING_ENABLED = false;
address public priceProvider;
IEggs public eggs;
address[CREATURE_TYPE_COUNT_MAX] public amulets; // amulets by creature type
AddressRegistry public farm;
LandCount public landCount;
mapping(address => uint256) public maxAmuletBalances;
// mapping from user to his(her) staked tools
// Index of uint256[6] represent tool NFT itemID
mapping(address => uint256[TOOL_TYPE_COUNT]) public userStakedTools;
uint16 public allNormiesesLeft;
CreaturesCount[CREATURE_TYPE_COUNT_MAX] public creaturesBorn;
FarmRecord[] public farming;
mapping(uint => uint) public parents;
event Reveal(address _farmer, uint256 indexed _tokenId, bool _isCreature, uint8 _animalType);
event Harvest(
uint256 indexed _eggId,
address farmer,
uint8 result,
uint256 baseChance,
uint256 commonAmuletHold,
uint256 amuletBullTrend,
uint256 inventoryHold,
uint256 amuletMaxBalance,
uint256 resultChance
);
event Stake(address owner, uint8 innventory);
event UnStake(address owner, uint8 innventory);
constructor (
address _land,
address _creatures,
address _inventory,
address _bagstoken,
address _dungtoken,
IEggs _eggs
)
{
farm.land = _land;
farm.creatures = _creatures;
farm.inventory = _inventory;
farm.bagstoken = _bagstoken;
farm.dungtoken = _dungtoken;
// Index of creaturesBorn in this initial setting
// must NOT exceed CREATURE_TYPE_COUNT
for (uint i = 0; i < getCreatureTypeCount(); i++) {
creaturesBorn[i] = CreaturesCount(
getNormieCountInType(), // totalNormie;
getNormieCountInType(), // leftNormie;
getChadCountInType(), // totalChad;
getChadCountInType(), // leftChadToDiscover;
1, // totalDegen;
1, // leftDegenToDiscover;
0, // chadFarmAttempts;
0); // degenFarmAttempts;
}
landCount = LandCount(getMaxLands(), getMaxLands());
allNormiesesLeft = MAX_ALL_NORMIES;
eggs = _eggs;
}
function reveal(uint count) external {
require(_isRevelEnabled(), "Please wait for reveal enabled.");
require(count > 0, "Count must be positive");
require(count <= 8, "Count must less than 9"); // random limit
require(
IERC20(farm.bagstoken).allowance(msg.sender, address(this)) >= count*1,
"Please approve your BAGS token to this contract."
);
require(
IERC20(farm.bagstoken).transferFrom(msg.sender, address(this), count*1)
);
uint randomSeed = uint(keccak256(abi.encodePacked(block.timestamp, msg.sender)));
// random seed for 8 reveals (8x32=256)
for (uint i = 0; i < count; i++) {
_reveal(randomSeed);
randomSeed = randomSeed / 0x100000000; // shift right 32 bits
}
}
/**
* @dev Start farming process. New NFT - Egg will minted for user
* @param _creatureId - NFT tokenId, caller must be owner of this token
* @param _landId -- NFT tokenId, caller must be owner of this token
*/
function farmDeploy(uint256 _creatureId, uint256 _landId) external {
require(FARMING_ENABLED == true, "Chief Farmer not enable yet");
require(ICreatures(farm.creatures).ownerOf(_creatureId) == msg.sender,
"Need to be Creature Owner"
);
require(ILand(farm.land).ownerOf(_landId) == msg.sender,
"Need to be Land Owner"
);
(uint8 crType, uint8 crRarity) = ICreatures(farm.creatures).getTypeAndRarity(_creatureId);
require((DegenFarmBase.Rarity)(crRarity) == Rarity.Normie ||
(DegenFarmBase.Rarity)(crRarity) == Rarity.Chad,
"Can farm only Normie and Chad");
// Check that farming available yet
if (crRarity == 0) {
require(creaturesBorn[crType].leftChadToDiscover > 0, "No more chads left");
} else {
require(creaturesBorn[crType].leftDegenToDiscover > 0, "No more Degen left");
}
// Save deploy record
farming.push(
FarmRecord({
creatureId: _creatureId,
landId: _landId,
harvestTime: block.timestamp + getFarmingDuration(),
amuletsPrice1: _getExistingAmuletsPrices(amulets[crType]),
amuletsPrice2: 0,
harvest: Result.Fail,
harvestId: 0,
commonAmuletInitialHold: _getCommonAmuletsHoldState(msg.sender) //save initial hold state
})
);
// Let's mint Egg.
eggs.mint(
msg.sender, // farmer
farming.length - 1 // tokenId
);
// STAKE LAND and Creatures
ILand(farm.land).transferFrom(msg.sender, address(this), _landId);
ICreatures(farm.creatures).transferFrom(msg.sender, address(this), _creatureId);
}
/**
* @dev Finish farming process. Egg NFT will be burn
* @param _deployId - NFT tokenId, caller must be owner of this token
*/
function harvest(uint256 _deployId) external {
require(eggs.ownerOf(_deployId) == msg.sender, "This is NOT YOUR EGG");
FarmRecord storage f = farming[_deployId];
require(f.harvestTime <= block.timestamp, "To early for harvest");
// Lets Calculate Dung/CHAD-DEGEN chance
Result farmingResult;
Bonus memory bonus;
// 1. BaseChance
(uint8 crType, uint8 crRarity) = ICreatures(farm.creatures).getTypeAndRarity(
f.creatureId
);
uint256 baseChance;
if (crRarity == 0) {
// Try farm CHAD. So if there is no CHADs any more we must return assets
if (creaturesBorn[crType].leftChadToDiscover == 0) {
_endFarming(_deployId, Result.Fail);
return;
}
baseChance = 100 * creaturesBorn[crType].totalChad / creaturesBorn[crType].totalNormie; // by default 20%
// Decrease appropriate farm ATTEMPTS COUNT
creaturesBorn[crType].chadFarmAttempts += 1;
} else {
// Try farm DEGEN. So if there is no DEGENSs any more we must return assets
if (creaturesBorn[crType].leftDegenToDiscover == 0) {
_endFarming(_deployId, Result.Fail);
return;
}
baseChance = 100 * creaturesBorn[crType].totalDegen / creaturesBorn[crType].totalChad; // by default 5%
// Decrease appropriate farm ATTEMPTS COUNT
creaturesBorn[crType].degenFarmAttempts += 1;
}
//////////////////////////////////////////////
// 2. Bonus for common amulet token ***HOLD*** - commonAmuletHold
//////////////////////////////////////////////
// Get current hold stae
for (uint8 i = 0; i < COMMON_AMULETS.length; i ++){
if (f.commonAmuletInitialHold[i] && _getCommonAmuletsHoldState(msg.sender)[i]) {
bonus.commonAmuletHold = BONUS_POINTS_AMULET_HOLD;
}
}
//////////////////////////////////////////////
// 3. Bonus for creatures amulets BULLs trend - creatureAmuletBullTrend
// 4. Bonus for creatures amulets balance - creatureAmuletBalance
//////////////////////////////////////////////
uint256 prices2 = 0;
prices2 = _getExistingAmuletsPrices(amulets[crType]);
if (f.amuletsPrice1 > 0 && prices2 > 0 && prices2 > f.amuletsPrice1){
bonus.creatureAmuletBullTrend =
(prices2 - f.amuletsPrice1) * 100 / f.amuletsPrice1;
}
//Lets check max Balance, because
//bonus.amuletHold = userAmuletBalance/maxAmuletBalances*BONUS_POINTS_AMULET_HOLD
_checkAndSaveMaxAmuletPrice(amulets[crType]);
if (maxAmuletBalances[amulets[crType]] > 0) {
bonus.creatureAmuletBalance =
IERC20(amulets[crType]).balanceOf(msg.sender) * 100 //100 used for scale
/ maxAmuletBalances[amulets[crType]] * BONUS_POINTS_AMULET_HOLD /100;
}
f.amuletsPrice2 = prices2;
//////////////////////////////////////////////
//5. Bonus for inventory
//////////////////////////////////////////////
bonus.inventoryHold = 0;
if (userStakedTools[msg.sender].length > 0) {
for (uint8 i=0; i < userStakedTools[msg.sender].length; i++) {
if (userStakedTools[msg.sender][i] > 0) {
bonus.inventoryHold = bonus.inventoryHold + IInventory(farm.inventory).getToolBoost(i);
}
}
}
//////////////////////////////////////////////
uint256 allBonus = bonus.commonAmuletHold
+ bonus.creatureAmuletBullTrend
+ bonus.creatureAmuletBalance
+ bonus.inventoryHold;
if (allBonus > 100) {
allBonus = 100; // limit bonus to 100%
}
uint32[] memory choiceWeight = new uint32[](2);
choiceWeight[0] = uint32(baseChance * (100 + allBonus)); // chance of born new chad/degen
choiceWeight[1] = uint32(10000 - choiceWeight[0]); // receive DUNG
if (_getWeightedChoice(choiceWeight) == 0) {
f.harvestId = (crRarity + 1) * NFT_ID_MULTIPLIER + _deployId;
// Mint new chad/degen
uint32 index;
// Decrease appropriate CREATURE COUNT
if (crRarity + 1 == uint8(Rarity.Chad)) {
index = creaturesBorn[crType].totalChad - creaturesBorn[crType].leftChadToDiscover + 1;
creaturesBorn[crType].leftChadToDiscover -= 1;
farmingResult = Result.Chad;
} else if (crRarity + 1 == uint8(Rarity.Degen)) {
index = creaturesBorn[crType].totalDegen - creaturesBorn[crType].leftDegenToDiscover + 1;
creaturesBorn[crType].leftDegenToDiscover -= 1;
farmingResult = Result.Degen;
}
uint newCreatureId = (crRarity + 1) * NFT_ID_MULTIPLIER + _deployId;
ICreatures(farm.creatures).mint(
msg.sender,
newCreatureId, // new iD
crType, // AnimalType
crRarity + 1,
index // index
);
parents[newCreatureId] = f.creatureId;
} else {
// Mint new dung
IDung(farm.dungtoken).mint(msg.sender, FARM_DUNG_AMOUNT);
farmingResult = Result.Dung;
}
// BURN Land
ILand(farm.land).burn(f.landId);
_endFarming(_deployId, farmingResult);
emit Harvest(
_deployId,
msg.sender,
uint8(farmingResult),
baseChance,
bonus.commonAmuletHold,
bonus.creatureAmuletBullTrend,
bonus.inventoryHold,
bonus.creatureAmuletBalance,
choiceWeight[0]
);
}
/**
* @dev Stake one inventory item
* @param _itemId - NFT tokenId, caller must be owner of this token
*/
function stakeOneTool(uint8 _itemId) external {
_stakeOneTool(_itemId);
emit Stake(msg.sender, _itemId);
}
/**
* @dev UnStake one inventory item
* @param _itemId - NFT tokenId
*/
function unstakeOneTool(uint8 _itemId) external {
_unstakeOneTool(_itemId);
emit UnStake(msg.sender, _itemId);
}
/////////////////////////////////////////////////////
//// Admin functions ///////
/////////////////////////////////////////////////////
function setOneCommonAmulet(uint8 _index, address _token) external onlyOwner {
COMMON_AMULETS[_index] = _token;
}
function setAmuletForOneCreature(uint8 _index, address _token) external onlyOwner {
amulets[_index] = _token;
}
function setAmulets(address[] calldata _tokens) external onlyOwner {
for (uint i = 0; i < _tokens.length; i++) {
amulets[i] = _tokens[i];
}
}
function setPriceProvider(address _priceProvider) external onlyOwner {
priceProvider = _priceProvider;
}
function enableReveal(bool _isEnabled) external onlyOwner {
REVEAL_ENABLED = _isEnabled;
}
function enableFarming(bool _isEnabled) external onlyOwner {
FARMING_ENABLED = _isEnabled;
}
////////////////////////////////////////
/// Proxy for NFT Operators mamnage //
////////////////////////////////////////
function addOperator(address _contract, address newOperator) external onlyOwner {
IOperatorManage(_contract).addOperator(newOperator);
}
function removeOperator(address _contract, address oldOperator) external onlyOwner {
IOperatorManage(_contract).removeOperator(oldOperator);
}
function reclaimToken(address _contract, IERC20 anyTokens, address _admin) external onlyOwner {
IOperatorManage(_contract).withdrawERC20(anyTokens, _admin);
}
function setSigner(address _contract, address _newSigner) external onlyOwner {
IOperatorManage(_contract).setSigner(_newSigner);
}
////////////////////////////////////////////////////////
function getCreatureAmulets(uint8 _creatureType) external view returns (address) {
return _getCreatureAmulets(_creatureType);
}
function _getCreatureAmulets(uint8 _creatureType) internal view returns (address) {
return amulets[_creatureType];
}
function getCreatureStat(uint8 _creatureType)
external
view
returns (
uint16,
uint16,
uint16,
uint16,
uint16,
uint16,
uint16,
uint16
)
{
CreaturesCount storage stat = creaturesBorn[_creatureType];
return (
stat.totalNormie,
stat.leftNormie,
stat.totalChad,
stat.leftChadToDiscover,
stat.totalDegen,
stat.leftDegenToDiscover,
stat.chadFarmAttempts,
stat.degenFarmAttempts
);
}
function getWeightedChoice(uint32[] memory _weights) external view returns (uint8){
return _getWeightedChoice(_weights);
}
function _getWeightedChoice(uint32[] memory _weights) internal view returns (uint8){
uint randomSeed = uint(keccak256(abi.encodePacked(block.timestamp, msg.sender)));
return _getWeightedChoice2(_weights, randomSeed);
}
function getFarmingById(uint256 _farmingId) external view returns (FarmRecord memory) {
return farming[_farmingId];
}
function getOneAmuletPrice(address _token) external view returns (uint256) {
return _getOneAmuletPrice(_token);
}
///////////////////////////////////////////////
/// Internals ///////
///////////////////////////////////////////////
/**
* @dev Save farming results in storage and mint
* appropriate token (NFT, ERC20 or None)
*/
function _endFarming(uint256 _deployId, Result _res) internal {
FarmRecord storage f = farming[_deployId];
f.harvest = _res;
// unstake creature
ICreatures(farm.creatures).transferFrom(address(this), msg.sender, f.creatureId);
eggs.burn(_deployId); // Burn EGG
if (_res == Result.Fail) {
//unstake land (if staked)
if (ILand(farm.land).ownerOf(f.landId) == address(this)){
ILand(farm.land).transferFrom(address(this), msg.sender, f.landId);
}
emit Harvest(
_deployId,
msg.sender,
uint8(_res),
0, //baseChance
0, //bonus.commonAmuletHold
0, //bonus.creatureAmuletBullTrend,
0, //bonus.inventoryHold
0, // bonus.creatureAmuletBalance
0
);
}
}
function _stakeOneTool(uint8 _itemId) internal {
require(IInventory(farm.inventory).balanceOf(msg.sender, _itemId) >= 1,
"You must own this tool for stake!"
);
// Before stake we need two checks.
// 1. Removed
// 2. Cant`t stake one tool more than one item
require(userStakedTools[msg.sender][_itemId] == 0, "Tool is already staked");
// stake
IInventory(farm.inventory).safeTransferFrom(
msg.sender,
address(this),
_itemId,
1,
bytes('0')
);
userStakedTools[msg.sender][_itemId] = block.timestamp;
}
function _unstakeOneTool(uint8 _itemId) internal {
require(userStakedTools[msg.sender][_itemId] > 0, "This tool is not staked yet");
require(block.timestamp - userStakedTools[msg.sender][_itemId] >= getToolUnstakeDelay(),
"Cant unstake earlier than a week"
);
userStakedTools[msg.sender][_itemId] = 0;
IInventory(farm.inventory).safeTransferFrom(
address(this),
msg.sender,
_itemId,
1,
bytes('0')
);
}
function _checkAndSaveMaxAmuletPrice(address _amulet) internal {
if (IERC20(_amulet).balanceOf(msg.sender)
> maxAmuletBalances[_amulet]
)
{
maxAmuletBalances[_amulet]
= IERC20(_amulet).balanceOf(msg.sender);
}
}
function _getCommonAmuletsHoldState(address _farmer) internal view returns (bool[COMMON_AMULET_COUNT] memory) {
// If token balance =0 - set false
bool[COMMON_AMULET_COUNT] memory res;
for (uint8 i = 0; i < COMMON_AMULETS.length; i++){
if (IERC20(COMMON_AMULETS[i]).balanceOf(_farmer) > 0){
res[i] = true;
} else {
// Set to zero if token balance is 0
res[i] = false;
}
}
return res;
}
function _getExistingAmuletsPrices(address _token)
internal
view
returns (uint256)
{
if (IERC20(_token).balanceOf(msg.sender) > 0){
return _getOneAmuletPrice(_token);
} else {
// Set to zero if token balance is 0
return 0;
}
}
function _getOneAmuletPrice(address _token) internal view returns (uint256) {
return IAmuletPriceProvider(priceProvider).getLastPrice(_token);
}
function _isRevelEnabled() internal view returns (bool) {
return REVEAL_ENABLED;
}
function _reveal(uint randomSeed) internal {
require ((landCount.left + allNormiesesLeft) > 0, "Sorry, no more reveal!");
//1. Lets choose Land OR Creature, %
//So we have two possible results. 1 - Land, 0 - Creature.
// sum of weights = 100, lets define weigth for Creature
uint32[] memory choiceWeight = new uint32[](2);
choiceWeight[0] = uint32(allNormiesesLeft) * CREATURE_P_MULT;
choiceWeight[1] = uint32(landCount.left) * 100;
uint8 choice = uint8(_getWeightedChoice2(choiceWeight, randomSeed));
randomSeed /= 0x10000; // shift right 16 bits
//Check that choice can be executed
if (choice != 0 && landCount.left == 0) {
//There are no more Lands. So we need change choice
choice = 0;
}
if (choice == 0) { // create creature
uint32[] memory choiceWeight0 = new uint32[](getCreatureTypeCount());
//2. Ok, Creature will be born. But what kind of?
for (uint8 i = 0; i < getCreatureTypeCount(); i ++) {
choiceWeight0[i] = uint32(creaturesBorn[i].leftNormie);
}
choice = uint8(_getWeightedChoice2(choiceWeight0, randomSeed));
ICreatures(farm.creatures).mint(
msg.sender,
MAX_ALL_NORMIES - allNormiesesLeft,
choice, //AnimalType
0,
creaturesBorn[choice].totalNormie - creaturesBorn[choice].leftNormie + 1 // index
);
emit Reveal(msg.sender, MAX_ALL_NORMIES - allNormiesesLeft, true, choice);
allNormiesesLeft -= 1;
creaturesBorn[choice].leftNormie -= 1;
} else { // create land
ILand(farm.land).mint(
msg.sender,
getMaxLands() - landCount.left,
randomSeed
);
emit Reveal(msg.sender, getMaxLands() - landCount.left , false, 0);
landCount.left -= 1;
}
}
function _getWeightedChoice2(uint32[] memory _weights, uint randomSeed) internal view returns (uint8){
uint256 sum_of_weights = 0;
for (uint8 index = 0; index < _weights.length; index++) {
sum_of_weights += _weights[index];
}
uint256 rnd = randomSeed % sum_of_weights;
for (uint8 kindex = 0; kindex < _weights.length; kindex++) {
if (rnd < _weights[kindex]) {
return kindex;
}
rnd -= _weights[kindex];
}
return 0;
}
/**
@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.
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
override
returns(bytes4)
{
return bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"));
}
/**
@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. 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
override
returns(bytes4)
{
return bytes4(keccak256("onERC1155BatchReceived(address,address,uint256,uint256,bytes)"));
}
function getCreatureTypeCount() virtual internal view returns (uint16);
function getFarmingDuration() virtual internal view returns (uint);
function getToolUnstakeDelay() virtual internal view returns (uint);
function getNormieCountInType() virtual internal view returns (uint16);
function getChadCountInType() virtual internal view returns (uint16);
function getMaxLands() virtual internal view returns (uint16);
function getUsersTokens(address _owner) external view returns (uint256[] memory) {
return eggs.getUsersTokens(_owner);
}
/**
* @dev Returns creatures owned by owner and that can be used for farming.this
* Some creatures types and rarity are limited to farm because all chad/degens
* was already discovered.
* @param _owner - creatures owner
*/
function getFarmingAllowedCreatures(address _owner) external view returns (uint256[] memory) {
uint256 n = ICreatures(farm.creatures).balanceOf(_owner);
uint256[] memory result = new uint256[](n);
uint256 count = 0;
for (uint16 i = 0; i < n; i++) {
uint creatureId = ICreatures(farm.creatures).tokenOfOwnerByIndex(_owner, i);
if (isFarmingAllowedForCreature(creatureId)) {
result[count] = creatureId;
count++;
}
}
uint256[] memory result2 = new uint256[](count);
for (uint16 i = 0; i < count; i++) {
result2[i] = result[i];
}
return result2;
}
function getFarmingAllowedCreaturesWithRarity(address _owner, uint8 wantRarity) external view returns (uint256[] memory) {
uint256 n = ICreatures(farm.creatures).balanceOf(_owner);
uint256[] memory result = new uint256[](n);
uint256 count = 0;
for (uint16 i = 0; i < n; i++) {
uint creatureId = ICreatures(farm.creatures).tokenOfOwnerByIndex(_owner, i);
(uint8 _, uint8 rarity) = ICreatures(farm.creatures).getTypeAndRarity(creatureId);
if (rarity == wantRarity && isFarmingAllowedForCreature(creatureId)) {
result[count] = creatureId;
count++;
}
}
uint256[] memory result2 = new uint256[](count);
for (uint16 i = 0; i < count; i++) {
result2[i] = result[i];
}
return result2;
}
function isFarmingAllowedForCreature(uint creatureId) public view returns (bool) {
(uint8 _type, uint8 rarity) = ICreatures(farm.creatures).getTypeAndRarity(creatureId);
if ((DegenFarmBase.Rarity)(rarity) == Rarity.Normie) {
return creaturesBorn[_type].leftChadToDiscover > 0;
}
if ((DegenFarmBase.Rarity)(rarity) == Rarity.Chad) {
return creaturesBorn[_type].leftDegenToDiscover > 0;
}
return false;
}
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "./IERC1155Receiver.sol";
import "./ERC165.sol";
/**
* @dev _Available since v3.1._
*/
abstract contract ERC1155Receiver is ERC165, IERC1155Receiver {
constructor() internal {
_registerInterface(
ERC1155Receiver(address(0)).onERC1155Received.selector ^
ERC1155Receiver(address(0)).onERC1155BatchReceived.selector
);
}
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts may inherit from this and call {_registerInterface} to declare
* their support of an interface.
*/
abstract contract ERC165 is IERC165 {
/*
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
*/
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
/**
* @dev Mapping of interface ids to whether or not it's supported.
*/
mapping(bytes4 => bool) private _supportedInterfaces;
constructor () internal {
// Derived contracts need only register support for their own interfaces,
// we register support for ERC165 itself here
_registerInterface(_INTERFACE_ID_ERC165);
}
/**
* @dev See {IERC165-supportsInterface}.
*
* Time complexity O(1), guaranteed to always use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return _supportedInterfaces[interfaceId];
}
/**
* @dev Registers the contract as an implementer of the interface defined by
* `interfaceId`. Support of the actual ERC165 interface is automatic and
* registering its interface id is not required.
*
* See {IERC165-supportsInterface}.
*
* Requirements:
*
* - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
*/
function _registerInterface(bytes4 interfaceId) internal virtual {
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] = true;
}
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.8.0;
import "./IERC165.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*
* _Available since v3.1._
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the amount of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `amount`.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `amounts` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "./IERC165.sol";
/**
* _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.
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. 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
pragma solidity >=0.6.0 <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
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.8.0;
import "./IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "./Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
{
"compilationTarget": {
"DegensFarm.sol": "DegenFarm"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_land","type":"address"},{"internalType":"address","name":"_creatures","type":"address"},{"internalType":"address","name":"_inventory","type":"address"},{"internalType":"address","name":"_bagstoken","type":"address"},{"internalType":"address","name":"_dungtoken","type":"address"},{"internalType":"contract IEggs","name":"_eggs","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_eggId","type":"uint256"},{"indexed":false,"internalType":"address","name":"farmer","type":"address"},{"indexed":false,"internalType":"uint8","name":"result","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"baseChance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"commonAmuletHold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amuletBullTrend","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"inventoryHold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amuletMaxBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"resultChance","type":"uint256"}],"name":"Harvest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_farmer","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"_isCreature","type":"bool"},{"indexed":false,"internalType":"uint8","name":"_animalType","type":"uint8"}],"name":"Reveal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint8","name":"innventory","type":"uint8"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint8","name":"innventory","type":"uint8"}],"name":"UnStake","type":"event"},{"inputs":[],"name":"BONUS_POINTS_AMULET_HOLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CHAD_COUNT_IN_TYPE","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"COMMON_AMULETS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COMMON_AMULET_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CREATURE_P_MULT","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CREATURE_TYPE_COUNT","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CREATURE_TYPE_COUNT_MAX","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FARMING_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FARMING_ENABLED","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FARM_DUNG_AMOUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_ALL_NORMIES","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_LANDS","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NFT_ID_MULTIPLIER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NORMIE_COUNT_IN_TYPE","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REVEAL_ENABLED","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOOL_TYPE_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOOL_UNSTAKE_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"},{"internalType":"address","name":"newOperator","type":"address"}],"name":"addOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allNormiesesLeft","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"amulets","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"creaturesBorn","outputs":[{"internalType":"uint16","name":"totalNormie","type":"uint16"},{"internalType":"uint16","name":"leftNormie","type":"uint16"},{"internalType":"uint16","name":"totalChad","type":"uint16"},{"internalType":"uint16","name":"leftChadToDiscover","type":"uint16"},{"internalType":"uint16","name":"totalDegen","type":"uint16"},{"internalType":"uint16","name":"leftDegenToDiscover","type":"uint16"},{"internalType":"uint16","name":"chadFarmAttempts","type":"uint16"},{"internalType":"uint16","name":"degenFarmAttempts","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eggs","outputs":[{"internalType":"contract IEggs","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_isEnabled","type":"bool"}],"name":"enableFarming","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isEnabled","type":"bool"}],"name":"enableReveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"farm","outputs":[{"internalType":"address","name":"land","type":"address"},{"internalType":"address","name":"creatures","type":"address"},{"internalType":"address","name":"inventory","type":"address"},{"internalType":"address","name":"bagstoken","type":"address"},{"internalType":"address","name":"dungtoken","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_creatureId","type":"uint256"},{"internalType":"uint256","name":"_landId","type":"uint256"}],"name":"farmDeploy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"farming","outputs":[{"internalType":"uint256","name":"creatureId","type":"uint256"},{"internalType":"uint256","name":"landId","type":"uint256"},{"internalType":"uint256","name":"harvestTime","type":"uint256"},{"internalType":"uint256","name":"amuletsPrice1","type":"uint256"},{"internalType":"uint256","name":"amuletsPrice2","type":"uint256"},{"internalType":"enum DegenFarmBase.Result","name":"harvest","type":"uint8"},{"internalType":"uint256","name":"harvestId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_creatureType","type":"uint8"}],"name":"getCreatureAmulets","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_creatureType","type":"uint8"}],"name":"getCreatureStat","outputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"getFarmingAllowedCreatures","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint8","name":"wantRarity","type":"uint8"}],"name":"getFarmingAllowedCreaturesWithRarity","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_farmingId","type":"uint256"}],"name":"getFarmingById","outputs":[{"components":[{"internalType":"uint256","name":"creatureId","type":"uint256"},{"internalType":"uint256","name":"landId","type":"uint256"},{"internalType":"uint256","name":"harvestTime","type":"uint256"},{"internalType":"uint256","name":"amuletsPrice1","type":"uint256"},{"internalType":"uint256","name":"amuletsPrice2","type":"uint256"},{"internalType":"enum DegenFarmBase.Result","name":"harvest","type":"uint8"},{"internalType":"uint256","name":"harvestId","type":"uint256"},{"internalType":"bool[2]","name":"commonAmuletInitialHold","type":"bool[2]"}],"internalType":"struct DegenFarmBase.FarmRecord","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"getOneAmuletPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"getUsersTokens","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"_weights","type":"uint32[]"}],"name":"getWeightedChoice","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_deployId","type":"uint256"}],"name":"harvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"creatureId","type":"uint256"}],"name":"isFarmingAllowedForCreature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"landCount","outputs":[{"internalType":"uint16","name":"total","type":"uint16"},{"internalType":"uint16","name":"left","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxAmuletBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"parents","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceProvider","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"},{"internalType":"contract IERC20","name":"anyTokens","type":"address"},{"internalType":"address","name":"_admin","type":"address"}],"name":"reclaimToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"},{"internalType":"address","name":"oldOperator","type":"address"}],"name":"removeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"name":"reveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_index","type":"uint8"},{"internalType":"address","name":"_token","type":"address"}],"name":"setAmuletForOneCreature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"setAmulets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_index","type":"uint8"},{"internalType":"address","name":"_token","type":"address"}],"name":"setOneCommonAmulet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_priceProvider","type":"address"}],"name":"setPriceProvider","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_contract","type":"address"},{"internalType":"address","name":"_newSigner","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_itemId","type":"uint8"}],"name":"stakeOneTool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_itemId","type":"uint8"}],"name":"unstakeOneTool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userStakedTools","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]