//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
);
}
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));
}
}
/** ****************************************************************************
* @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);
}
}
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*
* _Available since v2.4.0._
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* _Available since v2.4.0._
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
/*
* @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.
*/
contract Context {
// Empty internal constructor, to prevent people from mistakenly deploying
// an instance of this contract, which should be used via inheritance.
constructor () { }
// solhint-disable-previous-line no-empty-blocks
function _msgSender() internal view returns (address) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
/**
* @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.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Returns true if the caller is the current owner.
*/
function isOwner() public view returns (bool) {
return _msgSender() == _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 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 onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
/**
* _Available since v3.1._
*/
interface IERC1155Receiver {
/**
@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);
}
interface MoonDoge {
function mint(
address _to,
uint256 _id,
uint256 _quantity,
bytes calldata _data
) external;
function create(
uint256 _maxSupply,
uint256 _initialSupply,
string calldata _uri,
bytes calldata _data
) external returns (uint256 tokenId);
function safeTransferFrom(
address _from,
address _to,
uint256 _id,
uint256 _amount,
bytes calldata _data
) external;
function safeBatchTransferFrom(
address _from,
address _to,
uint256[] calldata _ids,
uint256[] calldata _amounts,
bytes calldata _data
) external;
function balanceOf(address _owner, uint256 _id) external view returns (uint256);
function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids)
external
view
returns (uint256[] memory);
function setApprovalForAll(address _operator, bool _approved) external;
function isApprovedForAll(address _owner, address _operator) external view returns (bool isOperator);
function tokenIdByTraits(bytes2 traits) external view returns (uint256 tokenId);
}
interface IERC1155 {
event TransferSingle(
address indexed _operator,
address indexed _from,
address indexed _to,
uint256 _id,
uint256 _amount
);
event TransferBatch(
address indexed _operator,
address indexed _from,
address indexed _to,
uint256[] _ids,
uint256[] _amounts
);
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
event URI(string _amount, uint256 indexed _id);
function mint(
address _to,
uint256 _id,
uint256 _quantity,
bytes calldata _data
) external;
function create(
uint256 _maxSupply,
uint256 _initialSupply,
string calldata _uri,
bytes calldata _data
) external returns (uint256 tokenId);
function safeTransferFrom(
address _from,
address _to,
uint256 _id,
uint256 _amount,
bytes calldata _data
) external;
function safeBatchTransferFrom(
address _from,
address _to,
uint256[] calldata _ids,
uint256[] calldata _amounts,
bytes calldata _data
) external;
function balanceOf(address _owner, uint256 _id) external view returns (uint256);
function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids)
external
view
returns (uint256[] memory);
function setApprovalForAll(address _operator, bool _approved) external;
function isApprovedForAll(address _owner, address _operator) external view returns (bool isOperator);
}
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see {ERC20Detailed}.
*/
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);
}
contract dogeIncubator is Ownable, IERC1155Receiver, VRFConsumerBase {
using SafeMath for uint256;
bytes2[] public availableDoges;
uint256 public nftid;
address public eggAddress;
address public crackedEggAddress;
uint256 public crackedEggId;
address public dogeAddress;
bool public active = false;
bytes32 internal keyHash;
bytes32 public currentRequestId;
event Request(bytes32 requestId);
event DogeBirth(bytes2 dogeType, uint256 pickedIndex);
/*
Chainlink VRF:
LINK 0x514910771AF9Ca656af840dff83E8264EcF986CA
VRF Coordinator 0xf0d54349aDdcf704F77AE15b96510dEA15cb7952
Key Hash 0xAA77729D3466CA35AE8D28B3BBAC7CC36A5031EFDC430821C02BC31A238AF445
Fee 2 LINK
*/
uint256 linkFee = 2 ether;
// requestId => hatcher address
mapping (bytes32 => address) public eggHatcher;
// requestId => isFulfilled address
mapping (bytes32 => bool) public requestFulfilled;
constructor(address _eggAddress, uint256 _eggid, address _crackedEggAddress, uint256 _crackedEggId, address _dogeAddress) VRFConsumerBase(0xf0d54349aDdcf704F77AE15b96510dEA15cb7952, 0x514910771AF9Ca656af840dff83E8264EcF986CA) {
eggAddress = _eggAddress;
nftid = _eggid;
crackedEggAddress = _crackedEggAddress;
crackedEggId = _crackedEggId;
dogeAddress = _dogeAddress;
keyHash = 0xAA77729D3466CA35AE8D28B3BBAC7CC36A5031EFDC430821C02BC31A238AF445;
}
function hatchEgg() public {
require(active == true, "The incubator is currently disabled");
// send user's eggs to this address
IERC1155(eggAddress).safeTransferFrom(msg.sender, address(this), nftid, 1, "");
// send the user a cracked egg
IERC1155(crackedEggAddress).safeTransferFrom(address(this), msg.sender, crackedEggId, 1, "");
currentRequestId = requestRandomness(keyHash, linkFee);
eggHatcher[currentRequestId] = msg.sender;
emit Request(currentRequestId);
}
// Skips eggs, cracked eggs, and incubator state check
function adminHatchEgg(address _receiver) public onlyOwner {
currentRequestId = requestRandomness(keyHash, linkFee);
eggHatcher[currentRequestId] = _receiver;
emit Request(currentRequestId);
}
function finishHatchingEgg(bytes32 requestId, uint256 randomNumber) private {
require(availableDoges.length >= 1, "No more doges");
uint256 randomDoge = 0;
if(availableDoges.length > 1) {
randomDoge = randomNumber % (availableDoges.length-1);
}
bytes2 pickedDoge = availableDoges[randomDoge];
availableDoges[randomDoge] = availableDoges[availableDoges.length - 1];
availableDoges.pop();
emit DogeBirth(pickedDoge, randomDoge);
uint256 pickedDogeId = MoonDoge(dogeAddress).tokenIdByTraits(pickedDoge);
address hatcher = eggHatcher[requestId];
MoonDoge(dogeAddress).mint(hatcher, pickedDogeId, 1, "");
requestFulfilled[requestId] = true;
}
function setActive(bool isActive) public onlyOwner {
active = isActive;
}
function addAvailableDoges(bytes2[] memory doges, uint256[] memory amounts) public onlyOwner {
for (uint256 i = 0; i < doges.length; i++) {
for (uint256 j = 0; j < amounts[i]; j++) {
availableDoges.push(doges[i]);
}
}
}
function removeAvailableDoges(bool confirm) public onlyOwner {
require(confirm == true, "You need to confirm");
delete availableDoges;
}
function withdrawCrackedEggs(address to) public onlyOwner {
uint256 amount = IERC1155(crackedEggAddress).balanceOf(address(this), crackedEggId);
IERC1155(crackedEggAddress).safeTransferFrom(address(this), to, crackedEggId, amount, "");
}
function withdrawEther(address payable to, uint256 amount) public onlyOwner {
to.transfer(amount);
}
function withdrawTokens(address token, address to, uint256 amount) public onlyOwner {
IERC20 token = IERC20(token);
token.transfer(to, amount);
}
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)"));
}
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)"));
}
/// @dev Called by Chainlink VRF random number provider.
function fulfillRandomness(bytes32 requestId, uint randomness) internal override {
require(eggHatcher[requestId] != address(0), "The requestId is invalid.");
require(requestFulfilled[requestId] == false, "This request is already fulfilled.");
finishHatchingEgg(requestId, randomness);
}
}
{
"compilationTarget": {
"dogeIncubator.sol": "dogeIncubator"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_eggAddress","type":"address"},{"internalType":"uint256","name":"_eggid","type":"uint256"},{"internalType":"address","name":"_crackedEggAddress","type":"address"},{"internalType":"uint256","name":"_crackedEggId","type":"uint256"},{"internalType":"address","name":"_dogeAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes2","name":"dogeType","type":"bytes2"},{"indexed":false,"internalType":"uint256","name":"pickedIndex","type":"uint256"}],"name":"DogeBirth","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":"bytes32","name":"requestId","type":"bytes32"}],"name":"Request","type":"event"},{"inputs":[],"name":"active","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes2[]","name":"doges","type":"bytes2[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"addAvailableDoges","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"adminHatchEgg","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"availableDoges","outputs":[{"internalType":"bytes2","name":"","type":"bytes2"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"crackedEggAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"crackedEggId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRequestId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dogeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eggAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"eggHatcher","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hatchEgg","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftid","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":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"rawFulfillRandomness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"confirm","type":"bool"}],"name":"removeAvailableDoges","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestFulfilled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"isActive","type":"bool"}],"name":"setActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"withdrawCrackedEggs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]