Contract Source Code:
File 1 of 1 : SFOG
/**
**/
pragma solidity ^0.8.17;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
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);
/**
* @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);
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
);
}
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
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 to, uint256 amount)
public
virtual
override
returns (bool)
{
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
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)
{
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue)
public
virtual
returns (bool)
{
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue)
public
virtual
returns (bool)
{
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(
currentAllowance >= subtractedValue,
"ERC20: decreased allowance below zero"
);
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(
fromBalance >= amount,
"ERC20: transfer amount exceeds balance"
);
unchecked {
_balances[from] = fromBalance - amount;
// Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
// decrementing then incrementing.
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, 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 += amount;
unchecked {
// Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(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);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
// Overflow not possible: amount <= accountBalance <= totalSupply.
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(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 _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(
currentAllowance >= amount,
"ERC20: insufficient allowance"
);
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b)
internal
pure
returns (bool, uint256)
{
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
constructor() {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() external 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;
}
}
interface IRouter {
error EXPIRED();
error IDENTICAL();
error ZERO_ADDRESS();
error INSUFFICIENT_AMOUNT();
error INSUFFICIENT_LIQUIDITY();
error INSUFFICIENT_OUTPUT_AMOUNT();
error INVALID_PATH();
error INSUFFICIENT_B_AMOUNT();
error INSUFFICIENT_A_AMOUNT();
error EXCESSIVE_INPUT_AMOUNT();
error ETH_TRANSFER_FAILED();
error INVALID_RESERVES();
struct route {
/// @dev token from
address from;
/// @dev token to
address to;
/// @dev is stable route
bool stable;
}
function WETH() external pure returns (address);
function factory() external pure returns (address);
/// @notice sorts the tokens to see what the expected LP output would be for token0 and token1 (A/B)
/// @param tokenA the address of tokenA
/// @param tokenB the address of tokenB
/// @return token0 address of which becomes token0
/// @return token1 address of which becomes token1
function sortTokens(address tokenA, address tokenB)
external
pure
returns (address token0, address token1);
/// @notice calculates the CREATE2 address for a pair without making any external calls
/// @param tokenA the address of tokenA
/// @param tokenB the address of tokenB
/// @param stable if the pair is using the stable curve
/// @return pair address of the pair
function pairFor(
address tokenA,
address tokenB,
bool stable
) external view returns (address pair);
/// @notice fetches and sorts the reserves for a pair
/// @param tokenA the address of tokenA
/// @param tokenB the address of tokenB
/// @param stable if the pair is using the stable curve
/// @return reserveA get the reserves for tokenA
/// @return reserveB get the reserves for tokenB
function getReserves(
address tokenA,
address tokenB,
bool stable
) external view returns (uint256 reserveA, uint256 reserveB);
/// @notice performs chained getAmountOut calculations on any number of pairs
/// @param amountIn the amount of tokens of routes[0] to swap
/// @param routes the struct of the hops the swap should take
/// @return amounts uint array of the amounts out
function getAmountsOut(uint256 amountIn, route[] memory routes)
external
view
returns (uint256[] memory amounts);
/// @notice performs chained getAmountOut calculations on any number of pairs
/// @param amountIn amount of tokenIn
/// @param tokenIn address of the token going in
/// @param tokenOut address of the token coming out
/// @return amount uint amount out
/// @return stable if the curve used is stable or not
function getAmountOut(
uint256 amountIn,
address tokenIn,
address tokenOut
) external view returns (uint256 amount, bool stable);
/// @notice performs calculations to determine the expected state when adding liquidity
/// @param tokenA the address of tokenA
/// @param tokenB the address of tokenB
/// @param stable if the pair is using the stable curve
/// @param amountADesired amount of tokenA desired to be added
/// @param amountBDesired amount of tokenB desired to be added
/// @return amountA amount of tokenA added
/// @return amountB amount of tokenB added
/// @return liquidity liquidity value added
function quoteAddLiquidity(
address tokenA,
address tokenB,
bool stable,
uint256 amountADesired,
uint256 amountBDesired
)
external
view
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
);
/// @param tokenA the address of tokenA
/// @param tokenB the address of tokenB
/// @param stable if the pair is using the stable curve
/// @param liquidity liquidity value to remove
/// @return amountA amount of tokenA removed
/// @return amountB amount of tokenB removed
function quoteRemoveLiquidity(
address tokenA,
address tokenB,
bool stable,
uint256 liquidity
) external view returns (uint256 amountA, uint256 amountB);
/// @param tokenA the address of tokenA
/// @param tokenB the address of tokenB
/// @param stable if the pair is using the stable curve
/// @param amountADesired amount of tokenA desired to be added
/// @param amountBDesired amount of tokenB desired to be added
/// @param amountAMin slippage for tokenA calculated from this param
/// @param amountBMin slippage for tokenB calculated from this param
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
/// @return amountA amount of tokenA used
/// @return amountB amount of tokenB used
/// @return liquidity amount of liquidity minted
function addLiquidity(
address tokenA,
address tokenB,
bool stable,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
)
external
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
);
/// @param token the address of token
/// @param stable if the pair is using the stable curve
/// @param amountTokenDesired desired amount for token
/// @param amountTokenMin slippage for token
/// @param amountETHMin minimum amount of ETH added (slippage)
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
/// @return amountToken amount of the token used
/// @return amountETH amount of ETH used
/// @return liquidity amount of liquidity minted
function addLiquidityETH(
address token,
bool stable,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
returns (
uint256 amountToken,
uint256 amountETH,
uint256 liquidity
);
/// @param tokenA the address of tokenA
/// @param tokenB the address of tokenB
/// @param stable if the pair is using the stable curve
/// @param amountADesired amount of tokenA desired to be added
/// @param amountBDesired amount of tokenB desired to be added
/// @param amountAMin slippage for tokenA calculated from this param
/// @param amountBMin slippage for tokenB calculated from this param
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
/// @return amountA amount of tokenA used
/// @return amountB amount of tokenB used
/// @return liquidity amount of liquidity minted
function addLiquidityAndStake(
address tokenA,
address tokenB,
bool stable,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
)
external
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
);
/// @notice adds liquidity to a legacy pair using ETH, and stakes it into a gauge on "to's" behalf
/// @param token the address of token
/// @param stable if the pair is using the stable curve
/// @param amountTokenDesired amount of token to be used
/// @param amountTokenMin slippage of token
/// @param amountETHMin slippage of ETH
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
/// @return amountA amount of tokenA used
/// @return amountB amount of tokenB used
/// @return liquidity amount of liquidity minted
function addLiquidityETHAndStake(
address token,
bool stable,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
returns (
uint256 amountA,
uint256 amountB,
uint256 liquidity
);
/// @param tokenA the address of tokenA
/// @param tokenB the address of tokenB
/// @param stable if the pair is using the stable curve
/// @param liquidity amount of LP tokens to remove
/// @param amountAMin slippage of tokenA
/// @param amountBMin slippage of tokenB
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
/// @return amountA amount of tokenA used
/// @return amountB amount of tokenB used
function removeLiquidity(
address tokenA,
address tokenB,
bool stable,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB);
/// @param token address of the token
/// @param stable if the pair is using the stable curve
/// @param liquidity liquidity tokens to remove
/// @param amountTokenMin slippage of token
/// @param amountETHMin slippage of ETH
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
/// @return amountToken amount of token used
/// @return amountETH amount of ETH used
function removeLiquidityETH(
address token,
bool stable,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountToken, uint256 amountETH);
/// @param amountIn amount to send ideally
/// @param amountOutMin slippage of amount out
/// @param routes the hops the swap should take
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
/// @return amounts amounts returned
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
route[] calldata routes,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
/// @param routes the hops the swap should take
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
/// @return amounts amounts returned
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
route[] memory routes,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
/// @param amountOutMin slippage of token
/// @param routes the hops the swap should take
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
/// @return amounts amounts returned
function swapExactETHForTokens(
uint256 amountOutMin,
route[] calldata routes,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
/// @param amountOut amount of tokens to get out
/// @param amountInMax max amount of tokens to put in to achieve amountOut (slippage)
/// @param routes the hops the swap should take
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
/// @return amounts amounts returned
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
route[] calldata routes,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
/// @param amountIn amount of tokens to swap
/// @param amountOutMin slippage of token
/// @param routes the hops the swap should take
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
/// @return amounts amounts returned
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
route[] calldata routes,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
/// @param amountOut exact amount out or revert
/// @param routes the hops the swap should take
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
/// @return amounts amounts returned
function swapETHForExactTokens(
uint256 amountOut,
route[] calldata routes,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
/// @param amountIn token amount to swap
/// @param amountOutMin slippage of token
/// @param routes the hops the swap should take
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
route[] calldata routes,
address to,
uint256 deadline
) external;
/// @param amountOutMin slippage of token
/// @param routes the hops the swap should take
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
route[] calldata routes,
address to,
uint256 deadline
) external payable;
/// @param amountIn token amount to swap
/// @param amountOutMin slippage of token
/// @param routes the hops the swap should take
/// @param to the address the liquidity tokens should be minted to
/// @param deadline timestamp deadline
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
route[] calldata routes,
address to,
uint256 deadline
) external;
/// @notice **** REMOVE LIQUIDITY (supporting fee-on-transfer tokens)****
/// @param token address of the token
/// @param stable if the swap curve is stable
/// @param liquidity liquidity value (lp tokens)
/// @param amountTokenMin slippage of token
/// @param amountETHMin slippage of ETH
/// @param to address to send to
/// @param deadline timestamp deadline
/// @return amountToken amount of token received
/// @return amountETH amount of ETH received
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
bool stable,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountToken, uint256 amountETH);
}
interface IPairFactory {
function createPair(
address tokenA,
address tokenB,
bool stable
) external returns (address pair);
}
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(
address(this).balance >= amount,
"Address: insufficient balance"
);
(bool success, ) = recipient.call{value: amount}("");
require(
success,
"Address: unable to send value, recipient may have reverted"
);
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data)
internal
returns (bytes memory)
{
return
functionCallWithValue(
target,
data,
0,
"Address: low-level call failed"
);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return
functionCallWithValue(
target,
data,
value,
"Address: low-level call with value failed"
);
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(
address(this).balance >= value,
"Address: insufficient balance for call"
);
(bool success, bytes memory returndata) = target.call{value: value}(
data
);
return
verifyCallResultFromTarget(
target,
success,
returndata,
errorMessage
);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data)
internal
view
returns (bytes memory)
{
return
functionStaticCall(
target,
data,
"Address: low-level static call failed"
);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return
verifyCallResultFromTarget(
target,
success,
returndata,
errorMessage
);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data)
internal
returns (bytes memory)
{
return
functionDelegateCall(
target,
data,
"Address: low-level delegate call failed"
);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return
verifyCallResultFromTarget(
target,
success,
returndata,
errorMessage
);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage)
private
pure
{
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(
token,
abi.encodeWithSelector(token.transfer.selector, to, value)
);
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(
token,
abi.encodeWithSelector(token.transferFrom.selector, from, to, value)
);
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(
token,
abi.encodeWithSelector(token.approve.selector, spender, value)
);
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(
token,
abi.encodeWithSelector(
token.approve.selector,
spender,
newAllowance
)
);
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(
oldAllowance >= value,
"SafeERC20: decreased allowance below zero"
);
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(
token,
abi.encodeWithSelector(
token.approve.selector,
spender,
newAllowance
)
);
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(
nonceAfter == nonceBefore + 1,
"SafeERC20: permit did not succeed"
);
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(
data,
"SafeERC20: low-level call failed"
);
if (returndata.length > 0) {
// Return data is optional
require(
abi.decode(returndata, (bool)),
"SafeERC20: ERC20 operation did not succeed"
);
}
}
}
interface ISFOG is IERC20 {
function burn(address from, uint256 amount) external;
function mint(address to, uint256 amount) external;
}
contract SFOG is ISFOG, ERC20, Ownable {
uint256 private initialSupply;
uint256 public maxSupply;
address public uniswapPair;
IRouter public uniswapRouter;
using SafeMath for uint256;
using SafeERC20 for ERC20;
mapping(address => bool) private isController;
bool public tradingEnabled = false;
address public treasuryAddress;
uint256 public taxSellForMarketing = 30;
uint256 public taxBuyForMarketing = 30;
uint256 private _marketingReserves = 0;
uint256 private _numTokensSellToAddToETH = 0;
uint256 _decimals = 18;
uint256 public maxWalletAmount = 2_000 * 10**_decimals;
address public marketingWallet = 0x7D07e3c9A427a8222a13Fe4Cd8BaD4AEE65b109B;
mapping(address => bool) private _isExcludedFromFee;
bool inSwapAndLiquify;
constructor() ERC20("SFOG", "SFOG") {
IRouter _uniswapRouter = IRouter(
0x1D368773735ee1E678950B7A97bcA2CafB330CDc
);
uniswapRouter = _uniswapRouter;
// address _factory = _uniswapRouter.factory();
// uniswapPair = IPairFactory(_factory).createPair(
// address(this), // Token SFOG
// _uniswapRouter.WETH(), // Token WETH
// false // Stable = false
// );
_isExcludedFromFee[address(uniswapRouter)] = true;
_isExcludedFromFee[marketingWallet] = true;
_isExcludedFromFee[address(this)] = true;
_isExcludedFromFee[msg.sender] = true;
initialSupply = 300_000 * 10**_decimals;
maxSupply = 1_000_000 * 10**_decimals;
_numTokensSellToAddToETH = 50 * 10**_decimals;
treasuryAddress = msg.sender;
isController[msg.sender] = true;
_mint(msg.sender, initialSupply);
}
modifier lockTheSwap() {
inSwapAndLiquify = true;
_;
inSwapAndLiquify = false;
}
function mint(address to_, uint256 amount_)
external
override
onlyController
{
require(
totalSupply().add(amount_) <= maxSupply,
"Maximum supply reached"
);
_mint(to_, amount_);
}
function burn(address from_, uint256 amount_)
external
override
onlyController
{
_burn(from_, amount_);
}
event ControllerAdded(address newController);
function addController(address toAdd_) external onlyOwner {
isController[toAdd_] = true;
emit ControllerAdded(toAdd_);
}
event ControllerRemoved(address controllerRemoved);
function removeController(address toRemove_) external onlyOwner {
isController[toRemove_] = false;
emit ControllerRemoved(toRemove_);
}
modifier onlyController() {
require(isController[_msgSender()], "CallerNotController");
_;
}
function pause_trading() public onlyOwner {
tradingEnabled = false;
}
function enable_trading() public onlyOwner {
tradingEnabled = true;
}
function getPair() public view returns (address) {
return uniswapPair;
}
function _transfer(
address from,
address to,
uint256 amount
) internal override {
require(
tradingEnabled || _isExcludedFromFee[from],
"Transfer is disabled"
);
if ((from == uniswapPair || to == uniswapPair) && !inSwapAndLiquify) {
if (from != uniswapPair) {
uint256 balanceContract = balanceOf(address(this));
if (_marketingReserves >= _numTokensSellToAddToETH) {
_swapTokensForEth(balanceContract);
_marketingReserves = 0;
}
}
uint256 transferAmount;
if (_isExcludedFromFee[from] || _isExcludedFromFee[to]) {
transferAmount = amount;
} else {
if (from == uniswapPair) {
require(
(amount + balanceOf(to)) <= maxWalletAmount,
"ERC20: balance amount exceeded max wallet amount limit"
);
}
uint256 marketingShare = 0;
if (from == uniswapPair) {
marketingShare = ((amount * taxBuyForMarketing) / 100);
} else if (to == uniswapPair) {
marketingShare = ((amount * taxSellForMarketing) / 100);
}
transferAmount = amount - (marketingShare);
_marketingReserves += marketingShare;
super._transfer(from, address(this), marketingShare);
}
super._transfer(from, to, transferAmount);
} else {
super._transfer(from, to, amount);
}
}
function _swapTokensForEth(uint256 tokenAmount) private lockTheSwap {
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = uniswapRouter.WETH();
_approve(address(this), address(uniswapRouter), tokenAmount);
IRouter.route[] memory routes = new IRouter.route[](1);
routes[0] = IRouter.route({from: path[0], to: path[1], stable: false});
uniswapRouter.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
0,
routes,
marketingWallet,
block.timestamp + 2000
);
}
function changeTaxForMarketing(
uint256 _taxBuyForMarketing,
uint256 _taxSellForMarketing
) public onlyOwner returns (bool) {
require(
_taxBuyForMarketing <= 99 && _taxSellForMarketing <= 99,
"ERC20: total tax must not be greater than 100"
);
taxBuyForMarketing = _taxBuyForMarketing;
taxSellForMarketing = _taxSellForMarketing;
return true;
}
function changeNumSellAddToETH(uint256 _numSell)
public
onlyOwner
returns (bool)
{
_numTokensSellToAddToETH = _numSell;
return true;
}
function changeMarketingWallet(address _address)
public
onlyOwner
returns (bool)
{
marketingWallet = _address;
return true;
}
function changeLimitWallet(uint256 _maxWallet)
public
onlyOwner
returns (bool)
{
maxWalletAmount = _maxWallet;
return true;
}
function setIsExcludeFee(address[] memory _address, bool state)
public
onlyOwner
returns (bool)
{
for (uint256 i = 0; i < _address.length; i++) {
_isExcludedFromFee[_address[i]] = state;
}
return true;
}
function setPair(address _pair) public onlyOwner returns (bool) {
uniswapPair = _pair;
}
}