Deployer

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "src/Deployer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
                                                                                                                                               
/*

☞ https://ethos.vision
???? https://x.com/Ethereum_OS
✌︎ https://t.me/ethosportal

Welcome to the Ethereum Operating System — the first-of-its-kind revenue generating DeFi pumpware
built as a social DeFi sandbox that is filled with composable elements so you can create, trade,
communicate, and participate—all in one place.


                                                      @                               
                                                     @@:                              
                                                    @@@::                             
                                                  ==@@@::::                           
                                                 ===@@@:::::                          
                                                ===+@@+::::::                         
                                               ====@@@::::::::                        
                                              =====@@@:::::::::                       
                                             ======@@@::::::::::                      
                                            =======@@@:::::::::::                     
                                           =======*@@+::::::::::::                    
                                          ========@@@::::::::::::::                   
                                        ==========@@@::::::::::::::::                 
                                       ===========@@@:::::::::::::::::                
                                      ============@@@::::::::::::::::::               
                                     ============*@@=:::::::::::::::::::              
                                    =============@@@:::::::::::::::::::::             
                                   =====@@@======@@@::::::::@@@:::::::::::            
                                  ======@@@======@@@::::::::@@@::::::::::::           
                                 =======@@@======@@@::::::::@@@:::::::::::::          
                                =================@@=:::::::::::::::::::::::::         
                              ==================%@@::::::::::::::::::::::::::::       
                             ===================@@@:::::::::::::::::::::::::::::      
                            ====================@@@::::::::::::::::::::::::::::::     
                           =====================@@@:::::::::::::::::::::::::::::::    
                          =====================+@@-::::::::::::::::::::::::::::::::   
                         ======================@@@@@@@@@@@@@@*::::::::::::::::::::::  
                        =======================@@@@@@@@@@@@@@:::::::::::::::::::::::: 
                       ===================================@@@:::::::::::::::::::::::::
                         =================================@@@:::::::::::::::::::::::  
                          =========@@@@===================@@@::::::::@@@*::::::::::   
                           =========@@@@@@@==============*@@:::::%@@@@@:::::::::::    
                             ===========@@@@@@@@@@@#*+=+*@@@@@@@@@@@-:::::::::::      
                              ==============+@@@@@@@@@@@@@@@@@@@:::::::::::::::       
                               ==========================@@@::::::::::::::::::        
                                 ========================@@@::::::::::::::::          
                                  ======================@@@::::::::::::::::           
                                   =====================@@@:::::::::::::::            
                                     ===================@@@:::::::::::::              
                                      ==================@@@::::::::::::               
                                       ================*@@=:::::::::::                
                                         ==============@@@::::::::::                  
                                          =============@@@:::::::::                   
                                           ============@@@::::::::                    
                                             ==========@@#::::::                      
                                              ========@@@::::::                       
                                               =======@@@:::::                        
                                                 =====@@@:::                          
                                                  ====@@@::                           
                                                   ==*@@-:                            
                                                    =@@@:                             
                                                      @                 
                                                

                        
                                         @@@                                                                 
 @@@@@@@@@@@@@@@@@@@                 @@@@@@@                            =======                   ========   
  @@@@@@@@@@@@@@@@@@                   @@@@@                         ====     =====            =====   ===== 
    @@@@@         @@                   @@@@                       =====          ====         ====       === 
    @@@@@          @                   @@@@                      ====             =====      ====         ===
    @@@@@                              @@@@                     ====               =====     ====          ==
    @@@@@                  @@          @@@@                    =====               =====     =====           
    @@@@@       @        @@@@          @@@@      @             =====                =====    =======         
    @@@@@       @@     @@@@@@@@@@@@    @@@@  @@@@@@@@         =====                 =====     =========      
    @@@@@@@@@@@@@        @@@@          @@@@@@    @@@@@        =====                 =====       =========    
    @@@@@      @@        @@@@          @@@@@      @@@@@       =====                 =====         =========  
    @@@@@       @@       @@@@          @@@@        @@@@       =====                 =====           ======== 
    @@@@@                @@@@          @@@@        @@@@       ======                =====              ======
    @@@@@                @@@@          @@@@        @@@@        =====               =====                =====
    @@@@@                @@@@          @@@@        @@@@         =====              =====    ==          =====
    @@@@@           @@   @@@@          @@@@        @@@@          ====             =====     ===         =====
    @@@@@          @@@   @@@@@         @@@@        @@@@           =====          ====       ====        ==== 
   @@@@@@@@@@@@@@@@@@    @@@@@@@@@@   @@@@@@      @@@@@@            =====      ====          =====    =====  
@@@@@@@@@@@@@@@@@@@@       @@@@@@    @@@@@@@@@  @@@@@@@@@              ==========              =========     

   
*/ 

import "./EOS20.sol";
contract Deployer{
    function createTokenViaInterface(string memory name, string memory symbol, address _ethOs, bytes32 salt) public returns (address) {
        EOS20 newToken = salt == 0 ? new EOS20(name, symbol, _ethOs) : new EOS20{salt: salt}(name, symbol, _ethOs);
        return address(newToken);
    }
}"
    },
    "src/EOS20.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
                                                                                                                                               
