文件 1 的 6:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 2 的 6:GreatestLARP.sol
pragma solidity 0.8.4;
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./TokenRecover.sol";
abstract contract BotToken {
function lastMintedToken() external view virtual returns (uint256);
function mint(address user) external virtual returns (uint256);
function transferOwnership(address newOwner) public virtual;
}
abstract contract StatueToken {
function lastMintedToken() external view virtual returns (uint256);
function mint(address user) external virtual returns (uint256);
function transferOwnership(address newOwner) public virtual;
}
contract GreatestLARP is Ownable {
using SafeMath for uint256;
address payable immutable gitcoin;
struct Token {
address tokenAddress;
uint256 thresholdBots;
uint256 thresholdStatues;
uint256 price;
uint256 inflationRate;
uint256 totalSupply;
}
mapping(uint256 => Token) tokenMap;
mapping(uint256 => Token) statueMap;
uint256 public totalTokens;
uint256 public totalStatues;
modifier isValidLevel(uint256 level) {
require(level > 0, "Invalid level selected");
require(level <= totalTokens, "Invalid level selected");
require(level <= totalStatues, "Invalid level selected");
_;
}
constructor(
BotToken[] memory tokens,
StatueToken[] memory statueTokens,
uint256[] memory thresholdBots,
uint256[] memory thresholdStatues,
uint256 startPriceBot,
uint256 startPriceStatue,
uint256[] memory inflationRatesStatues,
uint256[] memory inflationRatesBots
) {
gitcoin = payable(address(0xde21F729137C5Af1b01d73aF1dC21eFfa2B8a0d6));
require(
tokens.length == thresholdBots.length,
"Mismatch length of tokens and threshold"
);
require(
statueTokens.length == thresholdStatues.length,
"Mismatch length of tokens and threshold"
);
for (uint256 i = 0; i < tokens.length; i++) {
totalTokens += 1;
tokenMap[totalTokens] = Token({
tokenAddress: address(tokens[i]),
thresholdBots: thresholdBots[i],
thresholdStatues: 0,
price: startPriceBot,
totalSupply: 300,
inflationRate: inflationRatesBots[i]
});
}
for (uint256 i = 0; i < statueTokens.length; i++) {
totalStatues += 1;
statueMap[totalStatues] = Token({
tokenAddress: address(statueTokens[i]),
thresholdBots: 0,
thresholdStatues: thresholdStatues[i],
price: startPriceStatue,
totalSupply: 5,
inflationRate: inflationRatesStatues[i]
});
}
}
function whompwhomp(uint256 _level) public isValidLevel(_level) onlyOwner {
tokenMap[_level].price = tokenMap[_level].price.sub(
tokenMap[_level].price.mul(10).div(100)
);
statueMap[_level].price = statueMap[_level].price.sub(
statueMap[_level].price.mul(10).div(100)
);
}
function lastestPriceForTokenLevel(uint256 _level)
public
view
isValidLevel(_level)
returns (uint256)
{
return tokenMap[_level].price;
}
function lastestPriceForStatueLevel(uint256 _level)
public
view
isValidLevel(_level)
returns (uint256)
{
return statueMap[_level].price;
}
function getDetailForTokenLevels()
public
view
returns (uint256[5][] memory)
{
uint256[5][] memory levels = new uint256[5][](totalTokens);
for (uint256 i = 1; i <= totalTokens; i++) {
uint256[5] memory levelInfo;
levelInfo[0] = tokenMap[i].price;
levelInfo[1] = tokenMap[i].thresholdBots;
levelInfo[2] = tokenMap[i].totalSupply;
levelInfo[3] = BotToken(tokenMap[i].tokenAddress).lastMintedToken();
levelInfo[4] = tokenMap[i].totalSupply - levelInfo[3];
levels[i - 1] = levelInfo;
}
return levels;
}
function getDetailForStatueLevels()
public
view
returns (uint256[5][] memory)
{
uint256[5][] memory levels = new uint256[5][](totalTokens);
for (uint256 i = 1; i <= totalStatues; i++) {
uint256[5] memory levelInfo;
levelInfo[0] = statueMap[i].price;
levelInfo[1] = statueMap[i].thresholdStatues;
levelInfo[2] = statueMap[i].totalSupply;
levelInfo[3] = StatueToken(statueMap[i].tokenAddress)
.lastMintedToken();
levelInfo[4] = statueMap[i].totalSupply - levelInfo[3];
levels[i - 1] = levelInfo;
}
return levels;
}
function requestMint(uint256 level)
public
payable
isValidLevel(level)
returns (uint256)
{
BotToken levelToken = BotToken(tokenMap[level].tokenAddress);
if (level > 1) {
uint256 previousLevel = level - 1;
require(
BotToken(tokenMap[previousLevel].tokenAddress)
.lastMintedToken() >= tokenMap[previousLevel].thresholdBots,
"You can't continue until the previous level threshold is reached"
);
}
require(msg.value >= tokenMap[level].price, "NOT ENOUGH");
uint256 currentPrice = tokenMap[level].price;
tokenMap[level].price = (currentPrice * tokenMap[level].inflationRate)
.div(1000);
require(
levelToken.lastMintedToken() <= tokenMap[level].totalSupply,
"Minting completed for this level"
);
uint256 id = levelToken.mint(msg.sender);
(bool success, ) = gitcoin.call{value: currentPrice}("");
require(success, "could not send");
uint256 refund = msg.value.sub(currentPrice);
if (refund > 0) {
(bool refundSent, ) = msg.sender.call{value: refund}("");
require(refundSent, "Refund could not be sent");
}
return id;
}
function requestMintStatue(uint256 level)
public
payable
isValidLevel(level)
returns (uint256)
{
StatueToken levelToken = StatueToken(statueMap[level].tokenAddress);
if (level > 1) {
uint256 previousLevel = level - 1;
require(
StatueToken(statueMap[previousLevel].tokenAddress)
.lastMintedToken() >=
statueMap[previousLevel].thresholdStatues,
"You can't continue until the previous level threshold is reached"
);
}
require(msg.value >= statueMap[level].price, "NOT ENOUGH");
uint256 currentPrice = statueMap[level].price;
statueMap[level].price = (currentPrice * 1350).div(1000);
require(
levelToken.lastMintedToken() <= statueMap[level].totalSupply,
"Minting completed for this level"
);
uint256 id = levelToken.mint(msg.sender);
(bool success, ) = gitcoin.call{value: currentPrice}("");
require(success, "could not send");
uint256 refund = msg.value.sub(currentPrice);
if (refund > 0) {
(bool refundSent, ) = msg.sender.call{value: refund}("");
require(refundSent, "Refund could not be sent");
}
return id;
}
function transferTokenOwnership(address to) public onlyOwner {
require(
to != 0x0000000000000000000000000000000000000000,
"cannot make balck hole owner"
);
for (uint256 i = 1; i <= totalTokens; i++) {
BotToken(tokenMap[i].tokenAddress).transferOwnership(to);
}
}
function transferStatueOwnership(address to) public onlyOwner {
require(
to != 0x0000000000000000000000000000000000000000,
"cannot make balck hole owner"
);
for (uint256 i = 1; i <= totalStatues; i++) {
StatueToken(statueMap[i].tokenAddress).transferOwnership(to);
}
}
}
文件 3 的 6:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 4 的 6:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_setOwner(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_setOwner(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 5 的 6:SafeMath.sol
pragma solidity ^0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
文件 6 的 6:TokenRecover.sol
pragma solidity 0.8.4;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract TokenRecover is Ownable {
function recoverERC20(address tokenAddress, uint256 tokenAmount) public onlyOwner {
IERC20(tokenAddress).transfer(owner(), tokenAmount);
}
}
{
"compilationTarget": {
"contracts/GreatestLARP.sol": "GreatestLARP"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract BotToken[]","name":"tokens","type":"address[]"},{"internalType":"contract StatueToken[]","name":"statueTokens","type":"address[]"},{"internalType":"uint256[]","name":"thresholdBots","type":"uint256[]"},{"internalType":"uint256[]","name":"thresholdStatues","type":"uint256[]"},{"internalType":"uint256","name":"startPriceBot","type":"uint256"},{"internalType":"uint256","name":"startPriceStatue","type":"uint256"},{"internalType":"uint256[]","name":"inflationRatesStatues","type":"uint256[]"},{"internalType":"uint256[]","name":"inflationRatesBots","type":"uint256[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"getDetailForStatueLevels","outputs":[{"internalType":"uint256[5][]","name":"","type":"uint256[5][]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDetailForTokenLevels","outputs":[{"internalType":"uint256[5][]","name":"","type":"uint256[5][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_level","type":"uint256"}],"name":"lastestPriceForStatueLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_level","type":"uint256"}],"name":"lastestPriceForTokenLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"level","type":"uint256"}],"name":"requestMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"level","type":"uint256"}],"name":"requestMintStatue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"totalStatues","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferStatueOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferTokenOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_level","type":"uint256"}],"name":"whompwhomp","outputs":[],"stateMutability":"nonpayable","type":"function"}]