文件 1 的 37:BokkyPooBahsDateTimeLibrary.sol
pragma solidity ^0.7.6;
library BokkyPooBahsDateTimeLibrary {
uint constant SECONDS_PER_DAY = 24 * 60 * 60;
uint constant SECONDS_PER_HOUR = 60 * 60;
uint constant SECONDS_PER_MINUTE = 60;
int constant OFFSET19700101 = 2440588;
uint constant DOW_MON = 1;
uint constant DOW_TUE = 2;
uint constant DOW_WED = 3;
uint constant DOW_THU = 4;
uint constant DOW_FRI = 5;
uint constant DOW_SAT = 6;
uint constant DOW_SUN = 7;
function _daysFromDate(
uint year,
uint month,
uint day
) internal pure returns (uint _days) {
require(year >= 1970);
int _year = int(year);
int _month = int(month);
int _day = int(day);
int __days = _day -
32075 +
(1461 * (_year + 4800 + (_month - 14) / 12)) /
4 +
(367 * (_month - 2 - ((_month - 14) / 12) * 12)) /
12 -
(3 * ((_year + 4900 + (_month - 14) / 12) / 100)) /
4 -
OFFSET19700101;
_days = uint(__days);
}
function _daysToDate(
uint _days
) internal pure returns (uint year, uint month, uint day) {
int __days = int(_days);
int L = __days + 68569 + OFFSET19700101;
int N = (4 * L) / 146097;
L = L - (146097 * N + 3) / 4;
int _year = (4000 * (L + 1)) / 1461001;
L = L - (1461 * _year) / 4 + 31;
int _month = (80 * L) / 2447;
int _day = L - (2447 * _month) / 80;
L = _month / 11;
_month = _month + 2 - 12 * L;
_year = 100 * (N - 49) + _year + L;
year = uint(_year);
month = uint(_month);
day = uint(_day);
}
function timestampFromDate(
uint year,
uint month,
uint day
) internal pure returns (uint timestamp) {
timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY;
}
function timestampFromDateTime(
uint year,
uint month,
uint day,
uint hour,
uint minute,
uint second
) internal pure returns (uint timestamp) {
timestamp =
_daysFromDate(year, month, day) *
SECONDS_PER_DAY +
hour *
SECONDS_PER_HOUR +
minute *
SECONDS_PER_MINUTE +
second;
}
function timestampToDate(
uint timestamp
) internal pure returns (uint year, uint month, uint day) {
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
}
function timestampToDateTime(
uint timestamp
)
internal
pure
returns (
uint year,
uint month,
uint day,
uint hour,
uint minute,
uint second
)
{
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
uint secs = timestamp % SECONDS_PER_DAY;
hour = secs / SECONDS_PER_HOUR;
secs = secs % SECONDS_PER_HOUR;
minute = secs / SECONDS_PER_MINUTE;
second = secs % SECONDS_PER_MINUTE;
}
function isValidDate(
uint year,
uint month,
uint day
) internal pure returns (bool valid) {
if (year >= 1970 && month > 0 && month <= 12) {
uint daysInMonth = _getDaysInMonth(year, month);
if (day > 0 && day <= daysInMonth) {
valid = true;
}
}
}
function isValidDateTime(
uint year,
uint month,
uint day,
uint hour,
uint minute,
uint second
) internal pure returns (bool valid) {
if (isValidDate(year, month, day)) {
if (hour < 24 && minute < 60 && second < 60) {
valid = true;
}
}
}
function isLeapYear(uint timestamp) internal pure returns (bool leapYear) {
uint year;
uint month;
uint day;
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
leapYear = _isLeapYear(year);
}
function _isLeapYear(uint year) internal pure returns (bool leapYear) {
leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}
function isWeekDay(uint timestamp) internal pure returns (bool weekDay) {
weekDay = getDayOfWeek(timestamp) <= DOW_FRI;
}
function isWeekEnd(uint timestamp) internal pure returns (bool weekEnd) {
weekEnd = getDayOfWeek(timestamp) >= DOW_SAT;
}
function getDaysInMonth(
uint timestamp
) internal pure returns (uint daysInMonth) {
uint year;
uint month;
uint day;
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
daysInMonth = _getDaysInMonth(year, month);
}
function _getDaysInMonth(
uint year,
uint month
) internal pure returns (uint daysInMonth) {
if (
month == 1 ||
month == 3 ||
month == 5 ||
month == 7 ||
month == 8 ||
month == 10 ||
month == 12
) {
daysInMonth = 31;
} else if (month != 2) {
daysInMonth = 30;
} else {
daysInMonth = _isLeapYear(year) ? 29 : 28;
}
}
function getDayOfWeek(uint timestamp) internal pure returns (uint dayOfWeek) {
uint _days = timestamp / SECONDS_PER_DAY;
dayOfWeek = ((_days + 3) % 7) + 1;
}
function getYear(uint timestamp) internal pure returns (uint year) {
uint month;
uint day;
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
}
function getMonth(uint timestamp) internal pure returns (uint month) {
uint year;
uint day;
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
}
function getDay(uint timestamp) internal pure returns (uint day) {
uint year;
uint month;
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
}
function getHour(uint timestamp) internal pure returns (uint hour) {
uint secs = timestamp % SECONDS_PER_DAY;
hour = secs / SECONDS_PER_HOUR;
}
function getMinute(uint timestamp) internal pure returns (uint minute) {
uint secs = timestamp % SECONDS_PER_HOUR;
minute = secs / SECONDS_PER_MINUTE;
}
function getSecond(uint timestamp) internal pure returns (uint second) {
second = timestamp % SECONDS_PER_MINUTE;
}
function addYears(
uint timestamp,
uint _years
) internal pure returns (uint newTimestamp) {
uint year;
uint month;
uint day;
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
year += _years;
uint daysInMonth = _getDaysInMonth(year, month);
if (day > daysInMonth) {
day = daysInMonth;
}
newTimestamp =
_daysFromDate(year, month, day) *
SECONDS_PER_DAY +
(timestamp % SECONDS_PER_DAY);
require(newTimestamp >= timestamp);
}
function addMonths(
uint timestamp,
uint _months
) internal pure returns (uint newTimestamp) {
uint year;
uint month;
uint day;
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
month += _months;
year += (month - 1) / 12;
month = ((month - 1) % 12) + 1;
uint daysInMonth = _getDaysInMonth(year, month);
if (day > daysInMonth) {
day = daysInMonth;
}
newTimestamp =
_daysFromDate(year, month, day) *
SECONDS_PER_DAY +
(timestamp % SECONDS_PER_DAY);
require(newTimestamp >= timestamp);
}
function addDays(
uint timestamp,
uint _days
) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp + _days * SECONDS_PER_DAY;
require(newTimestamp >= timestamp);
}
function addHours(
uint timestamp,
uint _hours
) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp + _hours * SECONDS_PER_HOUR;
require(newTimestamp >= timestamp);
}
function addMinutes(
uint timestamp,
uint _minutes
) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE;
require(newTimestamp >= timestamp);
}
function addSeconds(
uint timestamp,
uint _seconds
) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp + _seconds;
require(newTimestamp >= timestamp);
}
function subYears(
uint timestamp,
uint _years
) internal pure returns (uint newTimestamp) {
uint year;
uint month;
uint day;
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
year -= _years;
uint daysInMonth = _getDaysInMonth(year, month);
if (day > daysInMonth) {
day = daysInMonth;
}
newTimestamp =
_daysFromDate(year, month, day) *
SECONDS_PER_DAY +
(timestamp % SECONDS_PER_DAY);
require(newTimestamp <= timestamp);
}
function subMonths(
uint timestamp,
uint _months
) internal pure returns (uint newTimestamp) {
uint year;
uint month;
uint day;
(year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
uint yearMonth = year * 12 + (month - 1) - _months;
year = yearMonth / 12;
month = (yearMonth % 12) + 1;
uint daysInMonth = _getDaysInMonth(year, month);
if (day > daysInMonth) {
day = daysInMonth;
}
newTimestamp =
_daysFromDate(year, month, day) *
SECONDS_PER_DAY +
(timestamp % SECONDS_PER_DAY);
require(newTimestamp <= timestamp);
}
function subDays(
uint timestamp,
uint _days
) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp - _days * SECONDS_PER_DAY;
require(newTimestamp <= timestamp);
}
function subHours(
uint timestamp,
uint _hours
) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp - _hours * SECONDS_PER_HOUR;
require(newTimestamp <= timestamp);
}
function subMinutes(
uint timestamp,
uint _minutes
) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE;
require(newTimestamp <= timestamp);
}
function subSeconds(
uint timestamp,
uint _seconds
) internal pure returns (uint newTimestamp) {
newTimestamp = timestamp - _seconds;
require(newTimestamp <= timestamp);
}
function diffYears(
uint fromTimestamp,
uint toTimestamp
) internal pure returns (uint _years) {
require(fromTimestamp <= toTimestamp);
uint fromYear;
uint fromMonth;
uint fromDay;
uint toYear;
uint toMonth;
uint toDay;
(fromYear, fromMonth, fromDay) = _daysToDate(
fromTimestamp / SECONDS_PER_DAY
);
(toYear, toMonth, toDay) = _daysToDate(toTimestamp / SECONDS_PER_DAY);
_years = toYear - fromYear;
}
function diffMonths(
uint fromTimestamp,
uint toTimestamp
) internal pure returns (uint _months) {
require(fromTimestamp <= toTimestamp);
uint fromYear;
uint fromMonth;
uint fromDay;
uint toYear;
uint toMonth;
uint toDay;
(fromYear, fromMonth, fromDay) = _daysToDate(
fromTimestamp / SECONDS_PER_DAY
);
(toYear, toMonth, toDay) = _daysToDate(toTimestamp / SECONDS_PER_DAY);
_months = toYear * 12 + toMonth - fromYear * 12 - fromMonth;
}
function diffDays(
uint fromTimestamp,
uint toTimestamp
) internal pure returns (uint _days) {
require(fromTimestamp <= toTimestamp);
_days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY;
}
function diffHours(
uint fromTimestamp,
uint toTimestamp
) internal pure returns (uint _hours) {
require(fromTimestamp <= toTimestamp);
_hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR;
}
function diffMinutes(
uint fromTimestamp,
uint toTimestamp
) internal pure returns (uint _minutes) {
require(fromTimestamp <= toTimestamp);
_minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE;
}
function diffSeconds(
uint fromTimestamp,
uint toTimestamp
) internal pure returns (uint _seconds) {
require(fromTimestamp <= toTimestamp);
_seconds = toTimestamp - fromTimestamp;
}
}
文件 2 的 37:Context.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 3 的 37:ERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "../../utils/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.sol";
contract ERC20 is Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
constructor (string memory name_, string memory symbol_) public {
_name = name_;
_symbol = symbol_;
_decimals = 18;
}
function name() public view virtual returns (string memory) {
return _name;
}
function symbol() public view virtual returns (string memory) {
return _symbol;
}
function decimals() public view virtual returns (uint8) {
return _decimals;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _setupDecimals(uint8 decimals_) internal virtual {
_decimals = decimals_;
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}
文件 4 的 37:FixedPoint96.sol
pragma solidity >=0.4.0;
library FixedPoint96 {
uint8 internal constant RESOLUTION = 96;
uint256 internal constant Q96 = 0x1000000000000000000000000;
}
文件 5 的 37:GudGuess.sol
pragma solidity ^0.7.6;
import '@uniswap/v3-core/contracts/libraries/FixedPoint96.sol';
import './HolderRewards.sol';
import './UniswapV3FeeERC20.sol';
import './interfaces/IGudGuessTickets.sol';
import './interfaces/ITwapUtils.sol';
import './interfaces/IWinnersCircle.sol';
import './libraries/BokkyPooBahsDateTimeLibrary.sol';
contract GudGuess is UniswapV3FeeERC20 {
uint32 constant DENOMENATOR = 10000;
ITwapUtils public twapUtils;
HolderRewards public rewards;
IGudGuessTickets public tickets;
IWinnersCircle public winnersCircle;
address public priceToken;
IUniswapV3Pool public pricePool;
IUniswapV3Pool public nativeStablePool;
bool _isPoolPairedWETH9;
address public adminWallet;
uint32 public burnPerc = (DENOMENATOR * 25) / 100;
uint32 public winningsPerc = (DENOMENATOR * 40) / 100;
uint32 public rewardsPerc = (DENOMENATOR * 1) / 100;
uint32 public adminPerc = (DENOMENATOR * 5) / 100;
uint256 public pricePerTicketMinUSDX96 = 2 * FixedPoint96.Q96;
uint256 public pricePerTicketMaxUSDX96 = 5 * FixedPoint96.Q96;
uint32 public minGuessJackpotWeight = 6 * DENOMENATOR;
uint32 public maxGuessJackpotWeight = 9 * DENOMENATOR;
uint256 public launchTime;
uint256 public swapAtAmountSupplyPerc = (DENOMENATOR * 2) / 1000;
bool public swapEnabled = true;
bool public taxEnabled = true;
uint8 public precisionDecimals = 16;
uint256 public guessCutoffBeforeClose = 3 days;
mapping(uint256 => uint256) public weeklyClosePrice;
mapping(uint256 => uint256) public totalWeeklyGuesses;
mapping(uint256 => mapping(uint256 => uint256)) public weeklyGuesses;
mapping(uint256 => mapping(uint256 => uint256)) public weeklyWeights;
mapping(address => bool) public amms;
mapping(address => bool) public isBot;
mapping(address => bool) public rewardsExcluded;
bool _swapping;
modifier lockSwap() {
_swapping = true;
_;
_swapping = false;
}
event Burn(address indexed wallet, uint256 amount);
event BuyTicket(
address indexed wallet,
uint256 indexed weeklyClose,
uint256 priceX96
);
event SubmitWeeklyClose(
uint256 indexed weeklyClose,
uint256 closePriceX96,
uint256 totalGuesses,
uint256 totalWinners,
uint256 totalWeight
);
constructor(
INonfungiblePositionManager _manager,
ISwapRouter _swapRouter,
address _priceToken,
IUniswapV3Pool _pricePool,
IUniswapV3Pool _nativeStablePool,
bool __isPoolPairedWETH9,
address _factory,
address _WETH9
)
UniswapV3FeeERC20(
'Gud Guess',
'GG',
_manager,
_swapRouter,
_factory,
_WETH9
)
{
rewards = new HolderRewards(address(this));
adminWallet = msg.sender;
rewardsExcluded[address(this)] = true;
priceToken = _priceToken;
pricePool = _pricePool;
nativeStablePool = _nativeStablePool;
_isPoolPairedWETH9 = __isPoolPairedWETH9;
uint256 _supply = 100_000_000 * 10 ** decimals();
_mint(address(this), _supply);
}
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual override {
bool _isBuy = amms[sender] && recipient != address(swapRouter);
bool _isSell = amms[recipient];
if (_isBuy || _isSell) {
require(launchTime > 0, 'TRANSFER: not launched');
}
uint256 _tax;
if (launchTime > 0) {
if (_isBuy) {
if (block.timestamp <= launchTime + 10 seconds) {
isBot[recipient] = true;
} else if (block.timestamp <= launchTime + 30 minutes) {
uint256 _launchMax = balanceOf(recipient) + amount;
require(_launchMax <= totalSupply() / 100, 'max 1% at launch');
}
if (taxEnabled) {
_tax = block.timestamp < launchTime + 30 days
? (amount * 5) / 100
: (amount * 1) / 100;
super._transfer(sender, address(this), _tax);
_afterTokenTransfer(sender, address(this), _tax);
}
} else {
require(!isBot[recipient], 'TRANSFER: bot0');
require(!isBot[sender], 'TRANSFER: bot1');
require(!isBot[_msgSender()], 'TRANSFER: bot2');
}
if (
!_swapping &&
swapEnabled &&
liquidityPosInitialized &&
balanceOf(address(this)) >= _getSwapAtAmount()
) {
_swapForETHAndProcess();
}
_checkAndSubmitPreviousWeeklyClose();
}
super._transfer(sender, recipient, amount - _tax);
_afterTokenTransfer(sender, recipient, amount - _tax);
}
function _mint(address account, uint256 amount) internal override {
super._mint(account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal override {
super._burn(account, amount);
_afterTokenTransfer(account, address(0), amount);
}
function _swapForETHAndProcess() internal lockSwap {
uint256 _swapAmount = _getSwapAtAmount();
uint256 _burnTokens = (_swapAmount * burnPerc) / DENOMENATOR;
_burn(address(this), _burnTokens);
_swapTokensForETH(_swapAmount - _burnTokens);
}
function _buyTicket(address _user, uint256 _priceUSDX96) internal {
uint256 _nextWeeklyClose = getWeeklyCloseFromTimestamp(block.timestamp);
uint256 _weeklyCloseForGuess = block.timestamp <
_nextWeeklyClose - guessCutoffBeforeClose
? _nextWeeklyClose
: getWeeklyCloseFromTimestamp(block.timestamp + 7 days);
uint256 _rawPriceAtPrecision = (_priceUSDX96 * 10 ** 18) /
FixedPoint96.Q96 /
10 ** precisionDecimals;
uint256 _finalPriceUSDX96 = (_rawPriceAtPrecision *
FixedPoint96.Q96 *
10 ** precisionDecimals) / 10 ** 18;
uint32 _weight = _getCurrentWinningsWeight();
tickets.mint(
_user,
_weeklyCloseForGuess,
priceToken,
address(pricePool),
address(nativeStablePool),
_finalPriceUSDX96,
_weight
);
totalWeeklyGuesses[_weeklyCloseForGuess]++;
weeklyGuesses[_weeklyCloseForGuess][_finalPriceUSDX96]++;
weeklyWeights[_weeklyCloseForGuess][_finalPriceUSDX96] += _weight;
emit BuyTicket(_user, _weeklyCloseForGuess, _finalPriceUSDX96);
}
function _checkAndSubmitPreviousWeeklyClose() internal {
uint256 _prevWeeklyClose = getWeeklyCloseFromTimestamp(
block.timestamp - 7 days
);
if (
totalWeeklyGuesses[_prevWeeklyClose] == 0 ||
weeklyClosePrice[_prevWeeklyClose] > 0
) {
return;
}
uint256 _jackpotETH = getTotalJackpotBalance();
uint256 _fullClosePriceX96 = getPriceTokenPriceUSDX96();
uint256 _rawClosePriceAtPrecision = (_fullClosePriceX96 * 10 ** 18) /
FixedPoint96.Q96 /
10 ** precisionDecimals;
uint256 _finalClosePriceX96 = (_rawClosePriceAtPrecision *
FixedPoint96.Q96 *
10 ** precisionDecimals) / 10 ** 18;
weeklyClosePrice[_prevWeeklyClose] = _finalClosePriceX96;
uint256 _totWeights = weeklyWeights[_prevWeeklyClose][_finalClosePriceX96];
uint256 _rewardsETH = (_jackpotETH * rewardsPerc) / DENOMENATOR;
if (_rewardsETH > 0 && rewards.totalSharesDeposited() > 0) {
rewards.depositRewards{ value: _rewardsETH }();
}
uint256 _winningsETH;
if (weeklyGuesses[_prevWeeklyClose][_finalClosePriceX96] > 0) {
uint256 _totalWeeklyETH = (_jackpotETH * winningsPerc) / DENOMENATOR;
uint256 _adminETH = (_totalWeeklyETH * adminPerc) / DENOMENATOR;
if (_adminETH > 0) {
uint256 _before = address(this).balance;
(bool _success, ) = payable(adminWallet).call{ value: _adminETH }('');
require(_success, 'SUBMIT0');
require(address(this).balance >= _before - _adminETH, 'SUBMIT1');
}
uint256 _remainingWinningsETH = _totalWeeklyETH - _adminETH;
_winningsETH = _totWeights < maxGuessJackpotWeight
? (_remainingWinningsETH * _totWeights) / maxGuessJackpotWeight
: _remainingWinningsETH;
}
winnersCircle.closeWeeklyAndAddWinnings{ value: _winningsETH }(
_prevWeeklyClose,
_finalClosePriceX96,
_totWeights
);
emit SubmitWeeklyClose(
_prevWeeklyClose,
_finalClosePriceX96,
totalWeeklyGuesses[_prevWeeklyClose],
weeklyGuesses[_prevWeeklyClose][_finalClosePriceX96],
_totWeights
);
}
function getStartEndOfWeeklyGuessPeriod(
uint256 _timestamp
) public view returns (uint256 start, uint256 end, uint256 span) {
uint256 _followingWeeklyClose = getWeeklyCloseFromTimestamp(_timestamp);
uint256 _weeklyCloseForGuess = _timestamp <
_followingWeeklyClose - guessCutoffBeforeClose
? _followingWeeklyClose
: getWeeklyCloseFromTimestamp(_timestamp + 7 days);
start = _weeklyCloseForGuess - 7 days - guessCutoffBeforeClose;
end = _weeklyCloseForGuess - guessCutoffBeforeClose;
span = end - start;
}
function _getCurrentWinningsWeight() internal view returns (uint32) {
uint32 _min = minGuessJackpotWeight;
uint32 _max = maxGuessJackpotWeight;
(uint256 _start, , uint256 _span) = getStartEndOfWeeklyGuessPeriod(
block.timestamp
);
return
uint32(_max - (((block.timestamp - _start) * (_max - _min)) / _span));
}
function _getSwapAtAmount() internal view returns (uint256) {
return (totalSupply() * swapAtAmountSupplyPerc) / DENOMENATOR;
}
function _canReceiveRewards(address _wallet) internal view returns (bool) {
return _wallet != address(0) && !rewardsExcluded[_wallet] && !amms[_wallet];
}
function burn(uint256 _amount) external {
_burn(msg.sender, _amount);
emit Burn(msg.sender, _amount);
}
function lpCreatePool(
uint24 _fee,
uint256 _initialPriceX96,
uint16 _initPriceObservations
) external onlyOwner {
_createLiquidityPool(
_fee,
twapUtils.getSqrtPriceX96FromPriceX96(_initialPriceX96),
_initPriceObservations
);
}
function lpCreatePosition(
uint24 _fee,
uint8 _percentTokenAllo
) external payable onlyOwner {
require(msg.value > 0, 'ADDLP0');
require(_percentTokenAllo <= 100, 'ADDLP1');
address _pool = _createLiquidityPosition(
_fee,
(balanceOf(address(this)) * _percentTokenAllo) / 100,
msg.value
);
_setIsRewardsExcluded(_pool, true);
amms[_pool] = true;
}
function launch() external onlyOwner {
require(launchTime == 0, 'LAUNCH0');
require(liquidityPosInitialized, 'LAUNCH1');
launchTime = block.timestamp;
}
function submitClose() external {
_checkAndSubmitPreviousWeeklyClose();
}
function buyTicket(uint256 _priceUSDX96) external {
IERC20(address(this)).transferFrom(
msg.sender,
address(this),
getCurrentPriceTokensPerTicket()
);
_buyTicket(msg.sender, _priceUSDX96);
}
function buyMultipleTickets(uint256[] memory _priceUSDX96) external {
IERC20(address(this)).transferFrom(
msg.sender,
address(this),
_priceUSDX96.length * getCurrentPriceTokensPerTicket()
);
for (uint256 _i = 0; _i < _priceUSDX96.length; _i++) {
_buyTicket(msg.sender, _priceUSDX96[_i]);
}
}
function getTotalJackpotBalance() public view returns (uint256) {
return address(this).balance;
}
function getCurrentPriceTokensPerTicket() public view returns (uint256) {
uint256 _min = pricePerTicketMinUSDX96;
uint256 _max = pricePerTicketMaxUSDX96;
(uint256 _start, , uint256 _span) = getStartEndOfWeeklyGuessPeriod(
block.timestamp
);
uint256 _perTicketUSDX96 = _min +
(((block.timestamp - _start) * (_max - _min)) / _span);
return (_perTicketUSDX96 * 10 ** decimals()) / getCurrentPriceUSDX96();
}
function getCurrentPriceUSDX96() public view returns (uint256) {
require(liquidityPosInitialized, 'INIT');
(, , address _pool) = _getPoolInfo(_lpPoolFees[0]);
return
twapUtils.getPoolPriceUSDX96(
address(this),
_pool,
address(nativeStablePool),
WETH9,
true
);
}
function getPriceTokenPriceUSDX96() public view returns (uint256) {
return
twapUtils.getPoolPriceUSDX96(
priceToken,
address(pricePool),
address(nativeStablePool),
WETH9,
_isPoolPairedWETH9
);
}
function getWeeklyCloseFromTimestamp(
uint256 _timestamp
) public pure returns (uint256) {
uint256 _diffFromMidnight = _timestamp % 1 days;
uint256 _thisComingMidnight = _timestamp + 1 days - _diffFromMidnight;
uint256 _todayDOW = BokkyPooBahsDateTimeLibrary.getDayOfWeek(_timestamp);
uint256 _daysUntilEOW = 7 - _todayDOW;
return _thisComingMidnight + (_daysUntilEOW * 1 days) - 1;
}
function manualSwap() external onlyOwner {
require(balanceOf(address(this)) >= _getSwapAtAmount(), 'SWAP0');
_swapForETHAndProcess();
}
function setPriceTokenAndPool(
address _token,
IUniswapV3Pool _pool,
bool _pairedWithWETH9
) external onlyOwner {
address _token0 = _pool.token0();
address _token1 = _pool.token1();
require(_token0 == _token || _token1 == _token, 'BADTOKEN');
priceToken = _token;
pricePool = _pool;
_isPoolPairedWETH9 = _pairedWithWETH9;
}
function toggleAmm(address _amm) external onlyOwner {
amms[_amm] = !amms[_amm];
}
function forgiveBot(address _bot) external onlyOwner {
require(isBot[_bot], 'FORGIVE0');
isBot[_bot] = false;
}
function setTwapUtils(ITwapUtils _twapUtils) external onlyOwner {
require(address(twapUtils) == address(0), 'SETTW');
twapUtils = _twapUtils;
}
function setTickets(IGudGuessTickets _tickets) external onlyOwner {
require(address(tickets) == address(0), 'SETT');
tickets = _tickets;
}
function setWinnersCircle(IWinnersCircle _winnersCircle) external onlyOwner {
require(address(winnersCircle) == address(0), 'SETWC');
winnersCircle = _winnersCircle;
}
function setAdminWallet(address _adminWallet) external onlyOwner {
adminWallet = _adminWallet;
}
function setBurnPerc(uint32 _perc) external onlyOwner {
require(_perc <= DENOMENATOR, 'lte 100%');
burnPerc = _perc;
}
function setRewardsPerc(uint32 _perc) external onlyOwner {
require(_perc <= (DENOMENATOR * 10) / 100, 'lte 10%');
rewardsPerc = _perc;
}
function setWinningsPerc(uint32 _perc) external onlyOwner {
require(_perc <= (DENOMENATOR * 80) / 100, 'lte 80%');
winningsPerc = _perc;
}
function setAdminPerc(uint32 _perc) external onlyOwner {
require(_perc <= (DENOMENATOR * 5) / 100, 'lte 5%');
adminPerc = _perc;
}
function setGuessJackpotWeights(uint32 _min, uint32 _max) external onlyOwner {
require(_max > 0, 'WEIGHTS0');
require(_min <= _max, 'WEIGHTS1');
minGuessJackpotWeight = _min;
maxGuessJackpotWeight = _max;
}
function setPricePerTicketUSDX96(
uint256 _minUSD18,
uint256 _maxUSD18
) external onlyOwner {
require(_minUSD18 <= _maxUSD18, 'PPT');
pricePerTicketMinUSDX96 = (_minUSD18 * FixedPoint96.Q96) / 10 ** 18;
pricePerTicketMaxUSDX96 = (_maxUSD18 * FixedPoint96.Q96) / 10 ** 18;
}
function setSwapAtAmountSupplyPerc(uint256 _supplyPerc) external onlyOwner {
require(_supplyPerc > 0, 'SETSWAPAM0');
require(_supplyPerc <= (DENOMENATOR * 2) / 100, 'SETSWAPAM1');
swapAtAmountSupplyPerc = _supplyPerc;
}
function setSwapEnabled(bool _enabled) external onlyOwner {
require(swapEnabled != _enabled, 'SWAPEN');
swapEnabled = _enabled;
}
function setTaxEnabled(bool _enabled) external onlyOwner {
require(taxEnabled != _enabled, 'TAXEN');
taxEnabled = _enabled;
}
function setIsRewardsExcluded(
address _wallet,
bool _isExcluded
) external onlyOwner {
_setIsRewardsExcluded(_wallet, _isExcluded);
}
function _setIsRewardsExcluded(address _wallet, bool _isExcluded) internal {
require(rewardsExcluded[_wallet] != _isExcluded, 'SETEXCL');
rewardsExcluded[_wallet] = _isExcluded;
uint256 _walletBal = balanceOf(_wallet);
if (_walletBal > 0) {
bool _removeRewards = false;
if (_isExcluded) {
_removeRewards = true;
}
rewards.setShare(_wallet, _walletBal, _removeRewards);
}
}
function setPrecisionDecimals(uint8 _decimals) external onlyOwner {
precisionDecimals = _decimals;
}
function setGuessCutoffBeforeClose(uint256 _seconds) external onlyOwner {
guessCutoffBeforeClose = _seconds;
}
function _afterTokenTransfer(
address _from,
address _to,
uint256 _amount
) internal virtual {
if (_canReceiveRewards(_from)) {
rewards.setShare(_from, _amount, true);
}
if (_canReceiveRewards(_to)) {
rewards.setShare(_to, _amount, false);
}
}
}
文件 6 的 37:HolderRewards.sol
pragma solidity ^0.7.6;
contract HolderRewards {
uint256 constant MULTIPLIER = 10 ** 36;
address public token;
uint256 public totalStakedUsers;
uint256 public totalSharesDeposited;
struct Share {
uint256 amount;
uint256 stakedTime;
}
struct Reward {
uint256 totalExcluded;
uint256 totalRealized;
}
mapping(address => Share) shares;
mapping(address => Reward) public rewards;
uint256 public totalRewards;
uint256 public totalDistributed;
uint256 public rewardsPerShare;
event AddShares(address indexed user, uint256 amount);
event RemoveShares(address indexed user, uint256 amount);
event ClaimReward(address user);
event DistributeReward(address indexed user, uint256 amount);
event DepositRewards(address indexed user, uint256 amountTokens);
modifier onlyToken() {
require(msg.sender == token, 'ONLYTOKEN');
_;
}
constructor(address _token) {
token = _token;
}
function setShare(
address shareholder,
uint256 balanceUpdate,
bool isRemoving
) external onlyToken {
if (isRemoving) {
_removeShares(shareholder, balanceUpdate);
emit RemoveShares(shareholder, balanceUpdate);
} else {
_addShares(shareholder, balanceUpdate);
emit AddShares(shareholder, balanceUpdate);
}
}
function _addShares(address shareholder, uint256 amount) internal {
if (shares[shareholder].amount > 0) {
_distributeReward(shareholder);
}
uint256 sharesBefore = shares[shareholder].amount;
totalSharesDeposited += amount;
shares[shareholder].amount += amount;
shares[shareholder].stakedTime = block.timestamp;
if (sharesBefore == 0 && shares[shareholder].amount > 0) {
totalStakedUsers++;
}
rewards[shareholder].totalExcluded = _getCumulativeRewards(
shares[shareholder].amount
);
}
function _removeShares(address shareholder, uint256 amount) internal {
require(
shares[shareholder].amount > 0 && amount <= shares[shareholder].amount,
'REMOVE: no shares'
);
_distributeReward(shareholder);
totalSharesDeposited -= amount;
shares[shareholder].amount -= amount;
if (shares[shareholder].amount == 0) {
totalStakedUsers--;
}
rewards[shareholder].totalExcluded = _getCumulativeRewards(
shares[shareholder].amount
);
}
function depositRewards() external payable {
uint256 _amount = msg.value;
require(_amount > 0, 'DEPOSIT: no ETH');
require(totalSharesDeposited > 0, 'DEPOSIT: no shares');
totalRewards += _amount;
rewardsPerShare += (MULTIPLIER * _amount) / totalSharesDeposited;
emit DepositRewards(msg.sender, _amount);
}
function _distributeReward(address shareholder) internal {
if (shares[shareholder].amount == 0) {
return;
}
uint256 amount = getUnpaid(shareholder);
rewards[shareholder].totalRealized += amount;
rewards[shareholder].totalExcluded = _getCumulativeRewards(
shares[shareholder].amount
);
if (amount > 0) {
totalDistributed += amount;
uint256 _balBefore = address(this).balance;
(bool success, ) = payable(shareholder).call{ value: amount }('');
require(success, 'DIST: could not distribute');
require(address(this).balance >= _balBefore - amount, 'DIST: too much');
emit DistributeReward(shareholder, amount);
}
}
function claimReward() external {
_distributeReward(msg.sender);
emit ClaimReward(msg.sender);
}
function getUnpaid(address shareholder) public view returns (uint256) {
if (shares[shareholder].amount == 0) {
return 0;
}
uint256 earnedRewards = _getCumulativeRewards(shares[shareholder].amount);
uint256 rewardsExcluded = rewards[shareholder].totalExcluded;
if (earnedRewards <= rewardsExcluded) {
return 0;
}
return earnedRewards - rewardsExcluded;
}
function getShares(address user) external view returns (uint256) {
return shares[user].amount;
}
function _getCumulativeRewards(
uint256 share
) internal view returns (uint256) {
return (share * rewardsPerShare) / MULTIPLIER;
}
}
文件 7 的 37:IERC165.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 8 的 37:IERC20.sol
pragma solidity >=0.6.0 <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);
}
文件 9 的 37:IERC721.sol
pragma solidity >=0.6.2 <0.8.0;
import "../../introspection/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 balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}
文件 10 的 37:IERC721Enumerable.sol
pragma solidity >=0.6.2 <0.8.0;
import "./IERC721.sol";
interface IERC721Enumerable is IERC721 {
function totalSupply() external view returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);
function tokenByIndex(uint256 index) external view returns (uint256);
}
文件 11 的 37:IERC721Metadata.sol
pragma solidity >=0.6.2 <0.8.0;
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);
}
文件 12 的 37:IERC721Permit.sol
pragma solidity >=0.7.5;
import '@openzeppelin/contracts/token/ERC721/IERC721.sol';
interface IERC721Permit is IERC721 {
function PERMIT_TYPEHASH() external pure returns (bytes32);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function permit(
address spender,
uint256 tokenId,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external payable;
}
文件 13 的 37:IERC721Receiver.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC721Receiver {
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}
文件 14 的 37:IGudGuessTickets.sol
pragma solidity ^0.7.6;
pragma abicoder v2;
import '@openzeppelin/contracts/token/ERC721/IERC721.sol';
interface IGudGuessTickets is IERC721 {
struct TicketMetadata {
uint256 weeklyClose;
address token;
address primaryPool;
address nativeStablePool;
uint256 priceUSDX96;
uint32 winningsWeight;
}
function tickets(
uint256 tokenId
) external view returns (TicketMetadata memory);
function mint(
address owner,
uint256 weeklyClose,
address token,
address primaryPool,
address nativeStablePool,
uint256 priceUSDX96,
uint32 winningsWeight
) external returns (uint256);
}
文件 15 的 37:INonfungiblePositionManager.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
import '@openzeppelin/contracts/token/ERC721/IERC721Metadata.sol';
import '@openzeppelin/contracts/token/ERC721/IERC721Enumerable.sol';
import './IPoolInitializer.sol';
import './IERC721Permit.sol';
import './IPeripheryPayments.sol';
import './IPeripheryImmutableState.sol';
import '../libraries/PoolAddress.sol';
interface INonfungiblePositionManager is
IPoolInitializer,
IPeripheryPayments,
IPeripheryImmutableState,
IERC721Metadata,
IERC721Enumerable,
IERC721Permit
{
event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);
event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);
event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1);
function positions(uint256 tokenId)
external
view
returns (
uint96 nonce,
address operator,
address token0,
address token1,
uint24 fee,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
struct MintParams {
address token0;
address token1;
uint24 fee;
int24 tickLower;
int24 tickUpper;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
address recipient;
uint256 deadline;
}
function mint(MintParams calldata params)
external
payable
returns (
uint256 tokenId,
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
struct IncreaseLiquidityParams {
uint256 tokenId;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
function increaseLiquidity(IncreaseLiquidityParams calldata params)
external
payable
returns (
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
struct DecreaseLiquidityParams {
uint256 tokenId;
uint128 liquidity;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
function decreaseLiquidity(DecreaseLiquidityParams calldata params)
external
payable
returns (uint256 amount0, uint256 amount1);
struct CollectParams {
uint256 tokenId;
address recipient;
uint128 amount0Max;
uint128 amount1Max;
}
function collect(CollectParams calldata params) external payable returns (uint256 amount0, uint256 amount1);
function burn(uint256 tokenId) external payable;
}
文件 16 的 37:IPeripheryImmutableState.sol
pragma solidity >=0.5.0;
interface IPeripheryImmutableState {
function factory() external view returns (address);
function WETH9() external view returns (address);
}
文件 17 的 37:IPeripheryPayments.sol
pragma solidity >=0.7.5;
interface IPeripheryPayments {
function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;
function refundETH() external payable;
function sweepToken(
address token,
uint256 amountMinimum,
address recipient
) external payable;
}
文件 18 的 37:IPoolInitializer.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
interface IPoolInitializer {
function createAndInitializePoolIfNecessary(
address token0,
address token1,
uint24 fee,
uint160 sqrtPriceX96
) external payable returns (address pool);
}
文件 19 的 37:ISwapRouter.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';
interface ISwapRouter is IUniswapV3SwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}
文件 20 的 37:ITwapUtils.sol
pragma solidity ^0.7.6;
interface ITwapUtils {
function twapInterval() external view returns (uint32);
function getPoolPriceUSDX96(
address priceToken,
address pricePool,
address nativeStablePool,
address WETH9,
bool isPoolPairedWETH9
) external view returns (uint256);
function getSqrtPriceX96FromPoolAndInterval(
address uniswapV3Pool
) external view returns (uint160 sqrtPriceX96);
function getSqrtPriceX96FromPriceX96(
uint256 priceX96
) external pure returns (uint160 sqrtPriceX96);
function getPriceX96FromSqrtPriceX96(
uint160 sqrtPriceX96
) external pure returns (uint256 priceX96);
}
文件 21 的 37:IUniswapV3Pool.sol
pragma solidity >=0.5.0;
import './pool/IUniswapV3PoolImmutables.sol';
import './pool/IUniswapV3PoolState.sol';
import './pool/IUniswapV3PoolDerivedState.sol';
import './pool/IUniswapV3PoolActions.sol';
import './pool/IUniswapV3PoolOwnerActions.sol';
import './pool/IUniswapV3PoolEvents.sol';
interface IUniswapV3Pool is
IUniswapV3PoolImmutables,
IUniswapV3PoolState,
IUniswapV3PoolDerivedState,
IUniswapV3PoolActions,
IUniswapV3PoolOwnerActions,
IUniswapV3PoolEvents
{
}
文件 22 的 37:IUniswapV3PoolActions.sol
pragma solidity >=0.5.0;
interface IUniswapV3PoolActions {
function initialize(uint160 sqrtPriceX96) external;
function mint(
address recipient,
int24 tickLower,
int24 tickUpper,
uint128 amount,
bytes calldata data
) external returns (uint256 amount0, uint256 amount1);
function collect(
address recipient,
int24 tickLower,
int24 tickUpper,
uint128 amount0Requested,
uint128 amount1Requested
) external returns (uint128 amount0, uint128 amount1);
function burn(
int24 tickLower,
int24 tickUpper,
uint128 amount
) external returns (uint256 amount0, uint256 amount1);
function swap(
address recipient,
bool zeroForOne,
int256 amountSpecified,
uint160 sqrtPriceLimitX96,
bytes calldata data
) external returns (int256 amount0, int256 amount1);
function flash(
address recipient,
uint256 amount0,
uint256 amount1,
bytes calldata data
) external;
function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;
}
文件 23 的 37:IUniswapV3PoolDerivedState.sol
pragma solidity >=0.5.0;
interface IUniswapV3PoolDerivedState {
function observe(uint32[] calldata secondsAgos)
external
view
returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);
function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)
external
view
returns (
int56 tickCumulativeInside,
uint160 secondsPerLiquidityInsideX128,
uint32 secondsInside
);
}
文件 24 的 37:IUniswapV3PoolEvents.sol
pragma solidity >=0.5.0;
interface IUniswapV3PoolEvents {
event Initialize(uint160 sqrtPriceX96, int24 tick);
event Mint(
address sender,
address indexed owner,
int24 indexed tickLower,
int24 indexed tickUpper,
uint128 amount,
uint256 amount0,
uint256 amount1
);
event Collect(
address indexed owner,
address recipient,
int24 indexed tickLower,
int24 indexed tickUpper,
uint128 amount0,
uint128 amount1
);
event Burn(
address indexed owner,
int24 indexed tickLower,
int24 indexed tickUpper,
uint128 amount,
uint256 amount0,
uint256 amount1
);
event Swap(
address indexed sender,
address indexed recipient,
int256 amount0,
int256 amount1,
uint160 sqrtPriceX96,
uint128 liquidity,
int24 tick
);
event Flash(
address indexed sender,
address indexed recipient,
uint256 amount0,
uint256 amount1,
uint256 paid0,
uint256 paid1
);
event IncreaseObservationCardinalityNext(
uint16 observationCardinalityNextOld,
uint16 observationCardinalityNextNew
);
event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);
event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);
}
文件 25 的 37:IUniswapV3PoolImmutables.sol
pragma solidity >=0.5.0;
interface IUniswapV3PoolImmutables {
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function fee() external view returns (uint24);
function tickSpacing() external view returns (int24);
function maxLiquidityPerTick() external view returns (uint128);
}
文件 26 的 37:IUniswapV3PoolOwnerActions.sol
pragma solidity >=0.5.0;
interface IUniswapV3PoolOwnerActions {
function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;
function collectProtocol(
address recipient,
uint128 amount0Requested,
uint128 amount1Requested
) external returns (uint128 amount0, uint128 amount1);
}
文件 27 的 37:IUniswapV3PoolState.sol
pragma solidity >=0.5.0;
interface IUniswapV3PoolState {
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
function feeGrowthGlobal0X128() external view returns (uint256);
function feeGrowthGlobal1X128() external view returns (uint256);
function protocolFees() external view returns (uint128 token0, uint128 token1);
function liquidity() external view returns (uint128);
function ticks(int24 tick)
external
view
returns (
uint128 liquidityGross,
int128 liquidityNet,
uint256 feeGrowthOutside0X128,
uint256 feeGrowthOutside1X128,
int56 tickCumulativeOutside,
uint160 secondsPerLiquidityOutsideX128,
uint32 secondsOutside,
bool initialized
);
function tickBitmap(int16 wordPosition) external view returns (uint256);
function positions(bytes32 key)
external
view
returns (
uint128 _liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
function observations(uint256 index)
external
view
returns (
uint32 blockTimestamp,
int56 tickCumulative,
uint160 secondsPerLiquidityCumulativeX128,
bool initialized
);
}
文件 28 的 37:IUniswapV3SwapCallback.sol
pragma solidity >=0.5.0;
interface IUniswapV3SwapCallback {
function uniswapV3SwapCallback(
int256 amount0Delta,
int256 amount1Delta,
bytes calldata data
) external;
}
文件 29 的 37:IWETH.sol
pragma solidity ^0.7.6;
interface IWETH {
function balanceOf(address wallet) external view returns (uint256);
function decimals() external view returns (uint8);
function deposit() external payable;
function withdraw(uint256 _amount) external;
}
文件 30 的 37:IWinnersCircle.sol
pragma solidity ^0.7.6;
interface IWinnersCircle {
function closeWeeklyAndAddWinnings(
uint256 weeklyCloseTimestamp,
uint256 priceX96,
uint256 totalWinningsWeight
) external payable;
}
文件 31 的 37:Ownable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), 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 {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
文件 32 的 37:PeripheryImmutableState.sol
pragma solidity =0.7.6;
import '../interfaces/IPeripheryImmutableState.sol';
abstract contract PeripheryImmutableState is IPeripheryImmutableState {
address public immutable override factory;
address public immutable override WETH9;
constructor(address _factory, address _WETH9) {
factory = _factory;
WETH9 = _WETH9;
}
}
文件 33 的 37:PoolAddress.sol
pragma solidity >=0.5.0;
library PoolAddress {
bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;
struct PoolKey {
address token0;
address token1;
uint24 fee;
}
function getPoolKey(
address tokenA,
address tokenB,
uint24 fee
) internal pure returns (PoolKey memory) {
if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);
return PoolKey({token0: tokenA, token1: tokenB, fee: fee});
}
function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {
require(key.token0 < key.token1);
pool = address(
uint256(
keccak256(
abi.encodePacked(
hex'ff',
factory,
keccak256(abi.encode(key.token0, key.token1, key.fee)),
POOL_INIT_CODE_HASH
)
)
)
);
}
}
文件 34 的 37:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
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) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
文件 35 的 37:TickMath.sol
pragma solidity >=0.5.0 <0.8.0;
library TickMath {
int24 internal constant MIN_TICK = -887272;
int24 internal constant MAX_TICK = -MIN_TICK;
uint160 internal constant MIN_SQRT_RATIO = 4295128739;
uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;
function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {
uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));
require(absTick <= uint256(MAX_TICK), 'T');
uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;
if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;
if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;
if (tick > 0) ratio = type(uint256).max / ratio;
sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));
}
function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {
require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');
uint256 ratio = uint256(sqrtPriceX96) << 32;
uint256 r = ratio;
uint256 msb = 0;
assembly {
let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(5, gt(r, 0xFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(4, gt(r, 0xFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(3, gt(r, 0xFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(2, gt(r, 0xF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(1, gt(r, 0x3))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := gt(r, 0x1)
msb := or(msb, f)
}
if (msb >= 128) r = ratio >> (msb - 127);
else r = ratio << (127 - msb);
int256 log_2 = (int256(msb) - 128) << 64;
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(63, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(62, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(61, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(60, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(59, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(58, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(57, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(56, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(55, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(54, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(53, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(52, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(51, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(50, f))
}
int256 log_sqrt10001 = log_2 * 255738958999603826347141;
int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);
int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);
tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;
}
}
文件 36 的 37:TransferHelper.sol
pragma solidity >=0.6.0;
import '@openzeppelin/contracts/token/ERC20/IERC20.sol';
library TransferHelper {
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
(bool success, bytes memory data) =
token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');
}
function safeTransfer(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');
}
function safeApprove(
address token,
address to,
uint256 value
) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, 'STE');
}
}
文件 37 的 37:UniswapV3FeeERC20.sol
pragma solidity ^0.7.6;
pragma abicoder v2;
import '@openzeppelin/contracts/token/ERC20/ERC20.sol';
import '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol';
import '@openzeppelin/contracts/access/Ownable.sol';
import '@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol';
import '@uniswap/v3-core/contracts/libraries/TickMath.sol';
import '@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol';
import '@uniswap/v3-periphery/contracts/interfaces/INonfungiblePositionManager.sol';
import '@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol';
import '@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol';
import '@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol';
import './interfaces/IWETH.sol';
contract UniswapV3FeeERC20 is
IERC721Receiver,
ERC20,
Ownable,
PeripheryImmutableState
{
uint24[] internal _lpPoolFees;
INonfungiblePositionManager public lpPosManager;
ISwapRouter public swapRouter;
mapping(address => uint256) public liquidityPositions;
bool internal liquidityPosInitialized;
constructor(
string memory _name,
string memory _symbol,
INonfungiblePositionManager _manager,
ISwapRouter _swapRouter,
address _factory,
address _WETH9
) ERC20(_name, _symbol) PeripheryImmutableState(_factory, _WETH9) {
lpPosManager = _manager;
swapRouter = _swapRouter;
}
function onERC721Received(
address,
address,
uint256,
bytes calldata
) external override returns (bytes4) {
return this.onERC721Received.selector;
}
function collectLiquidityPositionFees(address _pool) external {
require(liquidityPosInitialized, 'COLLECTLPFEES: not initialized');
lpPosManager.collect(
INonfungiblePositionManager.CollectParams({
tokenId: liquidityPositions[_pool],
recipient: owner(),
amount0Max: type(uint128).max,
amount1Max: type(uint128).max
})
);
}
function depositLiquidityPosition(uint256 _tokenId) external onlyOwner {
address _owner = lpPosManager.ownerOf(_tokenId);
if (_owner != address(this)) {
lpPosManager.safeTransferFrom(_owner, address(this), _tokenId);
}
(
,
,
address _token0,
address _token1,
uint24 _fee,
,
,
,
,
,
,
) = lpPosManager.positions(_tokenId);
PoolAddress.PoolKey memory _poolKey = PoolAddress.PoolKey({
token0: _token0,
token1: _token1,
fee: _fee
});
address _pool = PoolAddress.computeAddress(factory, _poolKey);
_lpPoolFees.push(_fee);
liquidityPositions[_pool] = _tokenId;
}
function withdrawLiquidityPosition(address _pool) external onlyOwner {
uint256 _tokenId = liquidityPositions[_pool];
require(_tokenId > 0, 'WITHDRAW: no position');
delete liquidityPositions[_pool];
lpPosManager.safeTransferFrom(address(this), owner(), _tokenId);
uint24 _fee = IUniswapV3Pool(_pool).fee();
uint256 _idx;
for (uint256 _i = 0; _i < _lpPoolFees.length; _i++) {
if (_lpPoolFees[_i] == _fee) {
_idx = _i;
break;
}
}
_lpPoolFees[_idx] = _lpPoolFees[_lpPoolFees.length - 1];
_lpPoolFees.pop();
}
function _createLiquidityPool(
uint24 _poolFee,
uint160 _initialSqrtPriceX96,
uint16 _initPriceObservations
) internal {
(address _token0, address _token1) = _getToken0AndToken1();
for (uint256 _i = 0; _i < _lpPoolFees.length; _i++) {
require(_lpPoolFees[_i] != _poolFee, 'CREATEPOOL: already created');
}
_lpPoolFees.push(_poolFee);
address _newPool = lpPosManager.createAndInitializePoolIfNecessary(
_token0,
_token1,
_poolFee,
_initialSqrtPriceX96
);
if (_initPriceObservations > 0) {
IUniswapV3Pool(_newPool).increaseObservationCardinalityNext(
_initPriceObservations
);
}
}
function _createLiquidityPosition(
uint24 _poolFee,
uint256 _amount0,
uint256 _amount1
) internal returns (address pool) {
uint256 _balBefore = address(this).balance;
(address token0, address token1) = _getToken0AndToken1();
uint256 _amountETH = _amount1;
if (token0 != address(this)) {
uint256 _cachedAmount0 = _amount0;
_amount0 = _amount1;
_amount1 = _cachedAmount0;
}
TransferHelper.safeApprove(token0, address(lpPosManager), _amount0);
TransferHelper.safeApprove(token1, address(lpPosManager), _amount1);
(, , address _pool) = _getPoolInfo(_poolFee);
require(liquidityPositions[_pool] == 0, 'CREATELP: already created');
int24 _tickSpaceMaxMod = TickMath.MAX_TICK %
IUniswapV3Pool(_pool).tickSpacing();
INonfungiblePositionManager.MintParams
memory params = INonfungiblePositionManager.MintParams({
token0: token0,
token1: token1,
fee: _poolFee,
tickLower: TickMath.MIN_TICK + _tickSpaceMaxMod,
tickUpper: TickMath.MAX_TICK - _tickSpaceMaxMod,
amount0Desired: _amount0,
amount1Desired: _amount1,
amount0Min: 0,
amount1Min: 0,
recipient: address(this),
deadline: block.timestamp
});
(
uint256 tokenId,
,
uint256 amount0Actual,
uint256 amount1Actual
) = lpPosManager.mint{ value: _amountETH }(params);
lpPosManager.refundETH();
uint256 _returnETH = address(this).balance - (_balBefore - _amountETH);
if (_returnETH > 0) {
(bool _ethRefunded, ) = payable(owner()).call{ value: _returnETH }('');
require(_ethRefunded, 'CREATELP: ETH not refunded');
}
TransferHelper.safeApprove(token0, address(lpPosManager), 0);
TransferHelper.safeApprove(token1, address(lpPosManager), 0);
if (token0 == address(this)) {
if (amount0Actual < _amount0) {
uint256 refund0 = _amount0 - amount0Actual;
TransferHelper.safeTransfer(token0, owner(), refund0);
}
} else if (amount1Actual < _amount1) {
uint256 refund1 = _amount1 - amount1Actual;
TransferHelper.safeTransfer(token1, owner(), refund1);
}
liquidityPositions[_pool] = tokenId;
liquidityPosInitialized = true;
return _pool;
}
function _swapTokensForETH(uint256 _amountIn) internal {
for (uint256 _i = 0; _i < _lpPoolFees.length; _i++) {
uint24 _fee = _lpPoolFees[_i];
(, , address _pool) = _getPoolInfo(_fee);
(, , , , , , bool _unlocked) = IUniswapV3Pool(_pool).slot0();
if (!_unlocked) {
continue;
}
TransferHelper.safeApprove(address(this), address(swapRouter), _amountIn);
swapRouter.exactInputSingle(
ISwapRouter.ExactInputSingleParams({
tokenIn: address(this),
tokenOut: WETH9,
fee: _fee,
recipient: address(this),
deadline: block.timestamp,
amountIn: _amountIn,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
})
);
uint256 _balWETH = ERC20(WETH9).balanceOf(address(this));
if (_balWETH > 0) {
IWETH(WETH9).withdraw(_balWETH);
}
break;
}
}
function _getPoolInfo(
uint24 _fee
) internal view returns (address token0, address token1, address pool) {
(token0, token1) = _getToken0AndToken1();
PoolAddress.PoolKey memory _poolKey = PoolAddress.PoolKey({
token0: token0,
token1: token1,
fee: _fee
});
pool = PoolAddress.computeAddress(factory, _poolKey);
}
function _getToken0AndToken1() internal view returns (address, address) {
address _t0 = address(this);
address _t1 = WETH9;
return _t0 < _t1 ? (_t0, _t1) : (_t1, _t0);
}
receive() external payable {}
}
{
"compilationTarget": {
"contracts/GudGuess.sol": "GudGuess"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract INonfungiblePositionManager","name":"_manager","type":"address"},{"internalType":"contract ISwapRouter","name":"_swapRouter","type":"address"},{"internalType":"address","name":"_priceToken","type":"address"},{"internalType":"contract IUniswapV3Pool","name":"_pricePool","type":"address"},{"internalType":"contract IUniswapV3Pool","name":"_nativeStablePool","type":"address"},{"internalType":"bool","name":"__isPoolPairedWETH9","type":"bool"},{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_WETH9","type":"address"}],"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":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":true,"internalType":"uint256","name":"weeklyClose","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceX96","type":"uint256"}],"name":"BuyTicket","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":"uint256","name":"weeklyClose","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"closePriceX96","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalGuesses","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalWinners","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalWeight","type":"uint256"}],"name":"SubmitWeeklyClose","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":[],"name":"WETH9","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adminPerc","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adminWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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":"","type":"address"}],"name":"amms","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burnPerc","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_priceUSDX96","type":"uint256[]"}],"name":"buyMultipleTickets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_priceUSDX96","type":"uint256"}],"name":"buyTicket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"collectLiquidityPositionFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"depositLiquidityPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_bot","type":"address"}],"name":"forgiveBot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCurrentPriceTokensPerTicket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentPriceUSDX96","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPriceTokenPriceUSDX96","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"getStartEndOfWeeklyGuessPeriod","outputs":[{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"uint256","name":"span","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalJackpotBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"getWeeklyCloseFromTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"guessCutoffBeforeClose","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isBot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"launchTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"liquidityPositions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint24","name":"_fee","type":"uint24"},{"internalType":"uint256","name":"_initialPriceX96","type":"uint256"},{"internalType":"uint16","name":"_initPriceObservations","type":"uint16"}],"name":"lpCreatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"_fee","type":"uint24"},{"internalType":"uint8","name":"_percentTokenAllo","type":"uint8"}],"name":"lpCreatePosition","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"lpPosManager","outputs":[{"internalType":"contract INonfungiblePositionManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manualSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxGuessJackpotWeight","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minGuessJackpotWeight","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nativeStablePool","outputs":[{"internalType":"contract IUniswapV3Pool","name":"","type":"address"}],"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":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"precisionDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pricePerTicketMaxUSDX96","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pricePerTicketMinUSDX96","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pricePool","outputs":[{"internalType":"contract IUniswapV3Pool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewards","outputs":[{"internalType":"contract HolderRewards","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardsExcluded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsPerc","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_perc","type":"uint32"}],"name":"setAdminPerc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_adminWallet","type":"address"}],"name":"setAdminWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_perc","type":"uint32"}],"name":"setBurnPerc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_seconds","type":"uint256"}],"name":"setGuessCutoffBeforeClose","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_min","type":"uint32"},{"internalType":"uint32","name":"_max","type":"uint32"}],"name":"setGuessJackpotWeights","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wallet","type":"address"},{"internalType":"bool","name":"_isExcluded","type":"bool"}],"name":"setIsRewardsExcluded","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_decimals","type":"uint8"}],"name":"setPrecisionDecimals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minUSD18","type":"uint256"},{"internalType":"uint256","name":"_maxUSD18","type":"uint256"}],"name":"setPricePerTicketUSDX96","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"contract IUniswapV3Pool","name":"_pool","type":"address"},{"internalType":"bool","name":"_pairedWithWETH9","type":"bool"}],"name":"setPriceTokenAndPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_perc","type":"uint32"}],"name":"setRewardsPerc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_supplyPerc","type":"uint256"}],"name":"setSwapAtAmountSupplyPerc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setSwapEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setTaxEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IGudGuessTickets","name":"_tickets","type":"address"}],"name":"setTickets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ITwapUtils","name":"_twapUtils","type":"address"}],"name":"setTwapUtils","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IWinnersCircle","name":"_winnersCircle","type":"address"}],"name":"setWinnersCircle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_perc","type":"uint32"}],"name":"setWinningsPerc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"submitClose","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapAtAmountSupplyPerc","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapRouter","outputs":[{"internalType":"contract ISwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tickets","outputs":[{"internalType":"contract IGudGuessTickets","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_amm","type":"address"}],"name":"toggleAmm","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalWeeklyGuesses","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","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":[],"name":"twapUtils","outputs":[{"internalType":"contract ITwapUtils","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"weeklyClosePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"weeklyGuesses","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"weeklyWeights","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"winnersCircle","outputs":[{"internalType":"contract IWinnersCircle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"winningsPerc","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"withdrawLiquidityPosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]