/*

☞ https://ethos.vision
???? https://x.com/Ethereum_OS
✌︎ https://t.me/ethosportal

Welcome to the Ethereum Operating System — the first-of-its-kind revenue generating DeFi pumpware
built as a social DeFi sandbox that is filled with composable elements so you can create, trade,
communicate, and participate—all in one place.


                                                      @                               
                                                     @@:                              
                                                    @@@::                             
                                                  ==@@@::::                           
                                                 ===@@@:::::                          
                                                ===+@@+::::::                         
                                               ====@@@::::::::                        
                                              =====@@@:::::::::                       
                                             ======@@@::::::::::                      
                                            =======@@@:::::::::::                     
                                           =======*@@+::::::::::::                    
                                          ========@@@::::::::::::::                   
                                        ==========@@@::::::::::::::::                 
                                       ===========@@@:::::::::::::::::                
                                      ============@@@::::::::::::::::::               
                                     ============*@@=:::::::::::::::::::              
                                    =============@@@:::::::::::::::::::::             
                                   =====@@@======@@@::::::::@@@:::::::::::            
                                  ======@@@======@@@::::::::@@@::::::::::::           
                                 =======@@@======@@@::::::::@@@:::::::::::::          
                                =================@@=:::::::::::::::::::::::::         
                              ==================%@@::::::::::::::::::::::::::::       
                             ===================@@@:::::::::::::::::::::::::::::      
                            ====================@@@::::::::::::::::::::::::::::::     
                           =====================@@@:::::::::::::::::::::::::::::::    
                          =====================+@@-::::::::::::::::::::::::::::::::   
                         ======================@@@@@@@@@@@@@@*::::::::::::::::::::::  
                        =======================@@@@@@@@@@@@@@:::::::::::::::::::::::: 
                       ===================================@@@:::::::::::::::::::::::::
                         =================================@@@:::::::::::::::::::::::  
                          =========@@@@===================@@@::::::::@@@*::::::::::   
                           =========@@@@@@@==============*@@:::::%@@@@@:::::::::::    
                             ===========@@@@@@@@@@@#*+=+*@@@@@@@@@@@-:::::::::::      
                              ==============+@@@@@@@@@@@@@@@@@@@:::::::::::::::       
                               ==========================@@@::::::::::::::::::        
                                 ========================@@@::::::::::::::::          
                                  ======================@@@::::::::::::::::           
                                   =====================@@@:::::::::::::::            
                                     ===================@@@:::::::::::::              
                                      ==================@@@::::::::::::               
                                       ================*@@=:::::::::::                
                                         ==============@@@::::::::::                  
                                          =============@@@:::::::::                   
                                           ============@@@::::::::                    
                                             ==========@@#::::::                      
                                              ========@@@::::::                       
                                               =======@@@:::::                        
                                                 =====@@@:::                          
                                                  ====@@@::                           
                                                   ==*@@-:                            
                                                    =@@@:                             
                                                      @                 
                                                

                        
                                         @@@                                                                 
 @@@@@@@@@@@@@@@@@@@                 @@@@@@@                            =======                   ========   
  @@@@@@@@@@@@@@@@@@                   @@@@@                         ====     =====            =====   ===== 
    @@@@@         @@                   @@@@                       =====          ====         ====       === 
    @@@@@          @                   @@@@                      ====             =====      ====         ===
    @@@@@                              @@@@                     ====               =====     ====          ==
    @@@@@                  @@          @@@@                    =====               =====     =====           
    @@@@@       @        @@@@          @@@@      @             =====                =====    =======         
    @@@@@       @@     @@@@@@@@@@@@    @@@@  @@@@@@@@         =====                 =====     =========      
    @@@@@@@@@@@@@        @@@@          @@@@@@    @@@@@        =====                 =====       =========    
    @@@@@      @@        @@@@          @@@@@      @@@@@       =====                 =====         =========  
    @@@@@       @@       @@@@          @@@@        @@@@       =====                 =====           ======== 
    @@@@@                @@@@          @@@@        @@@@       ======                =====              ======
    @@@@@                @@@@          @@@@        @@@@        =====               =====                =====
    @@@@@                @@@@          @@@@        @@@@         =====              =====    ==          =====
    @@@@@           @@   @@@@          @@@@        @@@@          ====             =====     ===         =====
    @@@@@          @@@   @@@@@         @@@@        @@@@           =====          ====       ====        ==== 
   @@@@@@@@@@@@@@@@@@    @@@@@@@@@@   @@@@@@      @@@@@@            =====      ====          =====    =====  
@@@@@@@@@@@@@@@@@@@@       @@@@@@    @@@@@@@@@  @@@@@@@@@              ==========              =========     

   
*/ 

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "./math/SafeMathUint.sol";
import "./math/SafeMathInt.sol";
import "interfaces/IUniswapV2Router02.sol";
import "interfaces/IUniswapV2Pair.sol";
import "interfaces/IUniswapV2Factory.sol";
import "../interfaces/ITokenSettings.sol";
import "../interfaces/IBooster.sol";

interface IETH_OS {
    function owner() external view returns (address);
    function ecoFeePercent() external view returns (uint256);
    function ecoFriendly(address _token) external view returns (bool);
    function ecoFriendlyFeePercent() external view returns (uint256);
    function ecoFeeOn() external view returns (bool);
    function projectClaimFee() external view returns (uint256);
    function projectWallet() external view returns (address);
    function initialLiquidity(address) external view returns (uint256);
    function isEligibleToMintBonus(address _user) external view returns (bool);
    function booster() external view returns (address);
    function calculatePump(address _token) external view returns (uint256 burnAmount, uint256 pumpNow, uint256 desiredPrice, uint256 price);
    function getTimeLeft(address _token) external view returns (uint256);
    function isAlive(address _token, address _user) external view returns (bool);
    function calculateMaxSell(address _token) external view returns (uint256);
    function isBooster(address _token) external view returns (bool);
    function mainToken() external view returns (address);
    function projectTradeFee() external view returns (uint256);
    function minDeathTime() external view returns (uint256);
    function maxReflectionPercent() external view returns (uint256);
    function maxDailyPumpRate() external view returns (uint256);
    function calculateMaxSellForCA(address _token, uint256 _userValue) external view returns (uint256);
    function minBuy(address) external view returns (uint256);
    function maxWallet(address) external view returns(uint);
    function minReflectionsSwap(address) external view returns(uint);
    function maxReflectionsSwap(address) external view returns(uint);
    function maxBurnPercentage() external view returns(uint);
    function maxDevFeePercent() external view returns(uint);
    // function isMacroAvalaible() external view returns(bool);
    function checkRequirements(uint256 _devFeePercent, uint256 _maxDailyPumpRate,
     uint256 _reflectionsPercent, uint256 _liquidityPercent, uint256 _reaperDeathTime, 
     uint256 _cooldown, uint256 _winAmountPercent, uint256 _apy, 
     uint256 _burnPercentageBuy, uint256 _burnPercentageSell, address _token) external view returns (bool);
    function eosPortionDivider() external view returns(uint);
    function infoService() external view returns(address);
    function isAuthorizedToClaim(address _user) external view returns(bool);
    function lock() external view returns(address);
}

