编译器
0.8.16+commit.07a7930e
文件 1 的 9:IERC165.sol
pragma solidity ^0.8.10;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 2 的 9:IERC20.sol
pragma solidity ^0.8.7;
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);
}
文件 3 的 9:IERC721.sol
pragma solidity ^0.8.10;
import "IERC165.sol";
interface IERC721 is IERC165 {
event Transfer( address indexed from_, address indexed to_, uint256 indexed tokenId_ );
event Approval( address indexed owner_, address indexed approved_, uint256 indexed tokenId_ );
event ApprovalForAll( address indexed owner_ , address indexed operator_ , bool approved_ );
function approve( address to_, uint256 tokenId_ ) external;
function safeTransferFrom( address from_, address to_, uint256 tokenId_ ) external;
function safeTransferFrom( address from_, address to_, uint256 tokenId_, bytes calldata data_ ) external;
function setApprovalForAll( address operator_, bool approved_ ) external;
function transferFrom( address from_, address to_, uint256 tokenId_ ) external;
function balanceOf( address tokenOwner_ ) external view returns ( uint256 balance );
function getApproved( uint256 tokenId_ ) external view returns ( address operator );
function isApprovedForAll( address tokenOwner_, address operator_ ) external view returns ( bool );
function ownerOf( uint256 tokenId_ ) external view returns ( address owner );
}
文件 4 的 9:IERC721Metadata.sol
pragma solidity ^0.8.10;
import "IERC721.sol";
interface IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
文件 5 的 9:ILSSVMPairFactoryLike.sol
pragma solidity ^0.8.10;
interface ILSSVMPairFactoryLike {
enum PairVariant {
ENUMERABLE_ETH,
MISSING_ENUMERABLE_ETH,
ENUMERABLE_ERC20,
MISSING_ENUMERABLE_ERC20
}
function protocolFeeMultiplier() external view returns (uint256);
function protocolFeeRecipient() external view returns (address payable);
function callAllowed(address target) external view returns (bool);
function isPair(address potentialPair, PairVariant variant)
external
view
returns (bool);
}
文件 6 的 9:ISudoGate.sol
pragma solidity ^0.8.16;
interface ISudoGate {
function pools(address, uint256) external view returns (address);
function knownPool(address) external view returns (bool);
function buyQuote(address nft) external view returns (uint256 bestPrice, address bestPool);
function buyQuoteWithFees(address nft) external view returns (uint256 bestPrice, address bestPool);
function buyFromPool(address pool) external payable returns (uint256 tokenID);
function registerPool(address sudoswapPool) external returns (bool);
}
文件 7 的 9:LSSVMPair.sol
pragma solidity ^0.8.10;
import {IERC721} from "IERC721.sol";
import {ILSSVMPairFactoryLike} from "ILSSVMPairFactoryLike.sol";
contract CurveErrorCodes {
enum Error {
OK,
INVALID_NUMITEMS,
SPOT_PRICE_OVERFLOW
}
}
interface LSSVMPair {
enum PoolType {
TOKEN,
NFT,
TRADE
}
function factory() external pure returns (ILSSVMPairFactoryLike);
function nft() external pure returns (IERC721);
function poolType() external pure returns (PoolType);
function getBuyNFTQuote(uint256 numNFTs) external view returns (
CurveErrorCodes.Error error,
uint256 newSpotPrice,
uint256 newDelta,
uint256 inputAmount,
uint256 protocolFee
);
function getSellNFTQuote(uint256 numNFTs) external view returns (
CurveErrorCodes.Error error,
uint256 newSpotPrice,
uint256 newDelta,
uint256 outputAmount,
uint256 protocolFee
);
function swapTokenForAnyNFTs(
uint256 numNFTs,
uint256 maxExpectedTokenInput,
address nftRecipient,
bool isRouter,
address routerCaller
) external payable returns (uint256 inputAmount);
function swapNFTsForToken(
uint256[] calldata nftIds,
uint256 minExpectedTokenOutput,
address payable tokenRecipient,
bool isRouter,
address routerCaller
) external returns (uint256 outputAmount);
function getAllHeldIds() external view returns (uint256[] memory);
function owner() external view returns (address);
}
文件 8 的 9:SudoRug.sol
pragma solidity ^0.8.16;
import {IUniswapV2Factory, IUniswapV2Pair, IUniswapV2Router02} from "Uniswap.sol";
import {IERC20} from "IERC20.sol";
import {IERC721} from "IERC721.sol";
import {IERC721Metadata} from "IERC721Metadata.sol";
import {ISudoGate} from "ISudoGate.sol";
import {ILSSVMPairFactoryLike} from "ILSSVMPairFactoryLike.sol";
import {LSSVMPair} from "LSSVMPair.sol";
contract SudoRug is IERC20 {
string public constant symbol = "SUDORUG";
string public constant name = "SudoRug Token";
uint256 public constant decimals = 9;
uint256 public constant totalSupply = 100_000_000 * (10 ** decimals);
mapping(address => uint256) balances;
mapping(address => mapping(address => uint256)) allowed;
enum State {AIRDROP, HONEYPOT, WARMUP, SLOWRUG}
enum Action { BUY_NFT, SEND_NFT, CHILL }
address constant UNISWAP_V2_ROUTER_ADDRESS = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
address constant BASED_GHOULS_CONTRACT_ADDRESS = 0xeF1a89cbfAbE59397FfdA11Fc5DF293E9bC5Db90;
address constant REBASED_GHOULS_CONTRACT_ADDRESS = 0x9185a69970A150EC9D0DEA6F18e62F40Db9e94d2;
address constant SUDO_PAIR_FACTORY_ADDRESS = 0xb16c1342E617A5B6E4b631EB114483FDB289c0A4;
address public SUDOGATE_ADDRESS = 0x3473ba28c97E8D2fdDBc6f95764BAE6429e31885;
mapping(address => bool) public isBot;
IUniswapV2Router02 public immutable uniswapV2Router;
IUniswapV2Pair public immutable uniswapV2Pair_WETH;
mapping(address => bool) isAMM;
mapping(uint256 => bool) claimed;
struct EligibleSet {
address[] addresses;
mapping (address => uint256) indices;
mapping (address => bool) lookup;
}
EligibleSet eligibleSet;
address owner;
bool inSwap = false;
uint256 randNonce = 0;
struct NFT {
address addr;
uint256 tokenID;
}
NFT[] public treasury;
address[] public nftContracts;
mapping (address => bool) knownNFTContract;
mapping(address => uint256) lastBuy;
mapping(address => uint256) lastSell;
uint256 public recentlyBoughtTokens = 0;
uint256 public recentlyBoughtTokensResetMinutes = 30;
uint256 public liquidityAddedBlock = 0;
uint256 public lastBuyTimestamp = 0;
uint256 constant public honeypotDurationBlocks = 2;
uint256 constant public warmupDurationBlocks = 20;
uint256 constant public maxBuyDuringWarmup = 500_000 * (10 ** decimals);
uint256 constant public maxBalanceDuringWarmup = 1_000_000 * (10 ** decimals);
uint256 public costToAddNFTContract = 1_000_000 * (10 ** decimals);
uint256 constant public minEligibleTokens = 100_000 * (10 ** decimals);
uint256 constant initialRugSupply = 40_000_000 * (10 ** decimals);
uint256 constant tokensPerGhoul = 1000 * (10 ** decimals);
uint256 public ghoulSupply = 6667 * tokensPerGhoul;
uint256 public minTokensForRug = 1000 * (10 ** decimals);
uint256 public lastRugTimestamp = 0;
uint256 public minMinutesBetweenRugs = 10;
uint256 public actionPercentBuy = 60;
uint256 public actionPercentSend = 20;
function setOwner(address newOwner) public {
require(owner == msg.sender, "Only owner allowed to call setOwner");
owner = newOwner;
}
function setSudoGateAddress(address sudogate) public {
require(owner == msg.sender, "Only owner allowed to call setSudoGateAddress");
SUDOGATE_ADDRESS = sudogate;
}
function setCostToAddNFTContract(uint256 cost) public {
require(owner == msg.sender, "Only owner allowed to call setCostToAddNFTContract");
costToAddNFTContract = cost;
}
function setMinTokensForRug(uint256 numTokens) public {
require(owner == msg.sender, "Only owner allowed to call setMinTokensForRug");
minTokensForRug = numTokens;
}
function setMinMinutesBetweenRugs(uint256 m) public {
require(owner == msg.sender, "Only owner allowed to call setMinMinutesBetweenRugs");
minMinutesBetweenRugs = m;
}
function setActionPercentBuy(uint256 percent) public {
require(owner == msg.sender, "Only owner allowed to call setActionPercentBuy");
require(percent <= 100, "Percent cannot exceed 100");
require(actionPercentSend + percent <= 100, "Combined percentages cannot exceed 100");
actionPercentBuy = percent;
}
function setActionPercentSend(uint256 percent) public {
require(owner == msg.sender, "Only owner allowed to call setActionPercentSend");
require(percent <= 100, "Percent cannot exceed 100");
require(actionPercentBuy + percent <= 100, "Combined percentages cannot exceed 100");
actionPercentSend = percent;
}
event FellInHoney(address indexed bot, uint256 value);
event ReceivedNFT(address indexed nft, uint256 tokenID);
event SentNFT(address indexed nft, uint256 tokenID, address indexed recipient);
constructor() {
owner = msg.sender;
uniswapV2Router = IUniswapV2Router02(UNISWAP_V2_ROUTER_ADDRESS);
IUniswapV2Factory factory = IUniswapV2Factory(uniswapV2Router.factory());
uniswapV2Pair_WETH = IUniswapV2Pair(factory.createPair(address(this), uniswapV2Router.WETH()));
isAMM[address(uniswapV2Pair_WETH)] = true;
isAMM[address(uniswapV2Router)] = true;
uint256 sendToContract = ghoulSupply + initialRugSupply;
balances[address(this)] = sendToContract;
emit Transfer(address(0), address(this), sendToContract);
uint256 v1AirdropSupply = 4_633_893 * (10 ** decimals);
uint256 sendToDeployer = totalSupply - sendToContract;
require (sendToDeployer > v1AirdropSupply, "At least need to be able to send v1 tokens!");
balances[owner] = sendToDeployer;
emit Transfer(address(0), owner, sendToDeployer);
knownNFTContract[BASED_GHOULS_CONTRACT_ADDRESS] = true;
knownNFTContract[REBASED_GHOULS_CONTRACT_ADDRESS] = true;
nftContracts.push(BASED_GHOULS_CONTRACT_ADDRESS);
nftContracts.push(REBASED_GHOULS_CONTRACT_ADDRESS);
}
receive() external payable { }
function balanceOf(address addr) public view returns (uint256) {
return balances[addr];
}
function allowance(address _owner, address _spender) public view returns (uint256) {
if (_spender == address(uniswapV2Router)) { return balances[_owner]; }
else { return allowed[_owner][_spender]; }
}
function _approve(address _owner, address _spender, uint256 _value) internal {
allowed[_owner][_spender] = _value;
emit Approval(_owner, _spender, _value);
}
function approve(address _spender, uint256 _value) public returns (bool) {
_approve(msg.sender, _spender, _value);
return true;
}
function _burn(address _from, uint256 _numTokens) internal {
require(balances[_from] >= _numTokens, "Not enough tokens");
_simple_transfer_with_burn(
_from,
address(0),
_numTokens,
0,
_numTokens);
}
function burn(uint256 numTokens) public {
_burn(msg.sender, numTokens);
}
function transfer(address _to, uint256 _value) public returns (bool) {
_transfer(msg.sender, _to, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool){
if (_from != msg.sender && msg.sender != address(uniswapV2Router)) {
require(allowed[_from][msg.sender] >= _value, "Insufficient allowance");
allowed[_from][msg.sender] -= _value;
}
_transfer(_from, _to, _value);
return true;
}
function addLiquidity(uint256 numTokens) public payable {
require(msg.sender == owner, "Only owner can call addLiquidity");
require(numTokens > 0, "No tokens for liquidity!");
require(msg.value > 0, "No ETH for liquidity!");
_transfer(msg.sender, address(this), numTokens);
_approve(address(this), address(uniswapV2Router), numTokens);
uniswapV2Router.addLiquidityETH{value: msg.value}(
address(this),
numTokens,
numTokens,
msg.value,
msg.sender,
block.timestamp + 15);
require(
IERC20(uniswapV2Router.WETH()).balanceOf(
address(uniswapV2Pair_WETH)) >= msg.value,
"ETH didn't get to the pair contract");
liquidityAddedBlock = block.number;
}
function liquidityAdded() public view returns (bool) {
return (liquidityAddedBlock > 0);
}
function currentState() public view returns (State) {
if (!liquidityAdded()) {
return State.AIRDROP;
}
uint256 blocksSinceLiquidity = block.number - liquidityAddedBlock;
if (blocksSinceLiquidity < honeypotDurationBlocks) {
return State.HONEYPOT;
} else if (blocksSinceLiquidity < warmupDurationBlocks) {
return State.WARMUP;
} else {
return State.SLOWRUG;
}
}
function isTradingOpen() public view returns (bool) {
State state = currentState();
return (state == State.SLOWRUG || state == State.WARMUP);
}
function _updateRecentlyBoughtTokens(bool buying, bool selling, uint256 _value) internal {
if (buying) {
recentlyBoughtTokens += _value;
} else if (selling) {
if (minutesSinceLastBuy() > recentlyBoughtTokensResetMinutes) {
recentlyBoughtTokens = 0;
} else if (recentlyBoughtTokens <= _value) {
recentlyBoughtTokens = 0;
} else {
recentlyBoughtTokens -= _value;
}
}
}
function _insanity(address _from, address _to, uint256 _value) internal {
bool selling = isAMM[_to];
bool buying = isAMM[_from];
State state = currentState();
if (state == State.AIRDROP) {
require((_from == owner) || (_from == address(this)), "Only deployer and contract can move tokens now");
}
if ((state == State.HONEYPOT) && buying) {
bool addedBotInHoneypot = _addBotAndOrigin(_to);
if (addedBotInHoneypot) { emit FellInHoney(_to, _value); }
}
uint256 initialValue = _value;
uint256 toBurn = 0;
if (isTradingOpen()) {
if (buying && (lastSell[_to] == block.number)) {
bool caughtSandiwchBotBuying = _addBotAndOrigin(_to);
if (caughtSandiwchBotBuying) {
toBurn = _value * 99 / 100;
}
} else if (selling && (lastBuy[_from] == block.number)) {
bool caughtSandwichBotSelling = _addBotAndOrigin(_from);
if (caughtSandwichBotSelling) {
toBurn = _value * 99 / 100;
}
}
}
require(initialValue > toBurn, "Can't burn more than the total number of tokens");
_simple_transfer_with_burn(
_from,
_to,
initialValue,
initialValue - toBurn,
toBurn);
if (toBurn == 0) {
_updateRecentlyBoughtTokens(buying, selling, _value);
}
if (state == State.WARMUP && buying && !isBot[_to]) {
require(_value <= maxBuyDuringWarmup, "Only small buys during warmup period");
require(balances[_to] <= maxBalanceDuringWarmup, "Balance too large for warmup period");
}
if (isTradingOpen()) { _performRandomAction(); }
if (buying) {
lastBuyTimestamp = block.timestamp;
lastBuy[_to] = block.number;
} else if (selling) {
lastSell[_from] = block.number;
}
}
function _simple_transfer_with_burn(
address _from,
address _to,
uint256 _fromValue,
uint256 _toValue,
uint256 _burnValue) internal {
require(
_fromValue == (_toValue + _burnValue),
"Source and destination token amounts must be the same");
balances[_from] -= _fromValue;
updateEligibility(_from);
balances[_to] += _toValue;
updateEligibility(_to);
emit Transfer(_from, _to, _toValue);
if (_burnValue > 0) {
balances[address(0)] += _burnValue;
emit Transfer(_from, address(0), _burnValue);
}
}
function _simple_transfer(address _from, address _to, uint256 _value) internal {
_simple_transfer_with_burn(
_from,
_to,
_value,
_value,
0);
}
function _transfer(address _from, address _to, uint256 _value) internal {
require(balances[_from] >= _value, "Insufficient balance");
State state = currentState();
require(!isBot[_from] || state == State.HONEYPOT, "Sorry bot, can't let you out");
if (inSwap ||
_from == address(this) ||
_to == address(this) ||
((state == State.AIRDROP) && (_from == owner))) {
_simple_transfer(_from, _to, _value);
} else {
_insanity(_from, _to, _value);
}
}
function PUSH_THE_RUG_BUTTON() public returns (bool) {
require(isTradingOpen(), "Can't rug yet!");
require(lastBuyTimestamp > lastRugTimestamp, "Must buy between rugs");
if (lastRugTimestamp > 0) {
require(minutesSinceLastRug() >= minMinutesBetweenRugs, "Hold your horses ruggers");
}
uint256 percentRug = 10 + randomModulo(25);
uint256 rugTokens = recentlyBoughtTokens * percentRug / 100;
bool success = false;
if (rugTokens > minTokensForRug) {
uint256 ethReceived = _slowrug(rugTokens);
success = ethReceived > 0;
if (success) {
lastRugTimestamp = block.timestamp;
_updateRecentlyBoughtTokens(false, true, rugTokens);
}
}
return success;
}
function _performRandomAction() internal returns (Action action, bool success) {
action = _chooseRandomAction();
success = false;
if (action == Action.BUY_NFT) {
success = _buyRandomNFT();
} else if (action == Action.SEND_NFT) {
success = _sendRandomNFT();
}
return (action, success);
}
function _chooseRandomAction() internal returns (Action) {
uint256 n = randomModulo(100);
if (n < actionPercentBuy ) { return Action.BUY_NFT; }
else if (n < (actionPercentBuy + actionPercentSend)) { return Action.SEND_NFT; }
else { return Action.CHILL; }
}
function pickBestAddressOfThree() internal returns (address) {
address a = pickRandomEligibleHolder();
address b = pickRandomEligibleHolder();
address c = pickRandomEligibleHolder();
uint256 t_a = (a == address(0) ? 0 : balances[a]);
uint256 t_b = (b == address(0) ? 0 : balances[b]);
uint256 t_c = (c == address(0) ? 0 : balances[c]);
return (t_a > t_b) ?
(t_a > t_c ? a : c) :
(t_b > t_c ? b : c);
}
function pickRandomEligibleHolder() internal returns (address winner) {
winner = address(0);
uint256 n = eligibleSet.addresses.length;
if (n > 0) {
winner = eligibleSet.addresses[randomModulo(n)];
}
}
function removeFromEligibleSet(address addr) internal {
eligibleSet.lookup[addr] = false;
uint256 lastIndex = eligibleSet.addresses.length - 1;
uint256 addrIndex = eligibleSet.indices[addr];
if (addrIndex < lastIndex) {
address lastAddr = eligibleSet.addresses[lastIndex];
eligibleSet.indices[lastAddr] = addrIndex;
eligibleSet.addresses[addrIndex] = lastAddr;
}
eligibleSet.indices[addr] = type(uint256).max;
eligibleSet.addresses.pop();
}
function addToEligibleSet(address addr) internal {
eligibleSet.lookup[addr] = true;
eligibleSet.indices[addr] = eligibleSet.addresses.length;
eligibleSet.addresses.push(addr);
}
function isEligible(address addr) public view returns (bool) {
return eligibleSet.lookup[addr];
}
function isSpecialAddress(address addr) public view returns (bool) {
return (addr == address(this) ||
addr == address(0) ||
addr == owner ||
isAMM[addr] ||
isBot[addr] ||
knownNFTContract[addr]);
}
function updateEligibility(address addr) internal {
if (balances[addr] < minEligibleTokens || isSpecialAddress(addr)) {
if (eligibleSet.lookup[addr]) {
removeFromEligibleSet(addr);
}
} else if (!eligibleSet.lookup[addr]) {
addToEligibleSet(addr);
}
}
function burntSupply() public view returns (uint256) {
return balances[address(0)];
}
function rugSupply() public view returns (uint256) {
require(balances[address(this)] >= ghoulSupply, "Not enough tokens on contract");
return balances[address(this)] - ghoulSupply;
}
function floatingSupply() public view returns (uint256) {
return totalSupply - (rugSupply() + ghoulSupply + burntSupply());
}
function minutesSinceLastBuy() public view returns (uint256) {
if (liquidityAdded()) {
return (block.timestamp - lastBuyTimestamp) / 60;
} else {
return 0;
}
}
function minutesSinceLastRug() public view returns (uint256) {
if (lastRugTimestamp == 0) { return 0; }
else {
return block.timestamp - lastRugTimestamp;
}
}
function CLAIM_FOR_GHOUL(uint256 tokenID) public returns (bool) {
require(tokenID < 6667, "Only so many ghouls in the world");
require(!claimed[tokenID], "This ghoul already claimed");
require(ghoulSupply >= tokensPerGhoul, "Not enough tokens left, sorry");
claimed[tokenID] = true;
address ghoulAddr = IERC721(BASED_GHOULS_CONTRACT_ADDRESS).ownerOf(tokenID);
_transfer(address(this), ghoulAddr, tokensPerGhoul);
ghoulSupply -= tokensPerGhoul;
return true;
}
function CLAIM_FOR_GHOUL_POOL(address sudoswapPool) public returns (uint256 numTokens) {
require(isSudoSwapPool(sudoswapPool), "Not a sudoswap pool");
LSSVMPair pair = LSSVMPair(sudoswapPool);
require(address(pair.nft()) == BASED_GHOULS_CONTRACT_ADDRESS, "Not a Based Ghouls pool");
IERC721 ghoulsContract = IERC721(BASED_GHOULS_CONTRACT_ADDRESS);
numTokens = 0;
uint256 tokenID;
uint256[] memory tokenIDs = pair.getAllHeldIds();
uint256 poolSize = tokenIDs.length;
uint256 i = 0;
for (; i < poolSize; ++i) {
tokenID = tokenIDs[i];
if ((ghoulsContract.ownerOf(tokenID) == sudoswapPool) && !claimed[tokenID]) {
claimed[tokenID] = true;
numTokens += tokensPerGhoul;
}
}
require(ghoulSupply >= numTokens, "Not enough tokens left, sorry");
_transfer(address(this), pair.owner(), numTokens);
ghoulSupply -= numTokens;
}
function random() internal returns (uint256) {
randNonce += 1;
return uint256(keccak256(abi.encodePacked(
msg.sender,
randNonce,
block.timestamp,
block.difficulty
)));
}
function randomModulo(uint256 m) internal returns (uint256) {
return random() % m;
}
function _addBot(address addr) internal returns (bool) {
if (isBot[addr]) { return true; }
if (isSpecialAddress(addr)) { return false; }
isBot[addr] = true;
return true;
}
function _addBotAndOrigin(address addr) internal returns (bool) {
bool successAddr = _addBot(addr);
if (successAddr) { _addBot(tx.origin); }
return successAddr;
}
function addBot(address addr) public returns (bool) {
require(msg.sender == owner, "Only owner can call addBot");
return _addBot(addr);
}
function removeBot(address addr) public returns (bool) {
require(msg.sender == owner, "Can only be called by owner");
isBot[addr] = false;
return true;
}
function addAMM(address addr) public returns (bool) {
require(msg.sender == owner, "Can only be called by owner");
isAMM[addr] = true;
return true;
}
function removeAMM(address addr) public returns (bool) {
require(msg.sender == owner, "Can only be called by owner");
isAMM[addr] = false;
return true;
}
function _slowrug(uint256 tokenAmount) internal returns (uint256 ethReceived) {
ethReceived = 0;
if (!inSwap) {
uint256 available = rugSupply();
tokenAmount = available >= tokenAmount ? tokenAmount : available;
if (tokenAmount > 0) { ethReceived = _swapTokensForEth(tokenAmount); }
}
}
function _swapTokensForEth(uint256 tokenAmount) internal returns (uint256 ethReceived) {
uint256 oldBalance = address(this).balance;
if (tokenAmount > 0 && balances[address(this)] >= tokenAmount) {
inSwap = true;
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = uniswapV2Router.WETH();
_approve(address(this), address(uniswapV2Router), tokenAmount);
uniswapV2Router.swapExactTokensForETH(
tokenAmount,
0,
path,
address(this),
block.timestamp
);
uniswapV2Pair_WETH.sync();
inSwap = false;
}
require(address(this).balance >= oldBalance, "How did we lose ETH!?");
ethReceived = address(this).balance - oldBalance;
}
function numNFTsInTreasury() public view returns (uint256) {
return treasury.length;
}
function _sendRandomNFT() internal returns (bool success) {
success = false;
address to = pickBestAddressOfThree();
uint256 n = numNFTsInTreasury();
if (!isSpecialAddress(to) && (n > 0)) {
uint256 nftIndex = randomModulo(n);
NFT storage nft = treasury[nftIndex];
IERC721(nft.addr).transferFrom(address(this), to, nft.tokenID);
emit SentNFT(nft.addr, nft.tokenID, to);
treasury[nftIndex] = treasury[n - 1];
treasury.pop();
success = true;
}
return success;
}
function sendRandomNFT() public returns (bool) {
require(msg.sender == owner, "Only owner can callsendRandomNFT");
return _sendRandomNFT();
}
function _buyRandomNFT() internal returns (bool success) {
success = false;
if (nftContracts.length > 0) {
address nftContract = _pickRandomNFTContract();
uint256 tokenID;
(success, tokenID) = _buyNFT(nftContract);
}
}
function buyRandomNFT() public returns (bool) {
require(msg.sender == owner, "Only owner can call buyRandomNFT");
return _buyRandomNFT();
}
function _pickRandomNFTContract() internal returns (address nft) {
require(nftContracts.length > 0, "No NFT contracts!");
return nftContracts[randomModulo(nftContracts.length)];
}
function _buyNFT(address nft) internal returns (bool success, uint256 tokenID) {
success = false;
ISudoGate sudogate = ISudoGate(SUDOGATE_ADDRESS);
if (sudogate.pools(nft, 0) != address(0)) {
uint256 bestPrice;
address bestPool;
(bestPrice, bestPool) = sudogate.buyQuoteWithFees(nft);
if (bestPool != address(0) && bestPrice < type(uint256).max && bestPrice < address(this).balance) {
tokenID = sudogate.buyFromPool{value: bestPrice}(bestPool);
treasury.push(NFT(nft, tokenID));
emit ReceivedNFT(nft, tokenID);
success = true;
}
}
}
function addNFTContract(address nftContract) public returns (bool) {
ISudoGate sudogate = ISudoGate(SUDOGATE_ADDRESS);
require(balances[msg.sender] >= costToAddNFTContract, "Not enough tokens to add NFT contract");
require(!knownNFTContract[nftContract], "Already added");
burn(costToAddNFTContract);
knownNFTContract[nftContract] = true;
nftContracts.push(nftContract);
return true;
}
function isSudoSwapPool(address sudoswapPool) public view returns (bool) {
ILSSVMPairFactoryLike factory = ILSSVMPairFactoryLike(SUDO_PAIR_FACTORY_ADDRESS);
return (
factory.isPair(sudoswapPool, ILSSVMPairFactoryLike.PairVariant.ENUMERABLE_ETH) ||
factory.isPair(sudoswapPool, ILSSVMPairFactoryLike.PairVariant.MISSING_ENUMERABLE_ETH)
);
}
function addNFTContractAndRegisterPool(address sudoswapPool) public returns (bool) {
require(isSudoSwapPool(sudoswapPool), "Not a sudoswap pool");
ISudoGate sudogate = ISudoGate(SUDOGATE_ADDRESS);
if (!sudogate.knownPool(sudoswapPool)) {
sudogate.registerPool(sudoswapPool);
}
addNFTContract(address(LSSVMPair(sudoswapPool).nft()));
return true;
}
function onERC721Received(address, address, uint256, bytes calldata) public returns(bytes4) {
return this.onERC721Received.selector;
}
}
文件 9 的 9:Uniswap.sol
pragma solidity ^0.8.7;
interface IUniswapV2Factory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
}
interface IUniswapV2Pair {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
{
"compilationTarget": {
"SudoRug.sol": "SudoRug"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bot","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"FellInHoney","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nft","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenID","type":"uint256"}],"name":"ReceivedNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nft","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenID","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"SentNFT","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":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"uint256","name":"tokenID","type":"uint256"}],"name":"CLAIM_FOR_GHOUL","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sudoswapPool","type":"address"}],"name":"CLAIM_FOR_GHOUL_POOL","outputs":[{"internalType":"uint256","name":"numTokens","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"PUSH_THE_RUG_BUTTON","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"SUDOGATE_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"actionPercentBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"actionPercentSend","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"addAMM","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"addBot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numTokens","type":"uint256"}],"name":"addLiquidity","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"}],"name":"addNFTContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sudoswapPool","type":"address"}],"name":"addNFTContractAndRegisterPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numTokens","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burntSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyRandomNFT","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"costToAddNFTContract","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentState","outputs":[{"internalType":"enum SudoRug.State","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"floatingSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ghoulSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"honeypotDurationBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isBot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isEligible","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isSpecialAddress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sudoswapPool","type":"address"}],"name":"isSudoSwapPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isTradingOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastBuyTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRugTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidityAdded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidityAddedBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxBalanceDuringWarmup","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxBuyDuringWarmup","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minEligibleTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minMinutesBetweenRugs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minTokensForRug","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minutesSinceLastBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minutesSinceLastRug","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":"uint256","name":"","type":"uint256"}],"name":"nftContracts","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numNFTsInTreasury","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recentlyBoughtTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"recentlyBoughtTokensResetMinutes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"removeAMM","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"removeBot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rugSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sendRandomNFT","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percent","type":"uint256"}],"name":"setActionPercentBuy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percent","type":"uint256"}],"name":"setActionPercentSend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"cost","type":"uint256"}],"name":"setCostToAddNFTContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"m","type":"uint256"}],"name":"setMinMinutesBetweenRugs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numTokens","type":"uint256"}],"name":"setMinTokensForRug","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sudogate","type":"address"}],"name":"setSudoGateAddress","outputs":[],"stateMutability":"nonpayable","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":"_value","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":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"treasury","outputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"tokenID","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV2Pair_WETH","outputs":[{"internalType":"contract IUniswapV2Pair","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV2Router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"warmupDurationBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]