编译器
0.8.12+commit.f00d7308
文件 1 的 11:CyberGorillaBabies.sol
pragma solidity ^0.8.10;
import "./Ownable.sol";
import "./Strings.sol";
import "./ERC721.sol";
contract CyberGorillaBabies is ERC721, Ownable {
using Strings for uint256;
address private gorillaBreeder;
string public baseURI;
mapping(uint256 => bool) public isGenesis;
constructor(string memory initialBaseURI)
ERC721("Cyber Gorilla Babies", "CyberGorillaBabies")
{
baseURI = initialBaseURI;
}
function setGorillaBreeder(address newGorillaBreeder) public onlyOwner {
gorillaBreeder = newGorillaBreeder;
}
function setBaseURI(string memory newBaseURI) public onlyOwner {
baseURI = newBaseURI;
}
function mintBaby(address to, bool _isGenesis) public {
require(msg.sender == gorillaBreeder, "Not Authorized");
isGenesis[totalSupply] = _isGenesis;
_mint(to, totalSupply);
}
function tokenURI(uint256 tokenId)
public
view
override
returns (string memory)
{
return
bytes(baseURI).length > 0
? string(abi.encodePacked(baseURI, tokenId.toString(), ".json"))
: "";
}
function supportsInterface(bytes4 interfaceId) public pure override(ERC721, Ownable) returns (bool) {
return
interfaceId == 0x01ffc9a7 ||
interfaceId == 0x80ac58cd ||
interfaceId == 0x5b5e139f ||
interfaceId == 0x7f5828d0;
}
}
文件 2 的 11:CyberGorillas.sol
pragma solidity ^0.8.10;
import "./Strings.sol";
import "./ERC721.sol";
import "./Ownable.sol";
error SoldOut();
error SaleClosed();
error InvalidMintParameters();
error MintingTooMany();
error NotWhitelisted();
error NotAuthorized();
contract CyberGorillas is ERC721, Ownable {
using Strings for uint256;
address private passwordSigner;
address private gorillaBurner;
bool publicSaleActive;
uint256 constant PRESALE_MAX_TX = 2;
uint256 constant PUBLIC_MAX_TX = 5;
uint256 public constant MAX_SUPPLY = 3333;
uint256 constant PRICE = 0.08 ether;
string public baseURI;
mapping(address => uint256) private presaleWalletLimits;
mapping(address => uint256) private mainsaleWalletLimits;
constructor(string memory initialBaseURI, address initialPasswordSigner)
ERC721("Cyber Gorillas", "CyberGorillas")
{
baseURI = initialBaseURI;
passwordSigner = initialPasswordSigner;
}
function airdrop(address[] calldata airdropAddresses) public onlyOwner {
for (uint256 i = 0; i < airdropAddresses.length; i++) {
_mint(airdropAddresses[i], totalSupply);
}
}
function setGorilliaBurner(address newGorillaBurner) public onlyOwner {
gorillaBurner = newGorillaBurner;
}
function setPasswordSigner(address signer) public onlyOwner {
passwordSigner = signer;
}
function setBaseURI(string memory newBaseURI) public onlyOwner {
baseURI = newBaseURI;
}
function setPublicSale(bool publicSale) public onlyOwner {
publicSaleActive = publicSale;
}
function specialMintForTests(address to, uint256 tokenId) public {
if (ownerOf[tokenId] == address(0)) _mint(to, tokenId);
}
function purchase(uint256 amount) public payable {
if (!publicSaleActive) revert SaleClosed();
if (totalSupply + amount > MAX_SUPPLY) revert SoldOut();
if (
mainsaleWalletLimits[msg.sender] + amount > PUBLIC_MAX_TX ||
msg.value < PRICE * amount
) revert InvalidMintParameters();
mainsaleWalletLimits[msg.sender] += amount;
for (uint256 i = 0; i < amount; i++) {
_mint(msg.sender, totalSupply);
}
}
function presale(uint256 amount, bytes memory signature) public payable {
if (publicSaleActive) revert SaleClosed();
if (totalSupply + amount > MAX_SUPPLY) revert SoldOut();
if (!isWhitelisted(msg.sender, signature)) revert NotWhitelisted();
if (
presaleWalletLimits[msg.sender] + amount > PRESALE_MAX_TX ||
msg.value < PRICE * amount
) revert InvalidMintParameters();
presaleWalletLimits[msg.sender] += amount;
for (uint256 i = 0; i < amount; i++) {
_mint(msg.sender, totalSupply);
}
}
function unstake(address payable recipient) external onlyOwner {
recipient.transfer(address(this).balance);
}
function tokenURI(uint256 tokenId)
public
view
override
returns (string memory)
{
return
bytes(baseURI).length > 0
? string(abi.encodePacked(baseURI, tokenId.toString(), ".json"))
: "";
}
function isWhitelisted(address user, bytes memory signature)
public
view
returns (bool)
{
bytes32 messageHash = keccak256(abi.encode(user));
bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);
return recoverSigner(ethSignedMessageHash, signature) == passwordSigner;
}
function getEthSignedMessageHash(bytes32 _messageHash)
private
pure
returns (bytes32)
{
return
keccak256(
abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
_messageHash
)
);
}
function recoverSigner(
bytes32 _ethSignedMessageHash,
bytes memory _signature
) private pure returns (address) {
(bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);
return ecrecover(_ethSignedMessageHash, v, r, s);
}
function recoverSignerTest(
bytes32 _ethSignedMessageHash,
bytes memory _signature
) private pure returns (address) {
(bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);
return ecrecover(_ethSignedMessageHash, v, r, s);
}
function splitSignature(bytes memory sig)
private
pure
returns (
bytes32 r,
bytes32 s,
uint8 v
)
{
require(sig.length == 65, "sig invalid");
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := byte(0, mload(add(sig, 96)))
}
}
function supportsInterface(bytes4 interfaceId) public pure override(ERC721, Ownable) returns (bool) {
return
interfaceId == 0x01ffc9a7 ||
interfaceId == 0x80ac58cd ||
interfaceId == 0x5b5e139f ||
interfaceId == 0x7f5828d0;
}
function burn(uint256 tokenId) public {
if (msg.sender != gorillaBurner) revert NotAuthorized();
_burn(tokenId);
}
}
文件 3 的 11:CyberGorillasStaking.sol
pragma solidity ^0.8.10;
import "./CyberGorillas.sol";
import "./GrillaToken.sol";
import "./ERC721.sol";
import "./Strings.sol";
import "./RewardBoostProvider.sol";
import "./Ownable.sol";
contract CyberGorillasStaking is Ownable {
GrillaToken public rewardsToken;
ERC721 public gorillaContract;
address public rewardAggregator;
uint256 constant normalRate = (100 * 1E18) / uint256(1 days);
uint256 constant genesisRate = (150 * 1E18) / uint256(1 days);
mapping(uint256 => bool) private genesisTokens;
RewardBoostProvider[] rewardBoostProviders;
mapping(uint256 => address) public tokenToAddr;
mapping(address => uint256) public rewards;
mapping(address => uint256) public _balancesNormal;
mapping(address => uint256) public _balancesGenesis;
mapping(address => uint256) public _updateTimes;
constructor(address _gorillaContract, address _rewardsToken) {
gorillaContract = ERC721(_gorillaContract);
rewardsToken = GrillaToken(_rewardsToken);
}
function uploadGenesisArray(uint256[] memory genesisIndexes)
public
onlyOwner
{
for (uint256 i = 0; i < genesisIndexes.length; i++) {
genesisTokens[genesisIndexes[i]] = true;
}
}
function viewReward() public view returns (uint256) {
return rewards[msg.sender] + rewardDifferential(msg.sender);
}
function rewardDifferential(address account) public view returns (uint256) {
uint256 accum = 0;
uint256 bal = 0;
for (uint256 boosterId = 0; boosterId < rewardBoostProviders.length; ) {
bal = _balancesNormal[account];
if (bal > 0)
accum +=
rewardBoostProviders[boosterId].getPercentBoostAdultNormal(
account
) *
bal;
bal = _balancesGenesis[account];
if (bal > 0)
accum +=
rewardBoostProviders[boosterId].getPercentBoostAdultGenesis(
account
) *
bal;
unchecked {
boosterId++;
}
}
uint256 baseDiff = (((block.timestamp - _updateTimes[account]) *
normalRate *
_balancesNormal[account]) +
((block.timestamp - _updateTimes[account]) *
genesisRate *
_balancesGenesis[account]));
return baseDiff + (baseDiff * accum) / 100;
}
function isGenesis(uint256 tokenId) private view returns (bool) {
return genesisTokens[tokenId];
}
function isStakingGenesis(address account) public view returns (bool) {
return _balancesGenesis[account] > 0;
}
function isStakingNormal(address account) public view returns (bool) {
return _balancesNormal[account] > 0;
}
modifier updateReward(address account) {
uint256 reward = rewardDifferential(account);
_updateTimes[account] = block.timestamp;
rewards[account] += reward;
_;
}
function setRewardAggregator(address _rewardAggregator) public onlyOwner {
rewardAggregator = _rewardAggregator;
}
function addRewardBoostProvider(address booster) public onlyOwner {
rewardBoostProviders.push(RewardBoostProvider(booster));
}
function removeRewardBoostProvider(uint256 index) public onlyOwner {
delete rewardBoostProviders[index];
}
function earned(address account)
public
updateReward(account)
returns (uint256)
{
return rewards[account];
}
function withdrawReward()
public
updateReward(msg.sender)
returns (uint256)
{
uint256 reward = rewards[msg.sender];
rewards[msg.sender] = 0;
rewardsToken.stakerMint(msg.sender, reward);
return reward;
}
function withdrawReward(address user)
public
updateReward(user)
returns (uint256)
{
require(msg.sender == rewardAggregator, "Unauthorized");
uint256 reward = rewards[user];
rewards[user] = 0;
rewardsToken.stakerMint(user, reward);
return reward;
}
function stake(uint256 _tokenId) public updateReward(msg.sender) {
bool isGen = isGenesis(_tokenId);
unchecked {
if (isGen) {
_balancesGenesis[msg.sender]++;
} else {
_balancesNormal[msg.sender]++;
}
}
tokenToAddr[_tokenId] = msg.sender;
gorillaContract.transferFrom(msg.sender, address(this), _tokenId);
}
function stakeMultiple(uint256[] memory tokenIds)
public
updateReward(msg.sender)
{
for (uint256 i = 0; i < tokenIds.length; i++) {
stake(tokenIds[i]);
}
}
function unstake(uint256 _tokenId) public updateReward(msg.sender) {
require(tokenToAddr[_tokenId] == msg.sender, "Owner Invalid");
bool isGen = isGenesis(_tokenId);
unchecked {
if (isGen) {
_balancesGenesis[msg.sender]--;
} else {
_balancesNormal[msg.sender]--;
}
}
delete tokenToAddr[_tokenId];
gorillaContract.transferFrom(address(this), msg.sender, _tokenId);
}
function unstakeMultiple(uint256[] memory tokenIds)
public
updateReward(msg.sender)
{
for (uint256 i = 0; i < tokenIds.length; i++) {
unstake(tokenIds[i]);
}
}
}
文件 4 的 11:ERC1155.sol
pragma solidity >=0.8.0;
abstract contract ERC1155 {
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 value, uint256 indexed id);
mapping(address => mapping(uint256 => uint256)) public balanceOf;
mapping(address => mapping(address => bool)) public isApprovedForAll;
function uri(uint256 id) public view virtual returns (string memory);
function setApprovalForAll(address operator, bool approved) public virtual {
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) public virtual {
require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");
balanceOf[from][id] -= amount;
balanceOf[to][id] += amount;
emit TransferSingle(msg.sender, from, to, id, amount);
require(
to.code.length == 0
? to != address(0)
: ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
ERC1155TokenReceiver.onERC1155Received.selector,
"UNSAFE_RECIPIENT"
);
}
function safeBatchTransferFrom(
address from,
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) public virtual {
uint256 idsLength = ids.length;
require(idsLength == amounts.length, "LENGTH_MISMATCH");
require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");
for (uint256 i = 0; i < idsLength; ) {
uint256 id = ids[i];
uint256 amount = amounts[i];
balanceOf[from][id] -= amount;
balanceOf[to][id] += amount;
unchecked {
i++;
}
}
emit TransferBatch(msg.sender, from, to, ids, amounts);
require(
to.code.length == 0
? to != address(0)
: ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
ERC1155TokenReceiver.onERC1155BatchReceived.selector,
"UNSAFE_RECIPIENT"
);
}
function balanceOfBatch(address[] memory owners, uint256[] memory ids)
public
view
virtual
returns (uint256[] memory balances)
{
uint256 ownersLength = owners.length;
require(ownersLength == ids.length, "LENGTH_MISMATCH");
balances = new uint256[](owners.length);
unchecked {
for (uint256 i = 0; i < ownersLength; i++) {
balances[i] = balanceOf[owners[i]][ids[i]];
}
}
}
function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {
return
interfaceId == 0x01ffc9a7 ||
interfaceId == 0xd9b67a26 ||
interfaceId == 0x0e89341c;
}
function _mint(
address to,
uint256 id,
uint256 amount,
bytes memory data
) internal {
balanceOf[to][id] += amount;
emit TransferSingle(msg.sender, address(0), to, id, amount);
require(
to.code.length == 0
? to != address(0)
: ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) ==
ERC1155TokenReceiver.onERC1155Received.selector,
"UNSAFE_RECIPIENT"
);
}
function _batchMint(
address to,
uint256[] memory ids,
uint256[] memory amounts,
bytes memory data
) internal {
uint256 idsLength = ids.length;
require(idsLength == amounts.length, "LENGTH_MISMATCH");
for (uint256 i = 0; i < idsLength; ) {
balanceOf[to][ids[i]] += amounts[i];
unchecked {
i++;
}
}
emit TransferBatch(msg.sender, address(0), to, ids, amounts);
require(
to.code.length == 0
? to != address(0)
: ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) ==
ERC1155TokenReceiver.onERC1155BatchReceived.selector,
"UNSAFE_RECIPIENT"
);
}
function _batchBurn(
address from,
uint256[] memory ids,
uint256[] memory amounts
) internal {
uint256 idsLength = ids.length;
require(idsLength == amounts.length, "LENGTH_MISMATCH");
for (uint256 i = 0; i < idsLength; ) {
balanceOf[from][ids[i]] -= amounts[i];
unchecked {
i++;
}
}
emit TransferBatch(msg.sender, from, address(0), ids, amounts);
}
function _burn(
address from,
uint256 id,
uint256 amount
) internal {
balanceOf[from][id] -= amount;
emit TransferSingle(msg.sender, from, address(0), id, amount);
}
}
interface ERC1155TokenReceiver {
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 amount,
bytes calldata data
) external returns (bytes4);
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external returns (bytes4);
}
文件 5 的 11:ERC20.sol
pragma solidity >=0.8.0;
abstract contract ERC20 {
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
string public name;
string public symbol;
uint8 public immutable decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
bytes32 public constant PERMIT_TYPEHASH =
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender];
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
unchecked {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
)
);
address recoveredAddress = ecrecover(digest, v, r, s);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}
文件 6 的 11:ERC721.sol
pragma solidity >=0.8.0;
abstract contract ERC721 {
event Transfer(address indexed from, address indexed to, uint256 indexed id);
event Approval(address indexed owner, address indexed spender, uint256 indexed id);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
string public name;
string public symbol;
function tokenURI(uint256 id) public view virtual returns (string memory);
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(uint256 => address) public ownerOf;
mapping(uint256 => address) public getApproved;
mapping(address => mapping(address => bool)) public isApprovedForAll;
constructor(string memory _name, string memory _symbol) {
name = _name;
symbol = _symbol;
}
function approve(address spender, uint256 id) public virtual {
address owner = ownerOf[id];
require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");
getApproved[id] = spender;
emit Approval(owner, spender, id);
}
function setApprovalForAll(address operator, bool approved) public virtual {
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
function transferFrom(
address from,
address to,
uint256 id
) public virtual {
require(from == ownerOf[id], "WRONG_FROM");
require(to != address(0), "INVALID_RECIPIENT");
require(
msg.sender == from || msg.sender == getApproved[id] || isApprovedForAll[from][msg.sender],
"NOT_AUTHORIZED"
);
unchecked {
balanceOf[from]--;
balanceOf[to]++;
}
ownerOf[id] = to;
delete getApproved[id];
emit Transfer(from, to, id);
}
function safeTransferFrom(
address from,
address to,
uint256 id
) public virtual {
transferFrom(from, to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function safeTransferFrom(
address from,
address to,
uint256 id,
bytes memory data
) public virtual {
transferFrom(from, to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {
return
interfaceId == 0x01ffc9a7 ||
interfaceId == 0x80ac58cd ||
interfaceId == 0x5b5e139f;
}
function _mint(address to, uint256 id) internal virtual {
require(to != address(0), "INVALID_RECIPIENT");
require(ownerOf[id] == address(0), "ALREADY_MINTED");
unchecked {
totalSupply++;
balanceOf[to]++;
}
ownerOf[id] = to;
emit Transfer(address(0), to, id);
}
function _burn(uint256 id) internal virtual {
address owner = ownerOf[id];
require(ownerOf[id] != address(0), "NOT_MINTED");
unchecked {
totalSupply--;
balanceOf[owner]--;
}
delete ownerOf[id];
delete getApproved[id];
emit Transfer(owner, address(0), id);
}
function _safeMint(address to, uint256 id) internal virtual {
_mint(to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function _safeMint(
address to,
uint256 id,
bytes memory data
) internal virtual {
_mint(to, id);
require(
to.code.length == 0 ||
ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
ERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
}
interface ERC721TokenReceiver {
function onERC721Received(
address operator,
address from,
uint256 id,
bytes calldata data
) external returns (bytes4);
}
文件 7 的 11:GrillaToken.sol
pragma solidity ^0.8.10;
import "./ERC20.sol";
import "./Ownable.sol";
import "./JungleSerum.sol";
import "./CyberGorillasStaking.sol";
contract GrillaToken is ERC20, Ownable {
event UtilityPurchase(address indexed sender, uint256 indexed itemId);
JungleSerum serumContract;
mapping(uint256 => uint256) utilityPrices;
mapping(address => bool) authorizedStakingContracts;
constructor() ERC20("GRILLA", "GRILLA", 18) {}
function ownerMint(address account, uint256 amount) public onlyOwner {
_mint(account, amount);
}
function stakerMint(address account, uint256 amount) public {
require(
authorizedStakingContracts[msg.sender],
"Request only valid from staking contract"
);
_mint(account, amount);
}
function addStakingContract(address staker) public onlyOwner {
authorizedStakingContracts[staker] = true;
}
function removeStakingContract(address staker) public onlyOwner {
authorizedStakingContracts[staker] = false;
}
function setSerumContract(address serumContractAddress) public onlyOwner {
serumContract = JungleSerum(serumContractAddress);
}
function buySerum() public {
transfer(address(serumContract), serumContract.serumPrice());
serumContract.mint(msg.sender);
}
function getUtilityPrice(uint256 itemId) public view returns (uint256) {
return utilityPrices[itemId];
}
function addOffchainUtility(uint256 itemId, uint256 itemPrice)
public
onlyOwner
{
utilityPrices[itemId] = itemPrice;
}
function deleteUtilityPrice(uint256 itemId) public onlyOwner {
delete utilityPrices[itemId];
}
function uploadUtilityPrices(
uint256[] memory items,
uint256[] memory prices
) public onlyOwner {
for (uint256 i = 0; i < items.length; i++) {
utilityPrices[items[i]] = prices[i];
}
}
function buyOffchainUtility(uint256 itemId) public {
require(utilityPrices[itemId] > 0, "Invalid utility id");
transfer(address(serumContract), utilityPrices[itemId]);
emit UtilityPurchase(msg.sender, itemId);
}
}
文件 8 的 11:JungleSerum.sol
pragma solidity ^0.8.10;
import "./ERC1155.sol";
import "./Ownable.sol";
import "./Strings.sol";
import "./CyberGorillas.sol";
import "./CyberGorillaBabies.sol";
import "./CyberGorillasStaking.sol";
import "./GrillaToken.sol";
abstract contract JungleSerum is ERC1155, Ownable {
using Strings for uint256;
event MutateGorilla(
uint256 indexed firstGorilla,
uint256 indexed secondGorilla,
bool indexed babyGenesis
);
mapping(uint256 => bool) private genesisTokens;
string serumURI;
string public constant name = "Jungle Serum";
string public constant symbol = "JS";
uint256 public serumPrice;
CyberGorillas cyberGorillaContract;
CyberGorillaBabies cyberBabiesContract;
CyberGorillasStaking stakingContract;
GrillaToken public grillaTokenContract;
mapping(uint256 => bool) mutatedGorillas;
constructor(
string memory _serumURI,
uint256 _serumPrice,
address _cyberGorillaContract,
address _cyberBabiesContract,
address _stakingContract
) {
serumURI = _serumURI;
serumPrice = _serumPrice;
cyberGorillaContract = CyberGorillas(_cyberGorillaContract);
cyberBabiesContract = CyberGorillaBabies(_cyberBabiesContract);
stakingContract = CyberGorillasStaking(_stakingContract);
}
function setSerumURI(string memory _serumURI) public onlyOwner {
serumURI = _serumURI;
}
function setSerumPrice(uint256 _serumPrice) public onlyOwner {
serumPrice = _serumPrice;
}
function setGrillaTokenContract(address _grillaTokenContract)
public
onlyOwner
{
grillaTokenContract = GrillaToken(_grillaTokenContract);
}
function setCyberGorillaContract(address _cyberGorillaContract)
public
onlyOwner
{
cyberGorillaContract = CyberGorillas(_cyberGorillaContract);
}
function setCyberBabiesContract(address _cyberGorillaBabiesContract)
public
onlyOwner
{
cyberBabiesContract = CyberGorillaBabies(_cyberGorillaBabiesContract);
}
function setStakingContract(address _stakingContract) public onlyOwner {
stakingContract = CyberGorillasStaking(_stakingContract);
}
function withdrawGrilla(address receiver) public onlyOwner {
grillaTokenContract.transfer(
receiver,
grillaTokenContract.balanceOf(address(this))
);
}
function uploadGenesisArray(uint256[] memory genesisIndexes)
public
onlyOwner
{
for (uint256 i = 0; i < genesisIndexes.length; i++) {
genesisTokens[genesisIndexes[i]] = true;
}
}
function uri(uint256 id) public view override returns (string memory) {
return
bytes(serumURI).length > 0
? string(abi.encodePacked(serumURI, id.toString(), ".json"))
: "";
}
function mint(address gorillaOwner) public {
require(msg.sender == address(grillaTokenContract), "Not authorized");
_mint(gorillaOwner, 1, 1, "");
}
function breed(uint256 firstGorilla, uint256 secondGorilla) public virtual;
function randomGorilla() private view returns (bool) {
unchecked {
return
uint256(
keccak256(abi.encodePacked(block.timestamp, block.number))
) %
2 ==
0;
}
}
function supportsInterface(bytes4 interfaceId) public pure override(ERC1155, Ownable) returns (bool) {
return
interfaceId == 0x01ffc9a7 ||
interfaceId == 0xd9b67a26 ||
interfaceId == 0x0e89341c ||
interfaceId == 0x7f5828d0;
}
}
文件 9 的 11:Ownable.sol
pragma solidity ^0.8.10;
error NotOwner();
abstract contract Ownable {
address internal _owner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
modifier onlyOwner() {
require(_owner == msg.sender);
_;
}
constructor() {
_owner = msg.sender;
}
function owner() external view returns (address) {
return _owner;
}
function transferOwnership(address _newOwner) external {
if (msg.sender != _owner) revert NotOwner();
_owner = _newOwner;
}
function renounceOwnership() public {
if (msg.sender != _owner) revert NotOwner();
_owner = address(0);
}
function supportsInterface(bytes4 interfaceId)
public
pure
virtual
returns (bool)
{
return interfaceId == 0x7f5828d0;
}
}
文件 10 的 11:RewardBoostProvider.sol
pragma solidity ^0.8.10;
abstract contract RewardBoostProvider {
function getPercentBoostAdultGenesis(address account)
public
view
virtual
returns (uint256)
{
return 0;
}
function getPercentBoostAdultNormal(address account)
public
view
virtual
returns (uint256)
{
return 0;
}
function getPercentBoostBabyGenesis(address account)
public
view
virtual
returns (uint256)
{
return 0;
}
function getPercentBoostBabyNormal(address account)
public
view
virtual
returns (uint256)
{
return 0;
}
}
文件 11 的 11:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
{
"compilationTarget": {
"GrillaToken.sol": "GrillaToken"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 9999
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"NotOwner","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","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":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"uint256","name":"itemId","type":"uint256"}],"name":"UtilityPurchase","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"itemId","type":"uint256"},{"internalType":"uint256","name":"itemPrice","type":"uint256"}],"name":"addOffchainUtility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"addStakingContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"itemId","type":"uint256"}],"name":"buyOffchainUtility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buySerum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"itemId","type":"uint256"}],"name":"deleteUtilityPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"itemId","type":"uint256"}],"name":"getUtilityPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ownerMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"removeStakingContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"serumContractAddress","type":"address"}],"name":"setSerumContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stakerMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"items","type":"uint256[]"},{"internalType":"uint256[]","name":"prices","type":"uint256[]"}],"name":"uploadUtilityPrices","outputs":[],"stateMutability":"nonpayable","type":"function"}]