// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; /* ============================================================ Golden Egg / GGE · BEP20 - 买卖各 1% 税:0.5% → 团队钱包(代币形式,立即到账) 0.5% → 留在本合约,任何人可调用 swapTaxToBnb() 换成 BNB 进分红池 - 分红池就是本合约本身:无 Owner、无提款函数,BNB 只能靠持有人 claim() 领走 - 分红规则: · 持币 ≥ 10,000,000 GGE 才有资格 · 按持币比例累计(进池那一刻的持仓决定份额,事后加仓不追补) · 累计可领 ≥ 0.01 BNB 才能领,避免 gas 吃掉收益 ============================================================ */ interface IBEP20 { function balanceOf(address) external view returns (uint256); function transfer(address, uint256) external returns (bool); } interface IPancakeRouter { function swapExactTokensForETHSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; } contract NiuJinDanToken { string public name = "Golden Egg"; string public symbol = "GGE"; uint8 public constant decimals = 18; uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /* ---------- 税 ---------- */ uint256 public constant TAX_BPS = 100; // 1% uint256 public constant TEAM_SHARE_BPS = 50; // 税里一半给团队 address public immutable teamWallet; address public launchContract; // 打新合约(免税收发奖励用),仅 deployer 可设一次 mapping(address => bool) public taxExempt; // 分发/团队地址免税收发,deployer 设置一次后永久锁定 bool public exemptionsLocked; IPancakeRouter public immutable router; address public immutable wbnb; uint256 public constant SWAP_THRESHOLD = 1_000_000 * 1e18; // 攒够 100 万代币才换 BNB /* ---------- 分红 ---------- */ uint256 public constant MAG = 1e18; uint256 public constant MIN_HOLD = 10_000_000 * 1e18; // 门槛 1000 万 uint256 public constant MIN_CLAIM = 0.01 ether; // 最低领取 0.01 BNB uint256 public accPerShare; mapping(address => uint256) public lastAcc; mapping(address => uint256) public pending; uint256 public totalDividendReceived; uint256 public totalAllocated; // 已记账给持有人的总额 uint256 public totalClaimed; // 已领走的总额 uint256 public constant TICK_BPS = 500; // 每轮分出合约余额的 5% address public immutable deployer; bool private _inSwap; event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); event DividendIn(address indexed from, uint256 amount); event DividendClaimed(address indexed user, uint256 amount); event TaxSwapped(uint256 tokens, uint256 bnb); constructor( string memory _name, string memory _symbol, address _team, uint256 _supply, address _holder, address _router, address _wbnb ) { name = _name; symbol = _symbol; teamWallet = _team; totalSupply = _supply; deployer = msg.sender; router = IPancakeRouter(_router); wbnb = _wbnb; balanceOf[_holder] = _supply; emit Transfer(address(0), _holder, _supply); } /// 打新合约地址只登记一次(登记后永远生效,无法取消) function setLaunchOnce(address _launch) external { require(msg.sender == deployer, "not deployer"); require(launchContract == address(0), "locked"); require(_launch != address(0), "zero"); launchContract = _launch; } function setExempt(address who, bool on) external { require(msg.sender == deployer, "not deployer"); require(!exemptionsLocked, "locked"); taxExempt[who] = on; } /// 上线后锁死,任何人都不能再改免税名单 function lockExemptions() external { require(msg.sender == deployer, "not deployer"); exemptionsLocked = true; } /* ---------- 分红 ---------- */ receive() external payable {} /// 每轮把合约 BNB 余额的 5% 记到持有人账上(任何人可调用,没有权限) /// 未领取的部分不会被重复分配:分配上限 = 余额 - 未领取 function distributeTick() external returns (uint256) { uint256 bal = address(this).balance; if (bal == 0) return 0; uint256 outstanding = totalAllocated - totalClaimed; uint256 avail = bal > outstanding ? bal - outstanding : 0; uint256 amount = (bal * TICK_BPS) / 10000; if (amount > avail) amount = avail; if (amount == 0) return 0; _distribute(amount); return amount; } function _eligibleSupply() internal view returns (uint256) { // 合约自己持有的税代币不参与分红 return totalSupply - balanceOf[address(this)]; } function _distribute(uint256 amount) internal { if (amount == 0) return; uint256 denom = _eligibleSupply(); if (denom == 0) return; accPerShare += (amount * MAG) / denom; totalDividendReceived += amount; totalAllocated += amount; emit DividendIn(msg.sender, amount); } function _settle(address user) internal { uint256 bal = balanceOf[user]; if (bal == 0) { lastAcc[user] = accPerShare; return; } uint256 owed = (bal * (accPerShare - lastAcc[user])) / MAG; if (owed > 0) pending[user] += owed; lastAcc[user] = accPerShare; } /// 持有人自己领 BNB(自付 gas),需持币 ≥ 1000 万、可领 ≥ 0.01 BNB function claim() external { _settle(msg.sender); uint256 amt = pending[msg.sender]; require(balanceOf[msg.sender] >= MIN_HOLD, "hold < 10M"); require(amt >= MIN_CLAIM, "less than 0.01 BNB"); pending[msg.sender] = 0; totalClaimed += amt; (bool ok, ) = payable(msg.sender).call{value: amt}(""); require(ok, "bnb fail"); emit DividendClaimed(msg.sender, amt); } function claimable(address user) external view returns (uint256) { uint256 bal = balanceOf[user]; uint256 extra = bal == 0 ? 0 : (bal * (accPerShare - lastAcc[user])) / MAG; uint256 total = pending[user] + extra; if (bal < MIN_HOLD || total < MIN_CLAIM) return 0; return total; } /* ---------- 税代币换 BNB(任何人可调用,无需权限) ---------- */ function swapTaxToBnb(uint256 minBnbOut) external { require(!_inSwap, "busy"); uint256 tokens = balanceOf[address(this)]; require(tokens >= SWAP_THRESHOLD, "below threshold"); _inSwap = true; _settle(address(this)); balanceOf[address(this)] = 0; emit Transfer(address(this), address(this), 0); address[] memory path = new address[](2); path[0] = address(this); path[1] = wbnb; allowance[address(this)][address(router)] = tokens; uint256 before = address(this).balance; router.swapExactTokensForETHSupportingFeeOnTransferTokens( tokens, minBnbOut, path, address(this), block.timestamp ); uint256 gained = address(this).balance - before; _inSwap = false; emit TaxSwapped(tokens, gained); } /* ---------- 转账与税 ---------- */ function transfer(address to, uint256 amount) external returns (bool) { _transfer(msg.sender, to, amount); return true; } function transferFrom(address from, address to, uint256 amount) external returns (bool) { uint256 a = allowance[from][msg.sender]; require(a >= amount, "allowance"); if (a != type(uint256).max) allowance[from][msg.sender] = a - amount; _transfer(from, to, amount); return true; } function approve(address spender, uint256 amount) external returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function _isExempt(address a) internal view returns (bool) { return taxExempt[a] || a == address(this) || (launchContract != address(0) && a == launchContract); } function _transfer(address from, address to, uint256 amount) internal { require(balanceOf[from] >= amount, "balance"); _settle(from); _settle(to); bool taxed = !_isExempt(from) && !_isExempt(to) && to != address(0); uint256 tax = taxed ? (amount * TAX_BPS) / 10000 : 0; uint256 net = amount - tax; balanceOf[from] -= amount; balanceOf[to] += net; if (tax > 0) { uint256 half = (tax * TEAM_SHARE_BPS) / 100; balanceOf[teamWallet] += half; balanceOf[address(this)] += tax - half; // 留在合约,等着换 BNB 进分红池 emit Transfer(from, teamWallet, half); emit Transfer(from, address(this), tax - half); } emit Transfer(from, to, net); } }