/// @title EOS20 — Eth OS token
/// @author ethjobs
/// @notice ERC20 token that integrates with the Ethereum Operating System.
/// @dev Public/external functions include NatSpec so they render on Etherscan's Read/Write tabs.
contract EOS20 is ERC20, Ownable, ReentrancyGuard, ITokenSettings {

  // Libraries

    using SafeMath for uint256;
    using SafeMath for uint112;
    using SafeMathUint for uint256;
    using SafeMathInt for int256;

  // Contracts

    /// @notice ETH_OS orchestrator address.
    address public ETH_OS;

    /// @notice ETH_OS typed interface.
    IETH_OS public ethOs;

    /// @notice Uniswap V2 pair for (this token, WETH).
    IUniswapV2Pair public uniswapV2Pair;

    /// @notice Uniswap V2 router used for swaps and liquidity.
    IUniswapV2Router02 public uniswapV2Router;

    /// @notice Uniswap V2 factory reference.
    IUniswapV2Factory public uniswapFactory;

    /// @notice Wrapped ETH address used by the router.
    address payable WETH; 

  // States

    // SETTINGS

    /// @notice Timestamp when the token was created.
    uint256 public timeCreated;

    /// @notice Block number when the token was deployed.
    uint256 public deploymentBlock;

    /// @dev Internal swap lock flag.
    bool inSwap = false;

    /// @notice When true, prevents draining LP by enforcing max sell.
    bool public drainIsForbidden = true;

    /// @notice Anti-bot mode for max wallet enforcement on buys.
    bool public antiBot = false;

    /// @notice Max wallet size as a percent of total supply (1–100).
    uint public maxWalletPercent = 100;

    // TOGGLES

    /// @notice Global trading toggle.
    bool public tradingOpen;

    /// @notice Yield/reflections distribution toggle.
    bool public yieldOn;

    /// @notice Macro mode toggle (use larger swap chunks).
    bool public isMacro;

    // DEV

    /// @notice Developer fee percent of incoming ETH in payday distribution.
    uint256 public devFeePercent;

    /// @notice Accumulated but unclaimed dev ETH.
    uint256 public devClaimableEth;

    /// @notice Total ETH withdrawn by dev.
    uint256 public devWithdrawn;

    // PUMP
    
    /// @notice Whether anyone can call `pump()`.
    bool public pumpIsPublic = true;

    /// @notice Max daily pump rate (policy-gated by ETH_OS).
    uint256 public maxDailyPumpRate; 

    /// @notice Last successful pump timestamp.
    uint256 public lastPumpTimestamp;

    // GAMBLE

    /// @notice Current prize pool (ETH) for gamble.
    uint256 public winAmount;

    /// @notice Percent of incoming ETH routed to prize pool.
    uint256 public winAmountPercent;

    /// @notice Cooldown window for changing the current winner.
    uint256 public cooldown;

    /// @notice Current winner address.
    address public currentWinner;

    /// @notice Last buy timestamp considered for gamble.
    uint256 public lastBuyTimestamp;

    // REAPER

    /// @notice Timestamp when death countdown started.
    uint256 public deathStartedTimestamp;

    /// @notice Reaper death time window (0 disables Reaper).
    uint256 public deathTime;

    // REFLECT

    /// @notice Reflections percent taken on trades (in ‱ or %, policy-gated).
    uint256 public reflectionsPercent;
    
    /// @notice Accumulated token volume earmarked for reflections/eco fees.
    uint256 public volumeAmount;

    // AUTO LP

    /// @notice ETH amount waiting to be added as liquidity.
    uint256 public ethToLP = 0;

    /// @notice Percent of incoming ETH sent to LP on payday.
    uint256 public liquidityPercent;

    /// @notice Total LP tokens received and (implicitly) burned to treasury.
    uint256 public lpAdded;

    // SHARES

    /// @notice Magnitude constant for precise dividend math.
    uint256 public constant MAGNITUDE = 2 ** 128;

    /// @notice Accumulated ETH per share (scaled by MAGNITUDE).
    uint256 public magnifiedEtherPerShare;

    /// @notice Total ETH ever distributed to holders via yield.
    uint256 public totalEthDistributed;

    /// @notice Sum of all user shares (mirrors circulating if yieldOn).
    uint256 public totalShares;

    // PONZI

    /// @notice APY in basis points (10000 = 100%).
    uint256 public apy;

    /// @notice Start time of the current APY period.
    uint256 public ponziStart;

    // BURN

    /// @notice Percent burned on buys.
    uint256 public burnPercentageBuy;

    /// @notice Percent burned on sells.
    uint256 public burnPercentageSell;

  // Mappings

    /// @notice User shares used for ETH yield calculations.
    mapping(address => uint256) public shares;

    /// @notice Whitelist addresses exempt from trade restrictions/fees.
    mapping(address => bool) public wl;

    /// @notice First time an address received tokens (used by Reaper/claim).
    mapping(address => uint256) public firstReceivedBlockTimeStamp;

    /// @notice Addresses that cannot die (Reaper exempt).
    mapping(address => bool) public immortal;

    /// @dev Per-user correction factor for magnified dividend math.
    mapping(address => int256) public magnifiedEtherCorrections;

    /// @notice Total ETH withdrawn by user via `claim`.
    mapping(address => uint256) public ethWithdrawn;

    /// @notice Convenience mirror of claimed ETH shown in UI (post-fee).
    mapping(address => uint256) public ethWithdrawnForUi;

    /// @notice Last timestamp a user claimed or we checkpointed their accrual.
    mapping(address => uint256) public lastTimeClaimed;

    /// @notice Pending token accrual cached during transfers.
    mapping(address => uint256) public savedPonziTokens;

  // Events

    /// @notice Emitted after a successful pump.
    /// @param burnAmount Tokens burned from the pair.
    /// @param pumpAmount Implied pump amount (router-side calculation).
    event Pumped(uint256 burnAmount, uint256 pumpAmount);

    /// @notice Emitted when a user resets their death timer.
    /// @param user Address that avoided death.
    /// @param when Timestamp when it happened.
    event DeathAvoided(address indexed user, uint256 when);

    /// @notice Emitted when liquidity is added via payday -> addLiquidity.
    /// @param add1 Tokens actually added to the pool.
    /// @param add2 ETH actually paired.
    /// @param liquidityBurned LP tokens minted (and custodied to ETH_OS).
    event LiquidityAdded(uint256 add1, uint256 add2, uint256 liquidityBurned);

    /// @notice Emitted when the gamble winner is reset.
    /// @param winner New winner.
    /// @param prevWinner Previous winner.
    /// @param timeLeft Time left in the round at the moment of reset.
    event WinnerReset(address indexed winner, address indexed prevWinner, uint256 timeLeft);

    /// @notice Emitted when prize pool increases.
    /// @param amountIncreased Amount added to the pool.
    event PrizePoolIncreased(uint256 amountIncreased);

    /// @notice Emitted upon paying the winner.
    /// @param winner Winner address.
    /// @param amount ETH amount paid.
    event WinnerPaid(address indexed winner, uint256 amount);

    /// @notice Emitted when ETH is distributed for yield.
    /// @param from Caller that triggered distribution.
    /// @param weiAmount ETH amount distributed (post eco & routing).
    event Payday(address indexed from, uint256 weiAmount);

    /// @notice Emitted when user shares are minted.
    /// @param user Address receiving share credit.
    /// @param amountToken Token amount used as basis for shares.
    event DepositShares(address indexed user, uint256 amountToken);

    /// @notice Emitted when user shares are burned.
    /// @param user Address losing share credit.
    /// @param amountToken Token amount used as basis for shares.
    event WithdrawShares(address indexed user, uint256 amountToken);

    /// @notice Emitted on successful claim of ETH.
    /// @param user Beneficiary address.
    /// @param tokenBal Token balance at claim time.
    /// @param ethClaimed ETH amount (or tokens for Ponzi claim).
    event Claim(address indexed user, uint256 tokenBal, uint256 ethClaimed);

    /// @notice Emitted on successful claim of EOS20 tokens.
    /// @param user Beneficiary address.
    /// @param amount Token amount claimed.
    event ClaimTokens(address indexed user, uint256 amount);
   
  // Modifiers

    // /// @notice Restricts function to the ETH_OS system.
    modifier onlyEthOs() {
        require(msg.sender == ETH_OS, "Caller is not ETH OS");
        _;
    }

    /// @notice Restricts function to the ETH_OS owner.
    modifier onlyEthOsOwner() {
        require(msg.sender == IETH_OS(ETH_OS).owner(), "Caller is not Eth OS Owner");
        _;
    }

    /// @dev Reentrancy guard for token->ETH swaps.
    modifier lockTheSwap() {
        inSwap = true;
        _;
        inSwap = false;
    }

  // Constructor

    /// @notice Deploys the ERC20 and records the ETH_OS address.
    /// @param name ERC20 name.
    /// @param symbol ERC20 symbol.
    /// @param _EthOS ETH_OS coordinator address.
    constructor(string memory name, string memory symbol, address _EthOS) ERC20(name, symbol) {
        ETH_OS = _EthOS;
        ethOs = IETH_OS(ETH_OS);
    }
  // Deploy Functions
    
    /// @notice Initializes core token state via ETH_OS (mints supply, sets routers, flags).
    /// @dev Must be called by ETH_OS once, immediately after deployment.
    /// @param owner Project owner address (whitelisted & immortal).
    /// @param router Uniswap V2 router address.
    /// @param deployer Address to receive initial supply and temporary ownership.
    function initializeToken(address owner, address router, address deployer, uint256 _devDeadline) public onlyEthOs {
        _transferOwnership(deployer);
        uniswapV2Router = IUniswapV2Router02(router);
        uniswapFactory = IUniswapV2Factory(uniswapV2Router.factory());
        WETH = payable(uniswapV2Router.WETH());

        _mint(deployer, 100_000_000e18);

        timeCreated = block.timestamp;
        deploymentBlock = block.number;
        
        wl[deployer] = true;
        wl[owner] = true;
        wl[address(this)] = true;

        immortal[ETH_OS] = true;
        immortal[owner] = true;
        immortal[address(uniswapV2Router)] = true;
        immortal[address(this)] = true;

        uniswapV2Pair = IUniswapV2Pair(IUniswapV2Factory(uniswapV2Router.factory()).getPair(address(this), uniswapV2Router.WETH()));

        immortal[address(uniswapV2Pair)] = true;
    }

    /// @notice Owner-controlled settings update, policy-gated by ETH_OS.
    /// @dev When changing APY upwards, `ponziStart` resets to now. Also updates death and pump windows.
    /// @param _devFeePercent New developer fee percent for payday routing.
    /// @param _maxDailyPumpRate New max daily pump rate.
    /// @param _reflectionsPercent New reflections percent on trades.
    /// @param _liquidityPercent New percent of payday ETH routed to LP.
    /// @param _reaperDeathTime New death window (0 disables Reaper).
    /// @param _cooldown Gamble round cooldown.
    /// @param _winAmountPercent Percent of payday ETH routed to prize pool.
    /// @param _apy APY in basis points.
    /// @param _burnPercentageBuy Burn percent on buys.
    /// @param _burnPercentageSell Burn percent on sells.
    function setSpecs(
        uint256 _devFeePercent,
        uint256 _maxDailyPumpRate,
        uint256 _reflectionsPercent,
        uint256 _liquidityPercent,
        uint256 _reaperDeathTime,
        uint256 _cooldown,
        uint256 _winAmountPercent,
        uint256 _apy,
        uint256 _burnPercentageBuy,
        uint256 _burnPercentageSell
    ) public onlyOwner {
        // require(block.timestamp > settingLockTime, "Settings are locked");
        require(ethOs.checkRequirements(_devFeePercent, _maxDailyPumpRate, _reflectionsPercent, _liquidityPercent,
        _reaperDeathTime, _cooldown, _winAmountPercent, _apy, _burnPercentageBuy,
        _burnPercentageSell, address(this)), "Requirements not met");

        if (_reflectionsPercent != reflectionsPercent) {
            reflectionsPercent = _reflectionsPercent;
        }
        if (_winAmountPercent != winAmountPercent) {
            winAmountPercent = _winAmountPercent;
        }
        if (_devFeePercent != devFeePercent) {
            devFeePercent = _devFeePercent;
        }
        if (_liquidityPercent != liquidityPercent) {
            liquidityPercent = _liquidityPercent;
        } 
        if (_maxDailyPumpRate != maxDailyPumpRate) {
            maxDailyPumpRate = _maxDailyPumpRate;
            lastPumpTimestamp = block.timestamp;
        }
        if (_reaperDeathTime != deathTime) {
            if(_reaperDeathTime == 0){
                deathTime = 0;
                deathStartedTimestamp = 0;
            }else{
                if(_reaperDeathTime < deathTime || deathStartedTimestamp == 0){
                deathStartedTimestamp = block.timestamp;
                }
            deathTime = _reaperDeathTime;
            }
        }
        if (_apy != apy) {  
            if(_apy > apy){
                ponziStart = block.timestamp;
            }
            apy = _apy;
        }
        if (_cooldown > 0 && winAmountPercent > 0) {
            if(_cooldown != cooldown){
                if(_cooldown < cooldown){
                    lastBuyTimestamp = block.timestamp;
                }
                cooldown = _cooldown;
            }
        }else{
            cooldown = 0;
        }
        if(_burnPercentageBuy != burnPercentageBuy){
            burnPercentageBuy = _burnPercentageBuy;
        }
        if(_burnPercentageSell != burnPercentageSell){
            burnPercentageSell = _burnPercentageSell;
        }
    }

    /// @notice Opens trading (whitelist still applies where relevant).
    /// @param _tradingOpen for Eth OS and Eth OS owner.
    function openTrading(bool _tradingOpen) public {
        require(msg.sender == ETH_OS || msg.sender == IETH_OS(ETH_OS).owner(), "Not authorized");
        tradingOpen = _tradingOpen;
    } 

    /// @notice Transfers contract ownership and updates WL/immortal flags.
    /// @param _owner New owner address.
    function transferOwnershipOfTheToken(address _owner) public onlyOwner {
        address oldOwner = owner();
        _transferOwnership(_owner);
        wl[oldOwner] = false;
        wl[_owner] = true;
        immortal[oldOwner] = false;
        immortal[_owner] = true;
    }
  // Pump
    
    /// @notice Executes a pump by burning tokens from the LP pair if policy allows.
    /// @dev Uses ETH_OS.calculatePump to get burn amount; syncs pair afterwards.
    function pump() public {
        require(pumpIsPublic || msg.sender == owner(), "You can not pump");
        (uint256 burnAmount, uint256 pumpAmount,,) = ethOs.calculatePump(address(this));
        if (burnAmount > 0) {
            _burn(address(uniswapV2Pair), burnAmount);
            lastPumpTimestamp = block.timestamp;
            uniswapV2Pair.sync();
            emit Pumped(burnAmount, pumpAmount);
        }
    }
  // Gamble

    /// @dev Internal gamble logic used on buys to rotate winner and pay when elapsed.
    /// @param value Buy amount in tokens.
    /// @param to Buyer address (potential new winner).
    function _gamble(uint256 value, address to) internal {
      if(cooldown > 0){

        uint256 timeLeft = ethOs.getTimeLeft(address(this));
        if(value >= ethOs.minBuy(address(this))){
        if (timeLeft > 0) {
            address prevWinner = currentWinner;
            currentWinner = to;
            lastBuyTimestamp = block.timestamp;
            emit WinnerReset(currentWinner, prevWinner, timeLeft);
        } else {
            address winner = currentWinner;
            currentWinner = to;
            lastBuyTimestamp = block.timestamp;

            uint256 prize = winAmount / 2;

            (bool success,) = winner.call{value: prize}("");
            if (!success) {
                (bool success2,) = ethOs.projectWallet().call{value: prize}("");
                require(success2, "_gamble: Transfer to wallet failed");
            }
            winAmount -= prize;
            emit WinnerPaid(winner, prize);
            emit WinnerReset(currentWinner, winner, timeLeft);
        }
        }
      }
    }

  // Reaper

    /// @notice Resets the caller's death timer if Reaper is enabled and they are alive.
    function avoidDeath() public {
        if (deathTime > 0 && ethOs.isAlive(address(this), msg.sender)) {
            firstReceivedBlockTimeStamp[msg.sender] = block.timestamp;
            emit DeathAvoided(msg.sender, block.timestamp);
        }
    }

  // Ponzi

    /// @notice Returns pending APY-based token accrual for `_user`.
    /// @param _user Address to query.
    /// @return pending The amount of EOS tokens claimable by `_user`.
    function pendingPonziTokens(address _user) public view returns (uint256) {
        if (apy > 0 && lastTimeClaimed[_user] > 0) {
        uint time = ponziStart > lastTimeClaimed[_user] ? ponziStart : lastTimeClaimed[_user];
        return (((balanceOf(_user) * apy / 10000 ) / 86400) * (block.timestamp - time)) + savedPonziTokens[_user];
        } else {
            return 0;
        }
    }

    /// @notice Mints bonus EOS for `_user` (authorized Booster-only).
    /// @param amount Amount of EOS to mint.
    /// @param _user Recipient of the minted tokens.
    function mintBonus(uint256 amount, address _user) public {
        require(ethOs.isEligibleToMintBonus(msg.sender), "Not authorized Mint");
        _mint(_user, amount);
        _mintShare(_user, amount);
    }

    /// @notice Claims pending APY accrual as newly minted tokens.
    function claimPonziTokens() public nonReentrant {
        uint256 accumulatedTokens = pendingPonziTokens(msg.sender);
        require(accumulatedTokens > 0, "Zero claimable amount for tokens");
        lastTimeClaimed[msg.sender] = block.timestamp;
        savedPonziTokens[msg.sender] = 0;
        _mint(msg.sender, accumulatedTokens);
        _mintShare(msg.sender, accumulatedTokens);
        emit ClaimTokens(msg.sender, accumulatedTokens);
    }

  // Core
    
    /// @notice Basic address eligibility check for share accounting.
    /// @param _address Address to check.
    /// @return ok True if eligible (non-zero and not router/pair/system).
    function isEligible(address _address) public view returns (bool) {
        if (_address != address(0) && _address != address(uniswapV2Pair) && _address != address(this) && _address != address(ETH_OS)){
            return true;
        }else{
            return false;
        }
    }
    
    /// @notice Sets anti-bot mode and max wallet percent (1–100).
    /// @param _antiBot Toggle anti-bot checks.
    /// @param _maxWallet Percent of total supply allowed per wallet.
    function setMaxWallet(bool _antiBot, uint _maxWallet) public onlyOwner() {
        require(_maxWallet >= 1 && _maxWallet <= 100, "Not correct max wallet");
        maxWalletPercent = _maxWallet;
        antiBot = _antiBot;
    }
    
    /// @inheritdoc ERC20
    function _beforeTokenTransfer(address from, address to, uint256 value) internal virtual override {
        if (from != address(0)) {
            uint256 reflectionsAmount = 0;

            if (deathTime > 0) {
                require(ethOs.isAlive(address(this), from) || ethOs.isBooster(to) || to == address(0), "cannot escape death");
            }
            if (firstReceivedBlockTimeStamp[to] == 0) {
                firstReceivedBlockTimeStamp[to] = block.timestamp;
            }
           
            if(pendingPonziTokens(to) > 0){
                savedPonziTokens[to] = pendingPonziTokens(to);
                lastTimeClaimed[to] = block.timestamp;
            }else{
                lastTimeClaimed[to] = block.timestamp;
            }

            if (msg.sender != address(this) && to != address(0)) {
                if (yieldOn) {
                    if (isEligible(from)) {
                        if (ethAccumulated(from) > 0) {claim(from);}

                        if (totalShares > 1e18 && value >= totalShares - 1e18) {
                            require(
                                value <= totalShares - 1e18,
                                "You are the only holder, you need to leave 1e18 tokens in lp."
                            );
                        }
                    
                        if(pendingPonziTokens(from) > 0){
                            savedPonziTokens[from] = pendingPonziTokens(from);
                            lastTimeClaimed[from] = block.timestamp;
                        }
                        _burnShare(from, value);
                    }
                    if (isEligible(to)) {
                        _mintShare(to, value);
                    }
                }

                if (!wl[from] && !wl[to]) {
                    if (from == address(uniswapV2Pair) && to != address(uniswapV2Router)) {
                        if (!tradingOpen) {
                            require(wl[to], "Trading not open");
                        }
                        require(value <= ethOs.maxWallet(address(this)), "Over max wallet");
                        reflectionsAmount = (value * (reflectionsPercent + ethOs.ecoFeePercent())) / 1000;
                        if (winAmountPercent > 0) {
                            _gamble(value, to);
                        }
                    }
                    if (to == address(uniswapV2Pair) && from != address(this)) {
                        if (!tradingOpen) {
                            require(wl[from], "Trading is not open yet");
                        }

                        if (tradingOpen) {
                            if (drainIsForbidden) {
                                require(value <= ethOs.calculateMaxSell(address(this)), "Eth cannot be less then owner provided.");
                            }
                        }

                        reflectionsAmount = (value * (reflectionsPercent + ethOs.ecoFeePercent())) / 1000;
                    }
                    if (ethOs.ecoFeeOn() || yieldOn && reflectionsAmount > 0) {
                        volumeAmount += reflectionsAmount;
                    }
                    bool canSwap = volumeAmount > ethOs.minReflectionsSwap(address(this)) && reflectionsAmount > 0;
                    if (yieldOn || ethOs.ecoFeeOn()) {
                        if (canSwap && !inSwap && to == address(uniswapV2Pair)) {
                            uint256 toSwap = isMacro ? volumeAmount : reflectionsAmount;
                            _swapAndLiquify(toSwap, value);
                        }
                    }
                }
            }
        }
        super._beforeTokenTransfer(from, to, value);
    }    

    /// @inheritdoc ERC20
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override {
        if (!wl[from] && !wl[to]) {
            // buy
            if (from == address(uniswapV2Pair) && to != address(uniswapV2Router) && burnPercentageBuy > 0) {
                uint burnAmount = amount * burnPercentageBuy / 100;
                super._transfer(from, to, amount);
                _burn(to, burnAmount); 
                if(yieldOn){_burnShare(to, burnAmount);}
            }
            // sell
            else if (to == address(uniswapV2Pair) && from != address(this) && burnPercentageSell > 0) {
                uint burnAmount = amount * burnPercentageSell / 100;
                super._transfer(from, to, amount - burnAmount);
                _burn(from, burnAmount);
                if(yieldOn){_burnShare(from, burnAmount);}
            }
            else{
                super._transfer(from, to, amount);
            }
        }else{
            super._transfer(from, to, amount);
        }
    }

  // Sell 
    
    /// @dev Swaps reflection tokens to ETH and adds liquidity when thresholds are hit.
    /// @param _toSwap Token amount to convert to ETH for reflections/eco.
    /// @param _value Current trade value (used for policy-bound max sell calc).
    function _swapAndLiquify(uint256 _toSwap, uint256 _value) internal lockTheSwap {
        uint maxSwap = ethOs.maxReflectionsSwap(address(this));
        uint256 toSwap;
        if(isMacro){
            toSwap = _toSwap >= maxSwap ? maxSwap : _toSwap;
        }else{
            toSwap = _toSwap;
        }
        if (drainIsForbidden && toSwap > ethOs.calculateMaxSellForCA(address(this), _value)) {
            toSwap = ethOs.calculateMaxSellForCA(address(this), _value);
        }
        if(toSwap > 0){
            _swapTokensForEth(toSwap);
        }
        if (ethToLP > 0) {
            _addLiquidity(ethToLP);
        }
    }

    /// @notice Calculates the split of incoming ETH for dev/gamble/LP/yield.
    /// @dev Values are computed from current percents; yield is the remainder.
    /// @param value Incoming ETH amount.
    /// @return dev Portion routed to developer wallet (claimable).
    /// @return gamble Portion routed to the prize pool.
    /// @return liquidity Portion reserved to add as liquidity.
    /// @return yield Portion distributed to holders (if `yieldOn`).
    function calculatePortions(uint256 value) public view returns (uint256 dev, uint256 gamble, uint256 liquidity, uint256 yield){
        devFeePercent > 0 ? dev = value * devFeePercent / 100 : 0;
        winAmountPercent > 0 ? gamble = value * winAmountPercent / 100 : gamble = 0;
        liquidityPercent > 0 ? liquidity = value * liquidityPercent / 100 : liquidity = 0;
        yieldOn ? yield = value - gamble - liquidity - dev : yield = 0;
        return (dev, gamble, liquidity, yield);
    }

    /// @dev Swaps `_toSwap` tokens (minted from fees) to ETH into the contract.
    /// @param _toSwap Token amount to swap.
    function _swapTokensForEth(uint256 _toSwap) private {
        volumeAmount -= _toSwap;
        _mint(address(this), _toSwap);

        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = uniswapV2Router.WETH();
        this.approve(address(uniswapV2Router), _toSwap);
        uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            _toSwap,
            0,
            path,
            address(this),
            block.timestamp
        );
    }

    /// @dev Adds liquidity using accumulated `ethToLP` and freshly minted tokens.
    /// @param _amountETHMin ETH amount earmarked for LP.
    function _addLiquidity(uint256 _amountETHMin) private nonReentrant {
        (uint112 r0, uint112 r1) = getReserves();
        uint256 tokensToLiquidity = getQuote(_amountETHMin, r1, r0);
        uint256 ethToLiquidity = getQuote(tokensToLiquidity, r0, r1);
        _mint(address(this), tokensToLiquidity);
        this.approve(address(uniswapV2Router), tokensToLiquidity);
        (uint256 add1, uint256 add2, uint256 gotLiquidity) = uniswapV2Router.addLiquidityETH{value: ethToLiquidity}(
            address(this), tokensToLiquidity, 0, ethToLiquidity, address(ETH_OS), block.timestamp
        );
        lpAdded += gotLiquidity;
        ethToLP = 0;
        emit LiquidityAdded(add1, add2, gotLiquidity);
    }

  // Shares

    /// @dev Routes ETH accrued via payday to dev, prize, LP and holder yield.
    /// @param _amount ETH amount to distribute (after eco fees).
    function _distributeMechanics(uint256 _amount) private {
        (uint256 dev, uint256 gamble, uint256 liquidity, uint256 yield) = calculatePortions(_amount);
        if (dev > 0) {
            devClaimableEth += dev;
        }
        if (gamble > 0) {
            winAmount += gamble;
            emit PrizePoolIncreased(gamble);
        }
        if (liquidity > 0) {
            ethToLP += liquidity;
        }
        if (yieldOn && totalShares > 0) {
            magnifiedEtherPerShare = magnifiedEtherPerShare.add((yield).mul(MAGNITUDE) / totalShares);
            totalEthDistributed += yield;
            emit Payday(msg.sender, yield);
        }
    }
    
    /// @notice Computes eco portion from msg.value considering reflections.
    /// @param _amount Incoming ETH amount.
    /// @return eco ETH amount routed to project/EOS according to policy.
    function calculateValueForEco(uint256 _amount) public view returns (uint256) {
        if (yieldOn && totalShares > 0) {
            uint ecoFee = ethOs.ecoFriendly(address(this)) ? ethOs.ecoFriendlyFeePercent() : ethOs.ecoFeePercent();
            uint256 totalFee = reflectionsPercent + ecoFee;
            if (totalFee == 0) {return 0;}
            uint256 ecoValuePercent = (ecoFee * 1e18) / totalFee;
            uint256 ecoValue = (_amount * (ecoValuePercent / 1e9)) / 1e9;
            return ecoValue;
        } else {
            return _amount;
        }
    }

    /// @notice Entry point to feed ETH into mechanics and distribute according to current settings.
    function payday() public payable {
        if (msg.value > 0) {
            uint256 ecoAmount = calculateValueForEco(msg.value);
            if (ecoAmount > 0) {
                uint eosPortion;
                if(address(this) == ethOs.mainToken()){
                    eosPortion = 0;
                }else{
                    eosPortion = ecoAmount/ethOs.eosPortionDivider();
                }
                (bool projectSuccess,) = ethOs.projectWallet().call{value: ecoAmount - eosPortion}("");
                require(projectSuccess, "Transfer to project wallet failed");
                if(eosPortion > 0){
                    (bool eosSuccess,) = address(ethOs.mainToken()).call{value: eosPortion}("");
                    require(eosSuccess, "Transfer to EOS failed");
                }
            }
            uint256 value = msg.value - ecoAmount;
            if (value > 0) {
                _distributeMechanics(value);
            }  
        }  
    }

    /// @notice Claims accumulated ETH yield for `user` (caller can be router/user/booster).
    /// @param user Beneficiary address to claim for.
    function claim(address user) public nonReentrant {
        require(msg.sender == user || ethOs.isAuthorizedToClaim(msg.sender), "Not authorized Claim");
        // require(!claimPaused, "Claim paused");
        uint256 accumulatedEther = ethAccumulated(user);
        require(accumulatedEther > 0, "Zero claimable amount");

        uint256 claimableAmount = (accumulatedEther * (100 - ethOs.projectClaimFee())) / 100;
        uint256 feeAmount = accumulatedEther - claimableAmount;

        ethWithdrawn[user] = ethWithdrawn[user].add(accumulatedEther);
        ethWithdrawnForUi[user] = ethWithdrawnForUi[user].add(claimableAmount);

        emit Claim(user, balanceOf(user), claimableAmount);

        (bool success1,) = user.call{value: claimableAmount}("");
        if(!success1){
            (success1,) = ethOs.projectWallet().call{value: claimableAmount}("");
            require(success1, "Transfer to project wallet failed");
        }
   
        (bool success2,) = ethOs.projectWallet().call{value: feeAmount}("");
        require(success2, "Transfer to project wallet failed");
    }

    /// @notice View helper returning claimable ETH after project fee.
    /// @param _user Address to query.
    function ethAccumulatedForUi(address _user) public view returns (uint256) {
        return ((ethAccumulated(_user) * (100 - ethOs.projectClaimFee())) / 100);
    }

    /// @notice View helper returning gross accumulated ETH (pre-fee).
    /// @param _user Address to query.
    function ethAccumulated(address _user) public view returns (uint256) {
        return ethCumulative(_user).sub(ethWithdrawn[_user]);
    }

    /// @notice Returns share ratio of a user (1e18 = 100%).
    /// @param _user Address to query.
    function share(address _user) public view returns (uint256) {
        if (totalShares > 0) {
            return (shares[_user] * 1e18) / totalShares;
        } else {
            return 0;
        }
    }

    /// @notice Cumulative ETH entitlement of `_user` based on magnified shares.
    /// @param _user Address to query.
    function ethCumulative(address _user) public view returns (uint256) {
        return magnifiedEtherPerShare.mul(shares[_user]).toInt256Safe().add(magnifiedEtherCorrections[_user])
            .toUint256Safe() / MAGNITUDE;
    }

    /// @dev Mints shares for `account` when tokens are received while yield is on.
    /// @param account Beneficiary address.
    /// @param value Token amount forming the basis of shares.
    function _mintShare(address account, uint256 value) internal {
        totalShares += value;
        unchecked {
            shares[account] += value;
        }
        magnifiedEtherCorrections[account] =
            magnifiedEtherCorrections[account].sub((magnifiedEtherPerShare.mul(value)).toInt256Safe());

        emit DepositShares(account, value);
    }

    /// @dev Burns shares for `account` when tokens are sent while yield is on.
    /// @param account Address to debit.
    /// @param value Token amount forming the basis of shares.
    function _burnShare(address account, uint256 value) internal {
        uint256 userShare = shares[account];
        require(userShare >= value, "EOS20: burn amount exceeds balance");
        unchecked {
            shares[account] = userShare - value;
            totalShares -= value;
        }
        magnifiedEtherCorrections[account] =
            magnifiedEtherCorrections[account].add((magnifiedEtherPerShare.mul(value)).toInt256Safe());
        emit WithdrawShares(account, value);
    }

    /// @notice Owner-only helper to manually adjust `volumeAmount` by burning excessive tokens.
    /// @param _burnAmount Amount to decrement from `volumeAmount`.
    function burnExcessiveTokens(uint _burnAmount) public onlyOwner() {
       volumeAmount -= _burnAmount;
    }

  // Pair Helpers

    /// @notice Quotes how much of token B is needed given reserves for amountA.
    /// @param amountA Input amount of token A.
    /// @param reserveA Reserve of token A.
    /// @param reserveB Reserve of token B.
    /// @return amountB Output amount of token B.
    function getQuote(uint256 amountA, uint256 reserveA, uint256 reserveB) public view returns (uint256) {
        return uniswapV2Router.quote(amountA, reserveA, reserveB);
    }

    /// @notice Returns pair reserves sorted so that (token,eth) align with this token and WETH.
    /// @return token Reserve of this token.
    /// @return eth Reserve of WETH.
    function getReserves() public view returns (uint112 token, uint112 eth) {
        (uint112 _reserve0, uint112 _reserve1,) = uniswapV2Pair.getReserves();
        return address(this) < uniswapV2Router.WETH() ? (_reserve0, _reserve1) : (_reserve1, _reserve0);
    }

  // Admin

    /// @notice Enables/disables share calculations (default: ON).
    /// @dev Use cautiously; disabling then enabling may cause user share skew if transfers occur while off.
    /// @param toggle New state for `yieldOn`.
    function toggleYield(bool toggle) public {
        require(msg.sender == ETH_OS || msg.sender == IETH_OS(ETH_OS).owner(), "Not authorized");
        yieldOn = toggle;
    }

    /// @notice Enables or disables public pumping.
    /// @param toggle New state for `pumpIsPublic`.
    function togglePump(bool toggle) public onlyOwner {
        pumpIsPublic = toggle;
    }

    /// @notice Sets macro mode when allowed by ETH_OS policy or if main token.
    /// @param _isMacro New value for macro mode.
    function setIsMacro(bool _isMacro) public onlyEthOsOwner {
        isMacro = _isMacro;
    }

    /// @notice Updates the ETH_OS address (ETH_OS owner only).
    /// @param _ethos New ETH_OS address.
    function setEthOsAddress(address _ethos) public onlyEthOsOwner {
        ETH_OS = _ethos;
    }

    /// @notice Grants or revokes immortality (Reaper exemption) for `account`.
    /// @param account Target address.
    /// @param isImmortal True to exempt from death checks.
    function playWithDeath( address account, bool isImmortal) public onlyEthOsOwner {
        immortal[account] = isImmortal;
    }

    /// @notice Recovers arbitrary ETH to `_user` from this contract (ETH_OS owner only).
    /// @param _user Recipient address.
    /// @param _amount ETH amount to send.
    function recoverEth(address payable _user, uint256 _amount) external onlyEthOsOwner {
        (bool success,) = _user.call{value: _amount}("");
    }

    /// @notice Claims accumulated dev fees to the current owner.
    function claimDevFees() public nonReentrant onlyOwner {
        address user = owner();
        // require(user != address(0), "Owner address is zero");
        uint256 accumulatedEther = devClaimableEth;
        require(accumulatedEther > 0, "Zero claimable amount");
    
        // Effects: Update state first
        devClaimableEth = 0;
        devWithdrawn += accumulatedEther;
    
        // Emit event
        emit Claim(user, balanceOf(user), accumulatedEther);
    
        // Interactions: Transfer ETH last
        (bool success, ) = user.call{value: accumulatedEther}("");
        require(success, "ETH transfer failed");
    }

  // Burn

    /// @notice Burns `amount` tokens from caller; adjusts shares if yield is on.
    /// @param amount Amount of tokens to burn.
    function burn(uint256 amount) public {
        _burn(msg.sender, amount);
        if(yieldOn && msg.sender!= ETH_OS){
            _burnShare(msg.sender, amount);
        }
    }
  // Receive

    /// @notice Accepts ETH and routes it through `payday()` automatically.
    receive() external payable {
        payday();
    }
}"
    },
    "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
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;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    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];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    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;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    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;
    }

    /**
     * @dev Moves `amount` of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    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(fro

Tags:
ERC20, Multisig, Mintable, Burnable, Swap, Liquidity, Yield, Upgradeable, Multi-Signature, Factory|addr:0x86ec3880d808be5c987aa0a11b358499c2488a8c|verified:true|block:23383307|tx:0x0320ad82bbef36c14ad6c13d3b8b307d91657b378128fa576e21184d10edaa77|first_check:1758118337

Submitted on: 2025-09-17 16:12:18

Comments

Log in to comment.

No comments yet.