Contract Source Code:
File 1 of 1 : HEDGEPOT
// File: @openzeppelin/contracts/utils/Context.sol
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
// File: @openzeppelin/contracts/access/Ownable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
// File: holder-storage.sol
pragma solidity ^0.8.26;
contract HolderStorage is Ownable {
address public tokenContract;
address public devWallet;
mapping(address => uint256) public balances;
mapping(address => uint256) private holderIndexes;
address[] public holders;
mapping(address => bool) public isHolder;
uint8 private constant decimals = 18;
uint256 public minimumBalance = 50000 * 10**decimals;
struct Payout {
address recipient;
uint256 amount;
string potType;
uint256 timestamp;
}
mapping(address => Payout[]) public holderPayoutHistory;
uint256 public totalHourlyPayouts;
uint256 public totalMegaPayouts;
uint256 public totalHourlyAmountPaid;
uint256 public totalMegaAmountPaid;
Payout[] public payoutHistory;
mapping(address => bool) public excludedFromPot;
modifier onlyTokenContract() {
require(msg.sender == tokenContract, "HolderStorage: Not authorized");
_;
}
constructor(address initialOwner) Ownable(initialOwner) {}
function setTokenContract(address _tokenContract) external onlyOwner {
require(
tokenContract == address(0),
"HolderStorage: Token contract already set"
);
tokenContract = _tokenContract;
}
function setDevWallet(address _devWallet) external onlyOwner {
require(
_devWallet != address(0),
"HolderStorage: Dev wallet is zero address"
);
devWallet = _devWallet;
}
function excludeFromPot(address account) external onlyOwner {
require(
account != devWallet,
"HolderStorage: Cannot exclude dev wallet"
);
excludedFromPot[account] = true;
}
function includeInPot(address account) external onlyOwner {
excludedFromPot[account] = false;
}
function setMinimumBalance(uint256 newMinimumBalance) external onlyOwner {
minimumBalance = newMinimumBalance;
}
function updateHolder(address holder, uint256 newBalance)
external
onlyTokenContract
{
if (newBalance < minimumBalance) {
removeHolder(holder);
} else {
if (!isHolder[holder]) {
holders.push(holder);
holderIndexes[holder] = holders.length - 1;
isHolder[holder] = true;
}
balances[holder] = newBalance;
}
}
function removeHolder(address holder) internal {
if (isHolder[holder]) {
uint256 index = holderIndexes[holder];
uint256 lastIndex = holders.length - 1;
if (index != lastIndex) {
address lastHolder = holders[lastIndex];
holders[index] = lastHolder;
holderIndexes[lastHolder] = index;
}
holders.pop();
isHolder[holder] = false;
balances[holder] = 0;
}
}
function getHolderCount() external view returns (uint256) {
return holders.length;
}
function getHolderByIndex(uint256 index) external view returns (address) {
require(index < holders.length, "HolderStorage: Index out of bounds");
return holders[index];
}
function recordPayout(
address recipient,
uint256 amount,
string memory potType
) external onlyTokenContract {
payoutHistory.push(Payout(recipient, amount, potType, block.timestamp));
if (keccak256(bytes(potType)) == keccak256(bytes("Hourly Jackpot"))) {
totalHourlyPayouts++;
totalHourlyAmountPaid += amount;
} else if (
keccak256(bytes(potType)) == keccak256(bytes("Mega Jackpot"))
) {
totalMegaPayouts++;
totalMegaAmountPaid += amount;
}
holderPayoutHistory[recipient].push(
Payout(recipient, amount, potType, block.timestamp)
);
if (recipient != devWallet) {
removeHolder(recipient);
}
}
function getPayoutHistoryByHolder(address holder)
external
view
returns (Payout[] memory)
{
return holderPayoutHistory[holder];
}
function getPayoutHistory(uint256 index)
external
view
returns (
address recipient,
uint256 amount,
string memory potType,
uint256 timestamp
)
{
require(
index < payoutHistory.length,
"HolderStorage: Index out of bounds"
);
Payout memory payout = payoutHistory[index];
return (
payout.recipient,
payout.amount,
payout.potType,
payout.timestamp
);
}
function getAggregateStats()
external
view
returns (
uint256 totalHourlyPayouts_,
uint256 totalMegaPayouts_,
uint256 totalHourlyAmountPaid_,
uint256 totalMegaAmountPaid_
)
{
return (
totalHourlyPayouts,
totalMegaPayouts,
totalHourlyAmountPaid,
totalMegaAmountPaid
);
}
function isEligibleForJackpot(address account)
external
view
returns (bool)
{
return !excludedFromPot[account];
}
}
// File: hpot.sol
pragma solidity ^0.8.26;
interface IUniswapV2Router02 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
returns (
uint256 amountToken,
uint256 amountETH,
uint256 liquidity
);
}
interface IUniswapV2Factory {
function createPair(address tokenA, address tokenB)
external
returns (address pair);
}
interface IUniswapV2Pair {
function getReserves()
external
view
returns (
uint112 reserve0,
uint112 reserve1,
uint32 blockTimestampLast
);
function token0() external view returns (address);
}
contract HEDGEPOT is IERC20, Ownable {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
mapping(address => bool) private _isExcludedFromFee;
address payable private _devWallet;
HolderStorage public holderStorage;
uint8 private constant _decimals = 18;
uint256 private constant _tTotal = 1_000_000_000 * 10**_decimals;
string private constant _name = unicode"HedgePot";
string private constant _symbol = unicode"HPOT";
uint256 public _maxTxAmount = 21500000000000 * 10**_decimals;
uint256 public _maxWalletSize = 8413800000000 * 10**_decimals;
uint256 public hourlyJackpotPool;
uint256 public megaJackpotPool;
uint256 public lastHourlyDraw;
uint256 public lastMegaDraw;
uint256 public hourlyInterval = 1 hours;
uint256 public megaInterval = 24 hours;
IUniswapV2Router02 private uniswapV2Router;
address private uniswapV2Pair;
bool private tradingOpen;
event MaxTxAmountUpdated(uint256 _maxTxAmount);
event HourlyJackpotWon(address indexed winner, uint256 amount);
event MegaJackpotWon(address indexed winner, uint256 amount);
constructor(address _holderStorage) Ownable(_msgSender()) {
_devWallet = payable(0xFe0a51777d8CB514754b3b19f6dB5389298Fc5F5);
_balances[_msgSender()] = _tTotal;
_isExcludedFromFee[owner()] = true;
_isExcludedFromFee[_msgSender()] = true;
_isExcludedFromFee[address(this)] = true;
_isExcludedFromFee[_devWallet] = true;
holderStorage = HolderStorage(_holderStorage);
lastHourlyDraw = block.timestamp;
lastMegaDraw = block.timestamp;
emit Transfer(address(0), _msgSender(), _tTotal);
}
function name() public pure returns (string memory) {
return _name;
}
function symbol() public pure returns (string memory) {
return _symbol;
}
function decimals() public pure returns (uint8) {
return _decimals;
}
function totalSupply() public pure override returns (uint256) {
return _tTotal;
}
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
function excludeFromFee(address account) external onlyOwner {
_isExcludedFromFee[account] = true;
}
function isExcludedFromFee(address account) public view returns (bool) {
return _isExcludedFromFee[account];
}
function transfer(address recipient, uint256 amount)
public
override
returns (bool)
{
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender)
public
view
override
returns (uint256)
{
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount)
public
override
returns (bool)
{
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public override returns (bool) {
_transfer(sender, recipient, amount);
_approve(
sender,
_msgSender(),
_allowances[sender][_msgSender()] - amount
);
return true;
}
function _approve(
address owner,
address spender,
uint256 amount
) private {
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 donateToMegaPotOrBurn(address sniper, bool donateToMega)
external
onlyOwner
{
uint256 balance = balanceOf(sniper);
require(balance > 0, "Early sniper has no tokens to donate");
if (donateToMega) {
_transfer(sniper, address(this), balance);
megaJackpotPool += balance;
emit Transfer(sniper, address(this), balance);
} else {
_transfer(
sniper,
address(0x000000000000000000000000000000000000dEaD),
balance
);
}
}
function _transfer(
address from,
address to,
uint256 amount
) private {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
require(amount > 0, "Transfer amount must be greater than zero");
uint256 feeAmount = 0;
if (
from == uniswapV2Pair &&
to != address(uniswapV2Router) &&
!_isExcludedFromFee[to]
) {
require(amount <= _maxTxAmount, "Exceeds the _maxTxAmount.");
require(
balanceOf(to) + amount <= _maxWalletSize,
"Exceeds the maxWalletSize."
);
}
if (!_isExcludedFromFee[from]) {
feeAmount = (amount * 3) / 100;
uint256 hourlyPotFee = feeAmount / 3;
uint256 megaPotFee = feeAmount / 3;
uint256 devFee = feeAmount / 3;
hourlyJackpotPool += hourlyPotFee;
megaJackpotPool += megaPotFee;
_balances[_devWallet] += devFee;
_balances[address(this)] += hourlyPotFee + megaPotFee;
emit Transfer(from, _devWallet, devFee);
emit Transfer(from, address(this), hourlyPotFee + megaPotFee);
}
_balances[from] -= amount;
_balances[to] += (amount - feeAmount);
emit Transfer(from, to, amount - feeAmount);
holderStorage.updateHolder(from, _balances[from]);
holderStorage.updateHolder(to, _balances[to]);
bool hourlyDue = block.timestamp >= lastHourlyDraw + hourlyInterval;
bool megaDue = block.timestamp >= lastMegaDraw + megaInterval;
if (hourlyDue) {
distributeHourlyJackpot();
}
if (megaDue) {
distributeMegaJackpot();
}
}
function getTimeUntilHourlyPayout() public view returns (uint256) {
if (block.timestamp >= lastHourlyDraw + hourlyInterval) {
return 0;
} else {
return (lastHourlyDraw + hourlyInterval) - block.timestamp;
}
}
function getTimeUntilMegaPayout() public view returns (uint256) {
if (block.timestamp >= lastMegaDraw + megaInterval) {
return 0;
} else {
return (lastMegaDraw + megaInterval) - block.timestamp;
}
}
function getCurrentHourlyPot() public view returns (uint256) {
return hourlyJackpotPool;
}
function getCurrentMegaPot() public view returns (uint256) {
return megaJackpotPool;
}
function distributeHourlyJackpot() internal {
lastHourlyDraw = block.timestamp;
uint256 holderCount = holderStorage.getHolderCount();
if (holderCount == 0 || hourlyJackpotPool == 0) {
return;
}
address winner;
uint256 randomIndex;
do {
randomIndex =
uint256(
keccak256(
abi.encodePacked(block.timestamp, block.prevrandao)
)
) %
holderCount;
winner = holderStorage.getHolderByIndex(randomIndex);
} while (!holderStorage.isEligibleForJackpot(winner));
uint256 reward = hourlyJackpotPool;
hourlyJackpotPool = 0;
_transfer(address(this), winner, reward);
holderStorage.recordPayout(winner, reward, "Hourly Jackpot");
emit HourlyJackpotWon(winner, reward);
}
function distributeMegaJackpot() internal {
lastMegaDraw = block.timestamp;
uint256 holderCount = holderStorage.getHolderCount();
if (holderCount == 0 || megaJackpotPool == 0) {
return;
}
address winner;
uint256 randomIndex;
do {
randomIndex =
uint256(
keccak256(
abi.encodePacked(block.timestamp, block.prevrandao)
)
) %
holderCount;
winner = holderStorage.getHolderByIndex(randomIndex);
} while (!holderStorage.isEligibleForJackpot(winner));
uint256 reward = megaJackpotPool;
megaJackpotPool = 0;
_transfer(address(this), winner, reward);
holderStorage.recordPayout(winner, reward, "Mega Jackpot");
emit MegaJackpotWon(winner, reward);
}
function distributeHourlyPot() external {
if (block.timestamp >= lastHourlyDraw + hourlyInterval) {
distributeHourlyJackpot();
}
}
function distributeMegaPot() external {
if (block.timestamp >= lastMegaDraw + megaInterval) {
distributeMegaJackpot();
}
}
function donateToHourlyPot(uint256 amount) external {
require(amount > 0, "Amount must be greater than zero");
require(_balances[_msgSender()] >= amount, "Insufficient balance");
_balances[_msgSender()] -= amount;
_balances[address(this)] += amount;
hourlyJackpotPool += amount;
emit Transfer(_msgSender(), address(this), amount);
}
function donateToMegaPot(uint256 amount) external {
require(amount > 0, "Amount must be greater than zero");
require(_balances[_msgSender()] >= amount, "Insufficient balance");
_balances[_msgSender()] -= amount;
_balances[address(this)] += amount;
megaJackpotPool += amount;
emit Transfer(_msgSender(), address(this), amount);
}
function removeLimits() external onlyOwner {
_maxTxAmount = _tTotal;
_maxWalletSize = _tTotal;
emit MaxTxAmountUpdated(_tTotal);
}
function getTokenPrice() public view returns (uint256) {
IUniswapV2Pair pair = IUniswapV2Pair(uniswapV2Pair);
(uint112 reserve0, uint112 reserve1, ) = pair.getReserves();
address token0 = pair.token0();
uint256 tokenReserve;
uint256 wethReserve;
if (token0 == address(this)) {
tokenReserve = reserve0;
wethReserve = reserve1;
} else {
tokenReserve = reserve1;
wethReserve = reserve0;
}
if (tokenReserve == 0) {
return 0;
} else {
return (wethReserve * 1e18) / tokenReserve;
}
}
function openTrading() external onlyOwner {
require(!tradingOpen, "Trading is already open");
uniswapV2Router = IUniswapV2Router02(
0x591cf6942c422fA53E8D81c62a9692D7BeA72F61
);
_approve(address(this), address(uniswapV2Router), _tTotal);
uniswapV2Pair = IUniswapV2Factory(uniswapV2Router.factory()).createPair(
address(this),
uniswapV2Router.WETH()
);
uniswapV2Router.addLiquidityETH{value: address(this).balance}(
address(this),
balanceOf(address(this)),
0,
0,
owner(),
block.timestamp
);
IERC20(uniswapV2Pair).approve(
address(uniswapV2Router),
type(uint256).max
);
tradingOpen = true;
}
receive() external payable {}
function rescueStuckSonic() public {
uint256 contractETHBalance = address(this).balance;
require(contractETHBalance > 0, "No Sonic to rescue");
_devWallet.transfer(contractETHBalance);
}
}