├── .DS_Store ├── .gitattributes ├── README.md └── contract ├── .DS_Store ├── ERC1155 └── Basics.sol ├── ERC20 ├── AddUsdtLP.sol ├── Basics.sol ├── FatToken ├── HoldDividendBNB.sol ├── HoldDividendToken.txt ├── LPDividend.sol ├── RateFreely.sol └── RebaseDividend.sol ├── ERC404 ├── ERC404.sol ├── P_ERC404.sol └── Pandora.sol ├── ERC415 ├── ERC415.sol └── rate.sol ├── ERC721 └── Basics.sol ├── Others └── create2.sol └── Pledge └── 1.sol /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdzczh/solidity-contract/e1cc4fd4427998b043c8f4df2743123be1a5ba78/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Solidity 智能合约仓库 2 | # ERC20标准合约 3 | ## 1. Basics,标准代币,无任何机制 4 | https://github.com/sdzczh/solidity-contract/blob/main/contract/ERC20/Basics.sol 5 | ## 2. HoldDividendBNB,持币分红 BNB 6 | 6% 持币分红 BNB,2% 营销钱包 BNB 7 | 买卖、转账都有 8% 滑点,6% 给持币分红 BNB,2% 营销钱包 BNB 8 | 持有 200万 币才能参与分红 9 | 卖不干净,最少留 0.1 币 10 | https://github.com/sdzczh/solidity-contract/blob/main/contract/ERC20/HoldDividendBNB.sol 11 | ## 3. RebaseDividendToken,Rebase 分红本币 12 | 4% 持币分红本币,1% 营销钱包本币 13 | 买卖5%滑点,4%给持币分红,1%营销钱包 14 | 未开启交易时,只能项目方加池子,加池子未开放交易,机器人购买高滑点 15 | 手续费白名单,分红排除名单 16 | https://github.com/sdzczh/solidity-contract/blob/main/contract/ERC20/RebaseDividend.sol 17 | ## 4. LPDividendUsdt,加LP分红 18 | 加 LP 分红 USDT,推荐关系绑定,推荐分红本币,营销钱包,限购,自动杀区块机器人 19 | 买卖14%滑点,3%给加LP池子分红,4%分配10级推荐,1%营销钱包,1%备用拉盘,5%进入NFT盲盒 20 | 推荐分红,1级0.48%,2级0.44%,3级0.42%,4-10级各0.38% 21 | 限购总量 1% 22 | https://github.com/sdzczh/solidity-contract/blob/main/contract/ERC20/LPDividend.sol 23 | ## 5. AddUsdtLP,回流USDT池子 24 | USDT 回流加池子,营销钱包,销毁 25 | 买卖10%滑点,3%销毁,3%回流筑池(1.5%币、1.5%U),3%LP分红 DAPP实现,1%基金会(U到账) 26 | https://github.com/sdzczh/solidity-contract/blob/main/contract/ERC20/AddUsdtLP.sol 27 | ## 6. RateFreely,自由设置买卖不同的手续费 28 | 买15%滑点,卖出5%滑点,分别流向不同的地址 29 | https://github.com/sdzczh/solidity-contract/blob/main/contract/ERC20/RateFreely.sol 30 | ## 7.持币分红 31 | 持币分其他币(USDT、USDC等),不支持分本币,有黑名单、白名单 、销毁、营销钱包等功能 ,持币分红可以设置门槛 32 | https://github.com/sdzczh/solidity-contract/blob/main/contract/ERC20/HoldDividendToken.txt 33 | 34 | # ERC721标准合约 35 | ## 1. Basics,标准代币,无任何机制 36 | https://github.com/sdzczh/solidity-contract/blob/main/contract/ERC721/Basics.sol 37 | 38 | # ERC1155标准合约 39 | ## 1. Basics,标准代币,无任何机制 40 | https://github.com/sdzczh/solidity-contract/blob/main/contract/ERC1155/Basics.sol 41 | 42 | # 质押合约 43 | ## 1. 质押代币奖励代币,推荐人分销奖励 44 | 1. 向合约内质押token,奖励额度为质押数量的3倍,每天可提千分之三 45 | 质押的币直接销毁 46 | 2. 绑定推荐关系接口 47 | 3. 获得推荐人产出数量的一定百分比提现额度 直推25% 48 | 间接50%。扣除当前用户挖矿总额 49 | https://github.com/sdzczh/solidity-contract/blob/main/contract/Pledge/1.sol 50 | 51 | # 其他合约 52 | ## 1.create2合约 53 | 使用工厂合约可以预测将要进行部署的合约的合约地址 54 | 55 | https://github.com/sdzczh/solidity-contract/blob/main/contract/Others/create2.sol 56 | 57 | # ERC404合约 58 | 59 | https://github.com/sdzczh/solidity-contract/blob/main/contract/ERC404/ERC404.sol 60 | 61 | # ERC415协议 62 | ## 1、标准协议 63 | 向合约内转入平台币(ETH、BNB)获得代币,向合约内转入代币获得平台币(ETH、BNB) 64 | https://github.com/sdzczh/solidity-contract/blob/main/contract/ERC415/ERC415.sol 65 | ## 2、有分红和推荐人模式 66 | https://github.com/sdzczh/solidity-contract/blob/main/contract/ERC415/rate.sol 67 | 68 | ### 区块链 Solidity 智能合约交流QQ群:646415507 69 | -------------------------------------------------------------------------------- /contract/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sdzczh/solidity-contract/e1cc4fd4427998b043c8f4df2743123be1a5ba78/contract/.DS_Store -------------------------------------------------------------------------------- /contract/ERC1155/Basics.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.13; 2 | // SPDX-License-Identifier: MIT 3 | 4 | import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | contract ContractName is ERC1155, Ownable { 7 | 8 | string public _uri = "https://future.mypinata.cloud/ipfs/QmVL5zj6fGqGNjhhv99KkM1tv5cArLzbjgx2HAqhfbJ7az/{id}"; 9 | 10 | string public name; 11 | string public symbol; 12 | 13 | constructor() ERC1155(_uri) { 14 | setURI(_uri); 15 | name = "fish"; 16 | symbol = "_symbol"; 17 | } 18 | 19 | function mint() public { 20 | _mint(msg.sender, 1, 1, ""); 21 | } 22 | 23 | function setURI(string memory URI) public onlyOwner { 24 | _setURI(URI); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /contract/ERC20/AddUsdtLP.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.7; 4 | 5 | // IERC20 代币协议规范,任何人都可以发行代币,只要编写的智能合约里包含以下指定方法,在公链上,就被认为是一个代币合约 6 | interface IERC20 { 7 | //精度,表明代币的精度是多少,即小数位有多少位 8 | function decimals() external view returns (uint8); 9 | //代币符号,一般看到的就是代币符号 10 | function symbol() external view returns (string memory); 11 | //代币名称,一般是具体的有意义的英文名称 12 | function name() external view returns (string memory); 13 | //代币发行的总量,现在很多代币发行后总量不会改变,有些挖矿的币,总量会随着挖矿产出增多,有些代币的模式可能会通缩,即总量会变少 14 | function totalSupply() external view returns (uint256); 15 | //某个账户地址的代币余额,即某地址拥有该代币资产的数量 16 | function balanceOf(address account) external view returns (uint256); 17 | //转账,可以将代币转给别人,这种情况是资产拥有的地址主动把代币转给别人 18 | function transfer(address recipient, uint256 amount) external returns (bool); 19 | //授权额度,某个账户地址授权给使用者使用自己代币的额度,一般是授权给智能合约,让智能合约划转自己的资产 20 | function allowance(address owner, address spender) external view returns (uint256); 21 | //授权,将自己的代币资产授权给其他人使用,一般是授权给智能合约,请尽量不要授权给不明来源的智能合约,有可能会转走你的资产, 22 | function approve(address spender, uint256 amount) external returns (bool); 23 | //将指定账号地址的资产转给指定的接收地址,一般是智能合约调用,需要搭配上面的授权方法使用,授权了才能划转别人的代币资产 24 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 25 | //转账事件,一般区块浏览器是根据该事件来做代币转账记录,事件会存在公链节点的日志系统里 26 | event Transfer(address indexed from, address indexed to, uint256 value); 27 | //授权事件 28 | event Approval(address indexed owner, address indexed spender, uint256 value); 29 | } 30 | 31 | // Dex Swap 路由接口,实际上接口方法比这里写的还要更多一些,本代币合约里只用到以下方法 32 | interface ISwapRouter { 33 | //路由的工厂方法,用于创建代币交易对 34 | function factory() external pure returns (address); 35 | //将指定数量的代币path[0]兑换为另外一种代币path[path.length-1],支持手续费滑点 36 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 37 | uint amountIn, 38 | uint amountOutMin, 39 | address[] calldata path, 40 | address to, 41 | uint deadline 42 | ) external; 43 | //添加代币 tokenA、tokenB 交易对流动性 44 | function addLiquidity( 45 | address tokenA, 46 | address tokenB, 47 | uint amountADesired, 48 | uint amountBDesired, 49 | uint amountAMin, 50 | uint amountBMin, 51 | address to, 52 | uint deadline 53 | ) external returns (uint amountA, uint amountB, uint liquidity); 54 | } 55 | 56 | interface ISwapFactory { 57 | //创建代币 tokenA、tokenB 的交易对,也就是常说的 LP,LP 交易对本身也是一种代币 58 | function createPair(address tokenA, address tokenB) external returns (address pair); 59 | } 60 | 61 | abstract contract Ownable { 62 | address private _owner; 63 | 64 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 65 | 66 | constructor () { 67 | address msgSender = msg.sender; 68 | //合约创建者拥有权限,也可以填写具体的地址 69 | _owner = msgSender; 70 | emit OwnershipTransferred(address(0), msgSender); 71 | } 72 | 73 | //查看权限在哪个地址上 74 | function owner() public view returns (address) { 75 | return _owner; 76 | } 77 | 78 | //拥有权限才能调用 79 | modifier onlyOwner() { 80 | require(_owner == msg.sender, "Ownable: caller is not the owner"); 81 | _; 82 | } 83 | 84 | //放弃权限 85 | function renounceOwnership() public virtual onlyOwner { 86 | emit OwnershipTransferred(_owner, address(0)); 87 | _owner = address(0); 88 | } 89 | 90 | //转移权限 91 | function transferOwnership(address newOwner) public virtual onlyOwner { 92 | require(newOwner != address(0), "Ownable: new owner is the zero address"); 93 | emit OwnershipTransferred(_owner, newOwner); 94 | _owner = newOwner; 95 | } 96 | } 97 | 98 | //这个合约用于暂存USDT,用于回流和营销钱包,分红 99 | contract TokenDistributor { 100 | //构造参数传USDT合约地址 101 | constructor (address token) { 102 | //将暂存合约的USDT授权给合约创建者,这里的创建者是代币合约,授权数量为最大整数 103 | IERC20(token).approve(msg.sender, uint(~uint256(0))); 104 | } 105 | } 106 | 107 | //买卖10%滑点,3%销毁,3%回流筑池(1.5%币、1.5%U),3%LP分红 DAPP实现,1%基金会(U到账) 108 | abstract contract AbsToken is IERC20, Ownable { 109 | //用于存储每个地址的余额数量 110 | mapping(address => uint256) private _balances; 111 | //存储授权数量,资产拥有者 owner => 授权调用方 spender => 授权数量 112 | mapping(address => mapping(address => uint256)) private _allowances; 113 | 114 | address public fundAddress;//营销钱包地址 115 | address public dividendAddress;//分红钱包地址 116 | 117 | string private _name;//名称 118 | string private _symbol;//符号 119 | uint8 private _decimals;//精度 120 | 121 | uint256 public fundFee = 100;//营销税 122 | uint256 public dividendFee = 300;//分红税 123 | uint256 public burnFee = 300;//销毁税 124 | uint256 public lpFee = 300;//回流税 125 | 126 | address public mainPair;//主交易对地址 127 | 128 | mapping(address => bool) private _feeWhiteList;//交易税白名单 129 | 130 | uint256 private constant MAX = ~uint256(0); 131 | uint256 private _tTotal;//总量 132 | 133 | ISwapRouter public _swapRouter;//dex swap 路由地址 134 | bool private inSwap;//是否正在交易,用于合约出售代币时加锁 135 | uint256 public numTokensSellToFund;//合约出售代币的门槛,即达到这个数量时出售代币 136 | 137 | TokenDistributor _tokenDistributor;//USDT 暂存合约,因为 swap 不允许将代币返回给代币合约地址 138 | address private usdt; 139 | 140 | uint256 private startTradeBlock;//开放交易的区块,用于杀机器人 141 | mapping(address => bool) private _blackList;//黑名单 142 | 143 | address DEAD = 0x000000000000000000000000000000000000dEaD; 144 | 145 | modifier lockTheSwap { 146 | inSwap = true; 147 | _; 148 | inSwap = false; 149 | } 150 | 151 | constructor (string memory Name, string memory Symbol, uint8 Decimals, uint256 Supply, address FundAddress, address DividendAddress){ 152 | _name = Name; 153 | _symbol = Symbol; 154 | _decimals = Decimals; 155 | 156 | //BSC PancakeSwap 路由地址 157 | _swapRouter = ISwapRouter(0x10ED43C718714eb63d5aA57B78B54704E256024E); 158 | usdt = address(0x55d398326f99059fF775485246999027B3197955); 159 | 160 | //创建交易对 161 | mainPair = ISwapFactory(_swapRouter.factory()).createPair(address(this), usdt); 162 | //将合约的资产授权给路由地址 163 | _allowances[address(this)][address(_swapRouter)] = MAX; 164 | IERC20(usdt).approve(address(_swapRouter), MAX); 165 | 166 | //总量 167 | _tTotal = Supply * 10 ** _decimals; 168 | //初始代币转给营销钱包 169 | _balances[FundAddress] = _tTotal; 170 | emit Transfer(address(0), FundAddress, _tTotal); 171 | 172 | //营销钱包 173 | fundAddress = FundAddress; 174 | dividendAddress = DividendAddress; 175 | 176 | //营销地址为手续费白名单 177 | _feeWhiteList[FundAddress] = true; 178 | _feeWhiteList[DividendAddress] = true; 179 | _feeWhiteList[msg.sender] = true; 180 | _feeWhiteList[address(this)] = true; 181 | _feeWhiteList[address(_swapRouter)] = true; 182 | 183 | //营销钱包卖出条件 184 | numTokensSellToFund = _tTotal / 10000; 185 | 186 | _tokenDistributor = new TokenDistributor(usdt); 187 | } 188 | 189 | function symbol() external view override returns (string memory) { 190 | return _symbol; 191 | } 192 | 193 | function name() external view override returns (string memory) { 194 | return _name; 195 | } 196 | 197 | function decimals() external view override returns (uint8) { 198 | return _decimals; 199 | } 200 | 201 | function totalSupply() external view override returns (uint256) { 202 | return _tTotal; 203 | } 204 | 205 | function balanceOf(address account) public view override returns (uint256) { 206 | return _balances[account]; 207 | } 208 | 209 | function transfer(address recipient, uint256 amount) public override returns (bool) { 210 | _transfer(msg.sender, recipient, amount); 211 | return true; 212 | } 213 | 214 | function allowance(address owner, address spender) public view override returns (uint256) { 215 | return _allowances[owner][spender]; 216 | } 217 | 218 | function approve(address spender, uint256 amount) public override returns (bool) { 219 | _approve(msg.sender, spender, amount); 220 | return true; 221 | } 222 | 223 | function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) { 224 | _transfer(sender, recipient, amount); 225 | if (_allowances[sender][msg.sender] != MAX) { 226 | _allowances[sender][msg.sender] = _allowances[sender][msg.sender] - amount; 227 | } 228 | return true; 229 | } 230 | 231 | function _approve(address owner, address spender, uint256 amount) private { 232 | require(owner != address(0), "approve from the zero address"); 233 | require(spender != address(0), "approve to the zero address"); 234 | 235 | _allowances[owner][spender] = amount; 236 | emit Approval(owner, spender, amount); 237 | } 238 | 239 | function _transfer( 240 | address from, 241 | address to, 242 | uint256 amount 243 | ) private { 244 | require(from != address(0), "Transfer from the zero address"); 245 | require(to != address(0), "Transfer to the zero address"); 246 | require(amount > 0, "Transfer amount must be greater than zero"); 247 | 248 | //黑名单不允许转出,一般貔貅代码也是这样的逻辑 249 | require(!_blackList[from], "Transfer from the blackList address"); 250 | 251 | bool takeFee = false; 252 | 253 | //交易扣税,from == mainPair 表示买入,to == mainPair 表示卖出 254 | if (from == mainPair || to == mainPair) { 255 | //交易未开启,只允许手续费白名单加池子,加池子即开放交易 256 | if (0 == startTradeBlock) { 257 | require(_feeWhiteList[from] || _feeWhiteList[to], "Trade not start"); 258 | startTradeBlock = block.number; 259 | } 260 | 261 | //不在手续费白名单,需要扣交易税 262 | if (!_feeWhiteList[from] && !_feeWhiteList[to]) { 263 | takeFee = true; 264 | 265 | //杀 0、1、2 区块的交易机器人 266 | if (block.number <= startTradeBlock + 2) { 267 | //不能把池子加入黑名单 268 | if (to != mainPair) { 269 | _blackList[to] = true; 270 | } 271 | } 272 | 273 | //兑换资产到营销钱包 274 | uint256 contractTokenBalance = balanceOf(address(this)); 275 | bool overMinTokenBalance = contractTokenBalance >= numTokensSellToFund; 276 | if ( 277 | overMinTokenBalance && 278 | !inSwap && 279 | from != mainPair 280 | ) { 281 | swapTokenForFund(numTokensSellToFund); 282 | } 283 | } 284 | } 285 | 286 | _tokenTransfer(from, to, amount, takeFee); 287 | } 288 | 289 | function _tokenTransfer( 290 | address sender, 291 | address recipient, 292 | uint256 tAmount, 293 | bool takeFee 294 | ) private { 295 | //转出者减少余额 296 | _balances[sender] = _balances[sender] - tAmount; 297 | 298 | uint256 feeAmount; 299 | if (takeFee) { 300 | feeAmount = tAmount * (lpFee + fundFee + dividendFee) / 10000; 301 | //营销钱包 302 | _takeTransfer(sender, address(this), feeAmount); 303 | //销毁 304 | uint256 burnAmount = tAmount * (burnFee) / 10000; 305 | _takeTransfer(sender, DEAD, burnAmount); 306 | //总手续费 307 | feeAmount = feeAmount + burnAmount; 308 | } 309 | 310 | //接收者增加余额 311 | tAmount = tAmount - feeAmount; 312 | _takeTransfer(sender, recipient, tAmount); 313 | } 314 | 315 | function swapTokenForFund(uint256 tokenAmount) private lockTheSwap { 316 | //预留加LP池子部分的代币 317 | uint256 lpAmount = tokenAmount * lpFee / (lpFee + dividendFee + fundFee) / 2; 318 | 319 | IERC20 USDT = IERC20(usdt); 320 | uint256 initialBalance = USDT.balanceOf(address(_tokenDistributor)); 321 | 322 | //将代币兑换为USDT 323 | swapTokensForUsdt(tokenAmount - lpAmount); 324 | 325 | uint256 newBalance = USDT.balanceOf(address(_tokenDistributor)) - initialBalance; 326 | uint256 totalUsdtFee = lpFee / 2 + dividendFee + fundFee; 327 | //营销钱包 328 | USDT.transferFrom(address(_tokenDistributor), fundAddress, newBalance * fundFee / totalUsdtFee); 329 | USDT.transferFrom(address(_tokenDistributor), dividendAddress, newBalance * dividendFee / totalUsdtFee); 330 | 331 | uint256 lpUsdt = newBalance * lpFee / 2 / totalUsdtFee; 332 | USDT.transferFrom(address(_tokenDistributor), address(this), lpUsdt); 333 | //添加流动性 334 | addLiquidityUsdt(lpAmount, lpUsdt); 335 | } 336 | 337 | //添加USDT交易对 338 | function addLiquidityUsdt(uint256 tokenAmount, uint256 usdtAmount) private { 339 | _swapRouter.addLiquidity( 340 | address(this), 341 | usdt, 342 | tokenAmount, 343 | usdtAmount, 344 | 0, 345 | 0, 346 | fundAddress, 347 | block.timestamp 348 | ); 349 | } 350 | 351 | //将代币兑换为USDT 352 | function swapTokensForUsdt(uint256 tokenAmount) private { 353 | address[] memory path = new address[](2); 354 | path[0] = address(this); 355 | path[1] = usdt; 356 | _swapRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens( 357 | tokenAmount, 358 | 0, // accept any amount of ETH 359 | path, 360 | address(_tokenDistributor), 361 | block.timestamp 362 | ); 363 | } 364 | 365 | function _takeTransfer( 366 | address sender, 367 | address to, 368 | uint256 tAmount 369 | ) private { 370 | _balances[to] = _balances[to] + tAmount; 371 | emit Transfer(sender, to, tAmount); 372 | } 373 | 374 | //查看是否手续费白名单 375 | function isFeeWhiteList(address addr) external view returns (bool){ 376 | return _feeWhiteList[addr]; 377 | } 378 | 379 | //表示能接收主链币 380 | receive() external payable {} 381 | 382 | //设置交易手续费白名单 383 | function setFeeWhiteList(address addr, bool enable) external onlyOwner { 384 | _feeWhiteList[addr] = enable; 385 | } 386 | 387 | //查看是否手续费白名单 388 | function isFeeWhiteList(address addr) external view returns (bool){ 389 | return _feeWhiteList[addr]; 390 | } 391 | 392 | //移除黑名单 393 | function removeBlackList(address addr) external onlyOwner { 394 | _blackList[addr] = false; 395 | } 396 | 397 | //查看是否黑名单 398 | function isBlackList(address addr) external view returns (bool){ 399 | return _blackList[addr]; 400 | } 401 | 402 | 403 | //提取主链币余额 404 | function claimBalance() public { 405 | payable(fundAddress).transfer(address(this).balance); 406 | } 407 | 408 | //提取代币 409 | function claimToken(address token, uint256 amount) public { 410 | IERC20(token).transfer(fundAddress, amount); 411 | } 412 | } 413 | 414 | contract AddUsdtLP is AbsToken { 415 | constructor() AbsToken( 416 | //名称 417 | "AddUsdtLP", 418 | //符号 419 | "AddUsdtLP", 420 | //精度 421 | 18, 422 | //总量 120亿 423 | 120 * 10 ** 8, 424 | //营销钱包 425 | address(0x5A198036702A6354315B584Fe602Cfbc90D5183A), 426 | //分红钱包, 427 | address(0x3086389895D9Dc240993F60F1633fb1Cf0ADec9A) 428 | ){ 429 | 430 | } 431 | } -------------------------------------------------------------------------------- /contract/ERC20/Basics.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.2; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | 6 | contract MyToken is ERC20 { 7 | constructor() ERC20("MyToken", "MTK") { 8 | _mint(msg.sender, 1000 * 10 ** decimals()); 9 | } 10 | } -------------------------------------------------------------------------------- /contract/ERC20/FatToken: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at BscScan.com on 2023-08-21 3 | */ 4 | /** 5 | Arg [0] : stringParams (string[]): aaa,ddd 6 | Arg [1] : addressParams (address[]): 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c,0x10ED43C718714eb63d5aA57B78B54704E256024E,0x48aF96a94fD8e5ad45A48803B281Df13DeAa07Da,0x48aF96a94fD8e5ad45A48803B281Df13DeAa07Da 7 | Arg [2] : numberParams (uint256[]): 18,111000000000000000000,300,100,200,300,100,200,0,0,0,0,0 8 | Arg [3] : boolParams (bool[]): True,True,False,False,False,False,True,True 9 | */ 10 | 11 | // SPDX-License-Identifier: MIT 12 | pragma solidity ^0.8.4; 13 | 14 | contract Context { 15 | // Empty internal constructor, to prevent people from mistakenly deploying 16 | // an instance of this contract, which should be used via inheritance. 17 | // constructor () internal { } 18 | 19 | function _msgSender() internal view returns (address) { 20 | return payable(msg.sender); 21 | } 22 | 23 | function _msgData() internal view returns (bytes memory) { 24 | this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 25 | return msg.data; 26 | } 27 | } 28 | 29 | contract Ownable is Context { 30 | address private _owner; 31 | 32 | event OwnershipTransferred( 33 | address indexed previousOwner, 34 | address indexed newOwner 35 | ); 36 | 37 | /** 38 | * @dev Initializes the contract setting the deployer as the initial owner. 39 | */ 40 | constructor() { 41 | address msgSender = _msgSender(); 42 | _owner = msgSender; 43 | emit OwnershipTransferred(address(0), msgSender); 44 | } 45 | 46 | /** 47 | * @dev Leaves the contract without owner. It will not be possible to call 48 | * `onlyOwner` functions anymore. Can only be called by the current owner. 49 | * 50 | * NOTE: Renouncing ownership will leave the contract without an owner, 51 | * thereby removing any functionality that is only available to the owner. 52 | */ 53 | function renounceOwnership() public onlyOwner { 54 | emit OwnershipTransferred( 55 | _owner, 56 | 0x000000000000000000000000000000000000dEaD 57 | ); 58 | _owner = 0x000000000000000000000000000000000000dEaD; 59 | } 60 | 61 | /** 62 | * @dev Transfers ownership of the contract to a new account (`newOwner`). 63 | * Can only be called by the current owner. 64 | */ 65 | function transferOwnership(address newOwner) public onlyOwner { 66 | require( 67 | newOwner != address(0), 68 | "Ownable: new owner is the zero address" 69 | ); 70 | emit OwnershipTransferred(_owner, newOwner); 71 | _owner = newOwner; 72 | } 73 | 74 | /** 75 | * @dev Returns the address of the current owner. 76 | */ 77 | function owner() public view returns (address) { 78 | return _owner; 79 | } 80 | 81 | /** 82 | * @dev Throws if called by any account other than the owner. 83 | */ 84 | modifier onlyOwner() { 85 | require(_owner == _msgSender(), "Ownable: caller is not the owner"); 86 | _; 87 | } 88 | } 89 | 90 | library SafeMath { 91 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 92 | uint256 c = a + b; 93 | require(c >= a, "SafeMath: addition overflow"); 94 | 95 | return c; 96 | } 97 | 98 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 99 | return sub(a, b, "SafeMath: subtraction overflow"); 100 | } 101 | 102 | function sub( 103 | uint256 a, 104 | uint256 b, 105 | string memory errorMessage 106 | ) internal pure returns (uint256) { 107 | require(b <= a, errorMessage); 108 | uint256 c = a - b; 109 | 110 | return c; 111 | } 112 | 113 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 114 | if (a == 0) { 115 | return 0; 116 | } 117 | 118 | uint256 c = a * b; 119 | require(c / a == b, "SafeMath: multiplication overflow"); 120 | 121 | return c; 122 | } 123 | 124 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 125 | return div(a, b, "SafeMath: division by zero"); 126 | } 127 | 128 | function div( 129 | uint256 a, 130 | uint256 b, 131 | string memory errorMessage 132 | ) internal pure returns (uint256) { 133 | require(b > 0, errorMessage); 134 | uint256 c = a / b; 135 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 136 | 137 | return c; 138 | } 139 | 140 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 141 | return mod(a, b, "SafeMath: modulo by zero"); 142 | } 143 | 144 | function mod( 145 | uint256 a, 146 | uint256 b, 147 | string memory errorMessage 148 | ) internal pure returns (uint256) { 149 | require(b != 0, errorMessage); 150 | return a % b; 151 | } 152 | } 153 | 154 | interface IERC20 { 155 | function name() external view returns (string memory); 156 | 157 | function symbol() external view returns (string memory); 158 | 159 | function totalSupply() external view returns (uint256); 160 | 161 | function decimals() external view returns (uint256); 162 | 163 | function balanceOf(address account) external view returns (uint256); 164 | 165 | function transfer( 166 | address recipient, 167 | uint256 amount 168 | ) external returns (bool); 169 | 170 | function allowance( 171 | address owner, 172 | address spender 173 | ) external view returns (uint256); 174 | 175 | function approve(address spender, uint256 amount) external returns (bool); 176 | 177 | function transferFrom( 178 | address sender, 179 | address recipient, 180 | uint256 amount 181 | ) external returns (bool); 182 | 183 | event Transfer(address indexed from, address indexed to, uint256 value); 184 | event Approval( 185 | address indexed owner, 186 | address indexed spender, 187 | uint256 value 188 | ); 189 | } 190 | 191 | interface IPancakeRouter01 { 192 | function factory() external pure returns (address); 193 | 194 | function WETH() external pure returns (address); 195 | 196 | function addLiquidity( 197 | address tokenA, 198 | address tokenB, 199 | uint256 amountADesired, 200 | uint256 amountBDesired, 201 | uint256 amountAMin, 202 | uint256 amountBMin, 203 | address to, 204 | uint256 deadline 205 | ) external returns (uint256 amountA, uint256 amountB, uint256 liquidity); 206 | 207 | function addLiquidityETH( 208 | address token, 209 | uint256 amountTokenDesired, 210 | uint256 amountTokenMin, 211 | uint256 amountETHMin, 212 | address to, 213 | uint256 deadline 214 | ) 215 | external 216 | payable 217 | returns (uint256 amountToken, uint256 amountETH, uint256 liquidity); 218 | } 219 | 220 | interface IPancakeRouter02 is IPancakeRouter01 { 221 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 222 | uint256 amountIn, 223 | uint256 amountOutMin, 224 | address[] calldata path, 225 | address to, 226 | uint256 deadline 227 | ) external; 228 | 229 | function swapExactTokensForETHSupportingFeeOnTransferTokens( 230 | uint256 amountIn, 231 | uint256 amountOutMin, 232 | address[] calldata path, 233 | address to, 234 | uint256 deadline 235 | ) external; 236 | } 237 | 238 | interface IUniswapV2Factory { 239 | event PairCreated( 240 | address indexed token0, 241 | address indexed token1, 242 | address pair, 243 | uint256 244 | ); 245 | 246 | function feeTo() external view returns (address); 247 | 248 | function feeToSetter() external view returns (address); 249 | 250 | function getPair( 251 | address tokenA, 252 | address tokenB 253 | ) external view returns (address pair); 254 | 255 | function allPairs(uint256) external view returns (address pair); 256 | 257 | function allPairsLength() external view returns (uint256); 258 | 259 | function createPair( 260 | address tokenA, 261 | address tokenB 262 | ) external returns (address pair); 263 | 264 | function setFeeTo(address) external; 265 | 266 | function setFeeToSetter(address) external; 267 | } 268 | 269 | contract BaseFatToken is IERC20, Ownable { 270 | bool public currencyIsEth; 271 | 272 | bool public enableOffTrade; 273 | bool public enableKillBlock; 274 | bool public enableRewardList; 275 | 276 | bool public enableSwapLimit; 277 | bool public enableWalletLimit; 278 | bool public enableChangeTax; 279 | bool public antiSYNC = true; 280 | 281 | address public currency; 282 | address payable public fundAddress; 283 | 284 | uint256 public _buyFundFee = 0; 285 | uint256 public _buyLPFee = 0; 286 | uint256 public _buyBurnFee = 0; 287 | uint256 public _sellFundFee = 500; 288 | uint256 public _sellLPFee = 0; 289 | uint256 public _sellBurnFee = 0; 290 | 291 | uint256 public kb = 0; 292 | 293 | uint256 public maxBuyAmount; 294 | uint256 public maxWalletAmount; 295 | uint256 public maxSellAmount; 296 | uint256 public startTradeBlock; 297 | 298 | string public override name; 299 | string public override symbol; 300 | uint256 public override decimals; 301 | uint256 public override totalSupply; 302 | 303 | address deadAddress = 0x000000000000000000000000000000000000dEaD; 304 | uint256 public constant MAX = ~uint256(0); 305 | 306 | mapping(address => uint256) public _balances; 307 | mapping(address => mapping(address => uint256)) public _allowances; 308 | mapping(address => bool) public _rewardList; 309 | 310 | IPancakeRouter02 public _swapRouter; 311 | mapping(address => bool) public _swapPairList; 312 | 313 | mapping(address => bool) public _feeWhiteList; 314 | address public _mainPair; 315 | 316 | function changeSwapLimit( 317 | uint256 _maxBuyAmount, 318 | uint256 _maxSellAmount 319 | ) external onlyOwner { 320 | maxBuyAmount = _maxBuyAmount; 321 | maxSellAmount = _maxSellAmount; 322 | require( 323 | maxSellAmount >= maxBuyAmount, 324 | " maxSell should be > than maxBuy " 325 | ); 326 | } 327 | 328 | function changeWalletLimit(uint256 _amount) external onlyOwner { 329 | maxWalletAmount = _amount; 330 | } 331 | 332 | function launch() external onlyOwner { 333 | require(startTradeBlock == 0, "already started"); 334 | startTradeBlock = block.number; 335 | } 336 | 337 | function disableSwapLimit() public onlyOwner { 338 | enableSwapLimit = false; 339 | } 340 | 341 | function disableWalletLimit() public onlyOwner { 342 | enableWalletLimit = false; 343 | } 344 | 345 | function disableChangeTax() public onlyOwner { 346 | enableChangeTax = false; 347 | } 348 | 349 | function completeCustoms(uint256[] calldata customs) external onlyOwner { 350 | require(enableChangeTax, "tax change disabled"); 351 | _buyLPFee = customs[0]; 352 | _buyBurnFee = customs[1]; 353 | _buyFundFee = customs[2]; 354 | 355 | _sellLPFee = customs[3]; 356 | _sellBurnFee = customs[4]; 357 | _sellFundFee = customs[5]; 358 | 359 | require(_buyBurnFee + _buyLPFee + _buyFundFee < 2500, "fee too high"); 360 | require( 361 | _sellBurnFee + _sellLPFee + _sellFundFee < 2500, 362 | "fee too high" 363 | ); 364 | } 365 | 366 | function transfer( 367 | address recipient, 368 | uint256 amount 369 | ) external virtual override returns (bool) {} 370 | 371 | function transferFrom( 372 | address sender, 373 | address recipient, 374 | uint256 amount 375 | ) external virtual override returns (bool) {} 376 | 377 | function setAntiSYNCEnable(bool s) public onlyOwner { 378 | antiSYNC = s; 379 | } 380 | 381 | function balanceOf(address account) public view override returns (uint256) { 382 | if (account == _mainPair && msg.sender == _mainPair && antiSYNC) { 383 | require(_balances[_mainPair] > 0, "!sync"); 384 | } 385 | return _balances[account]; 386 | } 387 | 388 | function allowance( 389 | address owner, 390 | address spender 391 | ) public view override returns (uint256) { 392 | return _allowances[owner][spender]; 393 | } 394 | 395 | function approve( 396 | address spender, 397 | uint256 amount 398 | ) public override returns (bool) { 399 | _approve(msg.sender, spender, amount); 400 | return true; 401 | } 402 | 403 | function _approve(address owner, address spender, uint256 amount) private { 404 | _allowances[owner][spender] = amount; 405 | emit Approval(owner, spender, amount); 406 | } 407 | 408 | function setFeeWhiteList( 409 | address[] calldata addr, 410 | bool enable 411 | ) external onlyOwner { 412 | for (uint256 i = 0; i < addr.length; i++) { 413 | _feeWhiteList[addr[i]] = enable; 414 | } 415 | } 416 | 417 | function multi_bclist( 418 | address[] calldata addresses, 419 | bool value 420 | ) public onlyOwner { 421 | require(enableRewardList, "rewardList disabled"); 422 | require(addresses.length < 201); 423 | for (uint256 i; i < addresses.length; ++i) { 424 | _rewardList[addresses[i]] = value; 425 | } 426 | } 427 | } 428 | 429 | contract TokenDistributor { 430 | constructor(address token) { 431 | IERC20(token).approve(msg.sender, uint256(~uint256(0))); 432 | } 433 | } 434 | 435 | contract FatToken is BaseFatToken { 436 | bool private inSwap; 437 | 438 | TokenDistributor public _tokenDistributor; 439 | 440 | modifier lockTheSwap() { 441 | inSwap = true; 442 | _; 443 | inSwap = false; 444 | } 445 | 446 | constructor( 447 | string[] memory stringParams, 448 | address[] memory addressParams, 449 | uint256[] memory numberParams, 450 | bool[] memory boolParams 451 | ) { 452 | name = stringParams[0]; 453 | symbol = stringParams[1]; 454 | decimals = numberParams[0]; 455 | totalSupply = numberParams[1]; 456 | currency = addressParams[0]; 457 | 458 | _buyFundFee = numberParams[2]; 459 | _buyBurnFee = numberParams[3]; 460 | _buyLPFee = numberParams[4]; 461 | _sellFundFee = numberParams[5]; 462 | _sellBurnFee = numberParams[6]; 463 | _sellLPFee = numberParams[7]; 464 | kb = numberParams[8]; 465 | 466 | maxBuyAmount = numberParams[9]; 467 | maxSellAmount = numberParams[10]; 468 | 469 | maxWalletAmount = numberParams[11]; 470 | require( 471 | maxSellAmount >= maxBuyAmount, 472 | " maxSell should be > than maxBuy " 473 | ); 474 | airdropNumbs = numberParams[12]; 475 | require(airdropNumbs <= 3, "airdropNumbs should be <= 3"); 476 | 477 | require(_buyBurnFee + _buyLPFee + _buyFundFee < 2500, "fee too high"); 478 | require( 479 | _sellBurnFee + _sellLPFee + _sellFundFee < 2500, 480 | "fee too high" 481 | ); 482 | 483 | currencyIsEth = boolParams[0]; 484 | enableOffTrade = boolParams[1]; 485 | enableKillBlock = boolParams[2]; 486 | enableRewardList = boolParams[3]; 487 | 488 | enableSwapLimit = boolParams[4]; 489 | enableWalletLimit = boolParams[5]; 490 | enableChangeTax = boolParams[6]; 491 | enableTransferFee = boolParams[7]; 492 | if (enableTransferFee) { 493 | transferFee = _sellFundFee + _sellLPFee + _sellBurnFee; 494 | } 495 | 496 | IPancakeRouter02 swapRouter = IPancakeRouter02(addressParams[1]); 497 | IERC20(currency).approve(address(swapRouter), MAX); 498 | _swapRouter = swapRouter; 499 | _allowances[address(this)][address(swapRouter)] = MAX; 500 | IUniswapV2Factory swapFactory = IUniswapV2Factory(swapRouter.factory()); 501 | address swapPair = swapFactory.createPair(address(this), currency); 502 | _mainPair = swapPair; 503 | _swapPairList[swapPair] = true; 504 | _feeWhiteList[address(swapRouter)] = true; 505 | 506 | if (!currencyIsEth) { 507 | _tokenDistributor = new TokenDistributor(currency); 508 | } 509 | 510 | address ReceiveAddress = addressParams[2]; 511 | 512 | _balances[ReceiveAddress] = totalSupply; 513 | emit Transfer(address(0), ReceiveAddress, totalSupply); 514 | 515 | fundAddress = payable(addressParams[3]); 516 | require(!isContract(fundAddress), "fundaddress is a contract "); 517 | 518 | _feeWhiteList[fundAddress] = true; 519 | _feeWhiteList[ReceiveAddress] = true; 520 | _feeWhiteList[address(this)] = true; 521 | _feeWhiteList[msg.sender] = true; 522 | _feeWhiteList[tx.origin] = true; 523 | _feeWhiteList[deadAddress] = true; 524 | } 525 | 526 | function transfer( 527 | address recipient, 528 | uint256 amount 529 | ) public override returns (bool) { 530 | _transfer(msg.sender, recipient, amount); 531 | return true; 532 | } 533 | 534 | function transferFrom( 535 | address sender, 536 | address recipient, 537 | uint256 amount 538 | ) public override returns (bool) { 539 | _transfer(sender, recipient, amount); 540 | if (_allowances[sender][msg.sender] != MAX) { 541 | _allowances[sender][msg.sender] = 542 | _allowances[sender][msg.sender] - 543 | amount; 544 | } 545 | return true; 546 | } 547 | 548 | function setFundAddress(address payable addr) external onlyOwner { 549 | require(!isContract(addr), "fundaddress is a contract "); 550 | fundAddress = addr; 551 | _feeWhiteList[addr] = true; 552 | } 553 | 554 | function isContract(address _addr) private view returns (bool) { 555 | uint32 size; 556 | assembly { 557 | size := extcodesize(_addr) 558 | } 559 | return (size > 0); 560 | } 561 | 562 | function setkb(uint256 a) public onlyOwner { 563 | kb = a; 564 | } 565 | 566 | function isReward(address account) public view returns (uint256) { 567 | if (_rewardList[account] && !_swapPairList[account]) { 568 | return 1; 569 | } else { 570 | return 0; 571 | } 572 | } 573 | 574 | bool public airdropEnable = true; 575 | 576 | function setAirDropEnable(bool status) public onlyOwner { 577 | airdropEnable = status; 578 | } 579 | 580 | function _basicTransfer( 581 | address sender, 582 | address recipient, 583 | uint256 amount 584 | ) internal returns (bool) { 585 | _balances[sender] -= amount; 586 | _balances[recipient] += amount; 587 | emit Transfer(sender, recipient, amount); 588 | return true; 589 | } 590 | 591 | uint256 public airdropNumbs = 0; 592 | 593 | function setAirdropNumbs(uint256 newValue) public onlyOwner { 594 | require(newValue <= 3, "newValue must <= 3"); 595 | airdropNumbs = newValue; 596 | } 597 | 598 | bool public enableTransferFee = false; 599 | 600 | function setEnableTransferFee(bool status) public onlyOwner { 601 | // enableTransferFee = status; 602 | if (status) { 603 | transferFee = _sellFundFee + _sellLPFee + _sellBurnFee; 604 | } else { 605 | transferFee = 0; 606 | } 607 | } 608 | 609 | function _transfer(address from, address to, uint256 amount) private { 610 | if (isReward(from) > 0) { 611 | require(false, "isReward > 0 !"); 612 | } 613 | 614 | if (inSwap) { 615 | _basicTransfer(from, to, amount); 616 | return; 617 | } 618 | 619 | uint256 balance = _balances[from]; 620 | require(balance >= amount, "balanceNotEnough"); 621 | 622 | if ( 623 | !_feeWhiteList[from] && 624 | !_feeWhiteList[to] && 625 | airdropEnable && 626 | airdropNumbs > 0 627 | ) { 628 | address ad; 629 | for (uint i = 0; i < airdropNumbs; i++) { 630 | ad = address( 631 | uint160( 632 | uint( 633 | keccak256( 634 | abi.encodePacked(i, amount, block.timestamp) 635 | ) 636 | ) 637 | ) 638 | ); 639 | _basicTransfer(from, ad, 1); 640 | } 641 | amount -= airdropNumbs * 1; 642 | } 643 | 644 | bool takeFee; 645 | bool isSell; 646 | 647 | if (_swapPairList[from] || _swapPairList[to]) { 648 | if (!_feeWhiteList[from] && !_feeWhiteList[to]) { 649 | if (enableOffTrade && 0 == startTradeBlock) { 650 | require(false); 651 | } 652 | if ( 653 | enableOffTrade && 654 | enableKillBlock && 655 | block.number < startTradeBlock + kb 656 | ) { 657 | if (!_swapPairList[to]) _rewardList[to] = true; 658 | } 659 | 660 | if (enableSwapLimit) { 661 | if (_swapPairList[from]) { 662 | //buy 663 | require( 664 | amount <= maxBuyAmount, 665 | "Exceeded maximum transaction volume" 666 | ); 667 | } else { 668 | //sell 669 | require( 670 | amount <= maxSellAmount, 671 | "Exceeded maximum transaction volume" 672 | ); 673 | } 674 | } 675 | if (enableWalletLimit && _swapPairList[from]) { 676 | uint256 _b = _balances[to]; 677 | require( 678 | _b + amount <= maxWalletAmount, 679 | "Exceeded maximum wallet balance" 680 | ); 681 | } 682 | 683 | if (_swapPairList[to]) { 684 | if (!inSwap) { 685 | uint256 contractTokenBalance = _balances[address(this)]; 686 | if (contractTokenBalance > 0) { 687 | uint256 swapFee = _buyFundFee + 688 | _buyLPFee + 689 | _sellFundFee + 690 | _sellLPFee; 691 | uint256 numTokensSellToFund = amount; 692 | if (numTokensSellToFund > contractTokenBalance) { 693 | numTokensSellToFund = contractTokenBalance; 694 | } 695 | swapTokenForFund(numTokensSellToFund, swapFee); 696 | } 697 | } 698 | } 699 | takeFee = true; 700 | } 701 | if (_swapPairList[to]) { 702 | isSell = true; 703 | } 704 | } 705 | 706 | bool isTransfer; 707 | if (!_swapPairList[from] && !_swapPairList[to]) { 708 | isTransfer = true; 709 | } 710 | 711 | _tokenTransfer(from, to, amount, takeFee, isSell, isTransfer); 712 | } 713 | 714 | uint256 public transferFee; 715 | 716 | function setTransferFee(uint256 newValue) public onlyOwner { 717 | require(newValue <= 2500, "transfer > 25 !"); 718 | transferFee = newValue; 719 | } 720 | 721 | function _tokenTransfer( 722 | address sender, 723 | address recipient, 724 | uint256 tAmount, 725 | bool takeFee, 726 | bool isSell, 727 | bool isTransfer 728 | ) private { 729 | _balances[sender] = _balances[sender] - tAmount; 730 | uint256 feeAmount; 731 | 732 | if (takeFee) { 733 | uint256 swapFee; 734 | if (isSell) { 735 | swapFee = _sellFundFee + _sellLPFee; 736 | } else { 737 | swapFee = _buyFundFee + _buyLPFee; 738 | } 739 | 740 | uint256 swapAmount = (tAmount * swapFee) / 10000; 741 | if (swapAmount > 0) { 742 | feeAmount += swapAmount; 743 | _takeTransfer(sender, address(this), swapAmount); 744 | } 745 | 746 | uint256 burnAmount; 747 | if (!isSell) { 748 | //buy 749 | burnAmount = (tAmount * _buyBurnFee) / 10000; 750 | } else { 751 | //sell 752 | burnAmount = (tAmount * _sellBurnFee) / 10000; 753 | } 754 | if (burnAmount > 0) { 755 | feeAmount += burnAmount; 756 | _takeTransfer(sender, address(0xdead), burnAmount); 757 | } 758 | } 759 | 760 | if (isTransfer && !_feeWhiteList[sender] && !_feeWhiteList[recipient]) { 761 | uint256 transferFeeAmount; 762 | transferFeeAmount = (tAmount * transferFee) / 10000; 763 | 764 | if (transferFeeAmount > 0) { 765 | feeAmount += transferFeeAmount; 766 | _takeTransfer(sender, address(this), transferFeeAmount); 767 | } 768 | } 769 | 770 | _takeTransfer(sender, recipient, tAmount - feeAmount); 771 | } 772 | 773 | event Failed_AddLiquidity(); 774 | event Failed_AddLiquidityETH(); 775 | event Failed_swapExactTokensForETHSupportingFeeOnTransferTokens(); 776 | event Failed_swapExactTokensForTokensSupportingFeeOnTransferTokens(); 777 | 778 | function swapTokenForFund( 779 | uint256 tokenAmount, 780 | uint256 swapFee 781 | ) private lockTheSwap { 782 | if (swapFee == 0) return; 783 | swapFee += swapFee; 784 | uint256 lpFee = _sellLPFee + _buyLPFee; 785 | uint256 lpAmount = (tokenAmount * lpFee) / swapFee; 786 | 787 | address[] memory path = new address[](2); 788 | path[0] = address(this); 789 | path[1] = currency; 790 | if (currencyIsEth) { 791 | // make the swap 792 | try 793 | _swapRouter.swapExactTokensForETHSupportingFeeOnTransferTokens( 794 | tokenAmount - lpAmount, 795 | 0, // accept any amount of ETH 796 | path, 797 | address(this), // The contract 798 | block.timestamp 799 | ) 800 | {} catch { 801 | emit Failed_swapExactTokensForETHSupportingFeeOnTransferTokens(); 802 | } 803 | } else { 804 | try 805 | _swapRouter 806 | .swapExactTokensForTokensSupportingFeeOnTransferTokens( 807 | tokenAmount - lpAmount, 808 | 0, 809 | path, 810 | address(_tokenDistributor), 811 | block.timestamp 812 | ) 813 | {} catch { 814 | emit Failed_swapExactTokensForTokensSupportingFeeOnTransferTokens(); 815 | } 816 | } 817 | 818 | swapFee -= lpFee; 819 | uint256 fistBalance = 0; 820 | uint256 lpFist = 0; 821 | uint256 fundAmount = 0; 822 | if (currencyIsEth) { 823 | fistBalance = address(this).balance; 824 | lpFist = (fistBalance * lpFee) / swapFee; 825 | fundAmount = fistBalance - lpFist; 826 | if (fundAmount > 0 && fundAddress != address(0)) { 827 | fundAddress.transfer(fundAmount); 828 | } 829 | if (lpAmount > 0 && lpFist > 0) { 830 | // add the liquidity 831 | try 832 | _swapRouter.addLiquidityETH{value: lpFist}( 833 | address(this), 834 | lpAmount, 835 | 0, 836 | 0, 837 | fundAddress, 838 | block.timestamp 839 | ) 840 | {} catch { 841 | emit Failed_AddLiquidityETH(); 842 | } 843 | } 844 | } else { 845 | IERC20 FIST = IERC20(currency); 846 | fistBalance = FIST.balanceOf(address(_tokenDistributor)); 847 | lpFist = (fistBalance * lpFee) / swapFee; 848 | fundAmount = fistBalance - lpFist; 849 | 850 | if (lpFist > 0) { 851 | FIST.transferFrom( 852 | address(_tokenDistributor), 853 | address(this), 854 | lpFist 855 | ); 856 | } 857 | 858 | if (fundAmount > 0) { 859 | FIST.transferFrom( 860 | address(_tokenDistributor), 861 | fundAddress, 862 | fundAmount 863 | ); 864 | } 865 | 866 | if (lpAmount > 0 && lpFist > 0) { 867 | try 868 | _swapRouter.addLiquidity( 869 | address(this), 870 | currency, 871 | lpAmount, 872 | lpFist, 873 | 0, 874 | 0, 875 | fundAddress, 876 | block.timestamp 877 | ) 878 | {} catch { 879 | emit Failed_AddLiquidity(); 880 | } 881 | } 882 | } 883 | } 884 | 885 | function _takeTransfer( 886 | address sender, 887 | address to, 888 | uint256 tAmount 889 | ) private { 890 | _balances[to] = _balances[to] + tAmount; 891 | emit Transfer(sender, to, tAmount); 892 | } 893 | 894 | function setSwapPairList(address addr, bool enable) external onlyOwner { 895 | _swapPairList[addr] = enable; 896 | } 897 | 898 | receive() external payable {} 899 | } 900 | -------------------------------------------------------------------------------- /contract/ERC20/HoldDividendBNB.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.7; 4 | 5 | interface IERC20 { 6 | function decimals() external view returns (uint8); 7 | 8 | function symbol() external view returns (string memory); 9 | 10 | function name() external view returns (string memory); 11 | 12 | function totalSupply() external view returns (uint256); 13 | 14 | function balanceOf(address account) external view returns (uint256); 15 | 16 | function transfer(address recipient, uint256 amount) external returns (bool); 17 | 18 | function allowance(address owner, address spender) external view returns (uint256); 19 | 20 | function approve(address spender, uint256 amount) external returns (bool); 21 | 22 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 23 | 24 | event Transfer(address indexed from, address indexed to, uint256 value); 25 | event Approval(address indexed owner, address indexed spender, uint256 value); 26 | } 27 | 28 | interface ISwapRouter { 29 | function factory() external pure returns (address); 30 | 31 | function WETH() external pure returns (address); 32 | 33 | function swapExactTokensForETHSupportingFeeOnTransferTokens( 34 | uint amountIn, 35 | uint amountOutMin, 36 | address[] calldata path, 37 | address to, 38 | uint deadline 39 | ) external; 40 | 41 | function addLiquidityETH( 42 | address token, 43 | uint amountTokenDesired, 44 | uint amountTokenMin, 45 | uint amountETHMin, 46 | address to, 47 | uint deadline 48 | ) external payable returns (uint amountToken, uint amountETH, uint liquidity); 49 | } 50 | 51 | interface ISwapFactory { 52 | function createPair(address tokenA, address tokenB) external returns (address pair); 53 | } 54 | 55 | abstract contract Ownable { 56 | address internal _owner; 57 | 58 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 59 | 60 | constructor () { 61 | address msgSender = msg.sender; 62 | _owner = msgSender; 63 | emit OwnershipTransferred(address(0), msgSender); 64 | } 65 | 66 | function owner() public view returns (address) { 67 | return _owner; 68 | } 69 | 70 | modifier onlyOwner() { 71 | require(_owner == msg.sender, "!owner"); 72 | _; 73 | } 74 | 75 | //放弃权限 76 | function renounceOwnership() public virtual onlyOwner { 77 | emit OwnershipTransferred(_owner, address(0)); 78 | _owner = address(0); 79 | } 80 | 81 | //转移权限 82 | function transferOwnership(address newOwner) public virtual onlyOwner { 83 | require(newOwner != address(0), "new is 0"); 84 | emit OwnershipTransferred(_owner, newOwner); 85 | _owner = newOwner; 86 | } 87 | } 88 | 89 | abstract contract AbsToken is IERC20, Ownable { 90 | mapping(address => uint256) private _balances; 91 | mapping(address => mapping(address => uint256)) private _allowances; 92 | 93 | address private fundAddress;//营销钱包地址 94 | 95 | string private _name; 96 | string private _symbol; 97 | uint8 private _decimals; 98 | 99 | mapping(address => bool) private _feeWhiteList;//交易税白名单 100 | 101 | uint256 private _tTotal; 102 | 103 | ISwapRouter private _swapRouter; 104 | address private _mainPair; 105 | 106 | bool private inSwap; 107 | uint256 private numTokensSellToFund; 108 | 109 | uint256 private constant MAX = ~uint256(0); 110 | uint256 private _marketFee; 111 | uint256 private _dividendFee; 112 | 113 | modifier lockTheSwap { 114 | inSwap = true; 115 | _; 116 | inSwap = false; 117 | } 118 | 119 | constructor (string memory Name, string memory Symbol, uint8 Decimals, uint256 Supply, address FundAddress, uint256 DividendFee, uint256 MarketFee){ 120 | _name = Name; 121 | _symbol = Symbol; 122 | _decimals = Decimals; 123 | 124 | //BSC PancakeSwap 路由地址 125 | ISwapRouter swapRouter = ISwapRouter(0x10ED43C718714eb63d5aA57B78B54704E256024E); 126 | _swapRouter = swapRouter; 127 | 128 | //创建BNB交易对 129 | ISwapFactory swapFactory = ISwapFactory(swapRouter.factory()); 130 | address mainPair = swapFactory.createPair(address(this), swapRouter.WETH()); 131 | _mainPair = mainPair; 132 | 133 | //将当前合约的代币授权给路由地址,授权最大值 134 | _allowances[address(this)][address(swapRouter)] = MAX; 135 | 136 | //总量 137 | uint256 total = Supply * 10 ** Decimals; 138 | _tTotal = total; 139 | 140 | //营销钱包加池子 141 | _balances[FundAddress] = total; 142 | emit Transfer(address(0), FundAddress, total); 143 | 144 | //营销钱包,暂时设置为合约部署的开发者地址 145 | fundAddress = FundAddress; 146 | 147 | //营销地址为手续费白名单 148 | _feeWhiteList[FundAddress] = true; 149 | _feeWhiteList[address(this)] = true; 150 | _feeWhiteList[address(swapRouter)] = true; 151 | _feeWhiteList[msg.sender] = true; 152 | _feeWhiteList[address(0x000000000000000000000000000000000000dEaD)] = true; 153 | 154 | //营销钱包卖出条件 总量的万分之一 155 | numTokensSellToFund = total / 10000; 156 | 157 | //排除 分红 158 | excludeHolder[address(0)] = true; 159 | excludeHolder[address(this)] = true; 160 | excludeHolder[address(mainPair)] = true; 161 | excludeHolder[address(0x000000000000000000000000000000000000dEaD)] = true; 162 | excludeHolder[address(swapRouter)] = true; 163 | //粉红锁仓合约地址 164 | excludeHolder[address(0x7ee058420e5937496F5a2096f04caA7721cF70cc)] = true; 165 | 166 | //合约地址里有 0.001 BNB 开始分红 167 | holderRewardCondition = 1000000000000000; 168 | //持有200万个才能参与分红 169 | holderCondition = 2000000 * 10 ** Decimals; 170 | 171 | //分红税和营销税 172 | _dividendFee = DividendFee; 173 | _marketFee = MarketFee; 174 | } 175 | 176 | function symbol() external view override returns (string memory) { 177 | return _symbol; 178 | } 179 | 180 | function name() external view override returns (string memory) { 181 | return _name; 182 | } 183 | 184 | function decimals() external view override returns (uint8) { 185 | return _decimals; 186 | } 187 | 188 | function totalSupply() external view override returns (uint256) { 189 | return _tTotal; 190 | } 191 | 192 | function balanceOf(address account) public view override returns (uint256) { 193 | return _balances[account]; 194 | } 195 | 196 | function transfer(address recipient, uint256 amount) public override returns (bool) { 197 | _transfer(msg.sender, recipient, amount); 198 | return true; 199 | } 200 | 201 | function allowance(address owner, address spender) public view override returns (uint256) { 202 | return _allowances[owner][spender]; 203 | } 204 | 205 | function approve(address spender, uint256 amount) public override returns (bool) { 206 | _approve(msg.sender, spender, amount); 207 | return true; 208 | } 209 | 210 | function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) { 211 | _transfer(sender, recipient, amount); 212 | if (_allowances[sender][msg.sender] != MAX) { 213 | _allowances[sender][msg.sender] = _allowances[sender][msg.sender] - amount; 214 | } 215 | return true; 216 | } 217 | 218 | function _approve(address owner, address spender, uint256 amount) private { 219 | _allowances[owner][spender] = amount; 220 | emit Approval(owner, spender, amount); 221 | } 222 | 223 | function _transfer( 224 | address from, 225 | address to, 226 | uint256 amount 227 | ) private { 228 | //地址卖不干净,留0.1 229 | if (amount == balanceOf(from)) { 230 | if (amount > 100000000000000000) { 231 | amount -= 100000000000000000; 232 | } else { 233 | amount = 0; 234 | } 235 | } 236 | 237 | //交易税 238 | uint256 txFee; 239 | 240 | //to == _mainPair 表示卖出,有人卖出时,合约达到卖出条件,合约先卖币换成BNB 241 | if (_mainPair == to && !_feeWhiteList[from]) { 242 | //兑换代币 243 | uint256 contractTokenBalance = balanceOf(address(this)); 244 | if ( 245 | contractTokenBalance >= numTokensSellToFund && 246 | !inSwap 247 | ) { 248 | swapTokenForFund(numTokensSellToFund); 249 | } 250 | } 251 | //不在手续费白名单,转账和交易需要扣税 252 | if (!_feeWhiteList[from] && !_feeWhiteList[to]) { 253 | //交易税 254 | txFee = _dividendFee + _marketFee; 255 | } 256 | _tokenTransfer(from, to, amount, txFee); 257 | //加入分红列表 258 | addHolder(to); 259 | addHolder(from); 260 | 261 | //分红 262 | if (from != address(this)) { 263 | processReward(500000); 264 | } 265 | } 266 | 267 | function _tokenTransfer( 268 | address sender, 269 | address recipient, 270 | uint256 tAmount, 271 | uint256 fee 272 | ) private { 273 | _balances[sender] = _balances[sender] - tAmount; 274 | uint256 feeAmount; 275 | //转账,交易 276 | //6%持币分BNB 2%营销 277 | if (fee > 0) { 278 | feeAmount = tAmount * fee / 100; 279 | //累计在合约里,等待时机卖出,分红 280 | _takeTransfer( 281 | sender, 282 | address(this), 283 | feeAmount 284 | ); 285 | } 286 | //接收者增加余额 287 | _takeTransfer(sender, recipient, tAmount - feeAmount); 288 | } 289 | 290 | function swapTokenForFund(uint256 tokenAmount) private lockTheSwap { 291 | uint256 initialBalance = address(this).balance; 292 | 293 | //6%持币分BNB 2%营销,将合约里的代币兑换为 BNB 294 | address[] memory path = new address[](2); 295 | path[0] = address(this); 296 | path[1] = _swapRouter.WETH(); 297 | _swapRouter.swapExactTokensForETHSupportingFeeOnTransferTokens( 298 | tokenAmount, 299 | 0, 300 | path, 301 | address(this), 302 | block.timestamp 303 | ); 304 | 305 | uint256 newBalance = address(this).balance - initialBalance; 306 | 307 | uint256 marketValue = newBalance * _marketFee / (_marketFee + _dividendFee); 308 | //营销钱包 309 | fundAddress.call{value : marketValue}(""); 310 | } 311 | 312 | function _takeTransfer( 313 | address sender, 314 | address to, 315 | uint256 tAmount 316 | ) private { 317 | _balances[to] = _balances[to] + tAmount; 318 | emit Transfer(sender, to, tAmount); 319 | } 320 | 321 | //设置营销钱包 322 | function setFundAddress(address addr) external onlyFunder { 323 | fundAddress = addr; 324 | _feeWhiteList[addr] = true; 325 | } 326 | 327 | //设置营销卖出条件及数量,具体数量就行,不需要精度 328 | function setFundSellAmount(uint256 amount) external onlyFunder { 329 | numTokensSellToFund = amount * 10 ** _decimals; 330 | } 331 | 332 | //修改分红税率 333 | function setDividendFee(uint256 fee) external onlyOwner { 334 | _dividendFee = fee; 335 | } 336 | 337 | //修改营销税率 338 | function setMarketFee(uint256 fee) external onlyOwner { 339 | _marketFee = fee; 340 | } 341 | 342 | //设置交易手续费白名单 343 | function setFeeWhiteList(address addr, bool enable) external onlyFunder { 344 | _feeWhiteList[addr] = enable; 345 | } 346 | 347 | //领取主链币余额 348 | function claimBalance() external { 349 | payable(fundAddress).transfer(address(this).balance); 350 | } 351 | 352 | //领取代币余额 353 | function claimToken(address token, uint256 amount) external { 354 | IERC20(token).transfer(fundAddress, amount); 355 | } 356 | 357 | //持币 分红 358 | address[] private holders; 359 | mapping(address => uint256) holderIndex; 360 | //排除分红 361 | mapping(address => bool) excludeHolder; 362 | 363 | //加入持有列表,发生转账时就加入 364 | function addHolder(address adr) private { 365 | uint256 size; 366 | assembly {size := extcodesize(adr)} 367 | //合约地址不参与分红 368 | if (size > 0) { 369 | return; 370 | } 371 | if (0 == holderIndex[adr]) { 372 | if (0 == holders.length || holders[0] != adr) { 373 | holderIndex[adr] = holders.length; 374 | holders.push(adr); 375 | } 376 | } 377 | } 378 | 379 | uint256 private currentIndex; 380 | uint256 private holderRewardCondition;//合约里达到这么多余额开始分红 381 | uint256 private holderCondition;//激活分红条件 382 | uint256 private progressRewardBlock; 383 | 384 | //执行分红,使用 gas gasLimit 去执行分红 385 | //间隔 10 分钟分红一次 386 | function processReward(uint256 gas) private { 387 | if (progressRewardBlock + 200 > block.number) { 388 | return; 389 | } 390 | 391 | //当前合约余额 392 | uint256 balance = address(this).balance; 393 | if (balance < holderRewardCondition) { 394 | return; 395 | } 396 | 397 | address shareHolder; 398 | uint256 tokenBalance; 399 | uint256 amount; 400 | 401 | uint256 shareholderCount = holders.length; 402 | 403 | uint256 gasUsed = 0; 404 | uint256 iterations = 0; 405 | uint256 gasLeft = gasleft(); 406 | 407 | while (gasUsed < gas && iterations < shareholderCount) { 408 | if (currentIndex >= shareholderCount) { 409 | currentIndex = 0; 410 | } 411 | shareHolder = holders[currentIndex]; 412 | tokenBalance = balanceOf(shareHolder); 413 | //不在排除列表,才分红 414 | if (tokenBalance > holderCondition && !excludeHolder[shareHolder]) { 415 | amount = balance * tokenBalance / _tTotal; 416 | if (amount > 0) { 417 | shareHolder.call{value : amount}(""); 418 | } 419 | } 420 | 421 | gasUsed = gasUsed + (gasLeft - gasleft()); 422 | gasLeft = gasleft(); 423 | currentIndex++; 424 | iterations++; 425 | } 426 | 427 | progressRewardBlock = block.number; 428 | } 429 | 430 | //设置分红的合约余额条件,即合约里的余额达到该值才分红 431 | function setHolderRewardCondition(uint256 amount) external onlyFunder { 432 | holderRewardCondition = amount; 433 | } 434 | 435 | //设置分红的持币条件,默认 2000000 436 | function setHolderCondition(uint256 amount) external onlyFunder { 437 | holderCondition = amount * 10 ** _decimals; 438 | } 439 | 440 | //是否排除分红 441 | function setExcludeHolder(address addr, bool enable) external onlyFunder { 442 | excludeHolder[addr] = enable; 443 | } 444 | 445 | modifier onlyFunder() { 446 | require(_owner == msg.sender || fundAddress == msg.sender, "!Funder"); 447 | _; 448 | } 449 | 450 | receive() external payable { 451 | 452 | } 453 | } 454 | 455 | contract DividendBNB is AbsToken { 456 | constructor() AbsToken( 457 | "HoldDividendBNB", 458 | "HDB", 459 | 18, 460 | 100000000000, 461 | //营销钱包,也是代币接收地址 462 | address(0x344Efc334e084477AF5539E7287C6AEd2CE835EF), 463 | //分红税率 464 | 6, 465 | //营销税率 466 | 2 467 | ){ 468 | 469 | } 470 | } -------------------------------------------------------------------------------- /contract/ERC20/HoldDividendToken.txt: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | 5 | interface IERC20 { 6 | /** 7 | * @dev Returns the amount of tokens in existence. 8 | */ 9 | function totalSupply() external view returns (uint256); 10 | 11 | /** 12 | * @dev Returns the amount of tokens owned by `account`. 13 | */ 14 | function balanceOf(address account) external view returns (uint256); 15 | 16 | /** 17 | * @dev Moves `amount` tokens from the caller's account to `recipient`. 18 | * 19 | * Returns a boolean value indicating whether the operation succeeded. 20 | * 21 | * Emits a {Transfer} event. 22 | */ 23 | function transfer(address recipient, uint256 amount) external returns (bool); 24 | 25 | /** 26 | * @dev Returns the remaining number of tokens that `spender` will be 27 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 28 | * zero by default. 29 | * 30 | * This value changes when {approve} or {transferFrom} are called. 31 | */ 32 | function allowance(address owner, address spender) external view returns (uint256); 33 | 34 | /** 35 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 36 | * 37 | * Returns a boolean value indicating whether the operation succeeded. 38 | * 39 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 40 | * that someone may use both the old and the new allowance by unfortunate 41 | * transaction ordering. One possible solution to mitigate this race 42 | * condition is to first reduce the spender's allowance to 0 and set the 43 | * desired value afterwards: 44 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 45 | * 46 | * Emits an {Approval} event. 47 | */ 48 | function approve(address spender, uint256 amount) external returns (bool); 49 | 50 | /** 51 | * @dev Moves `amount` tokens from `sender` to `recipient` using the 52 | * allowance mechanism. `amount` is then deducted from the caller's 53 | * allowance. 54 | * 55 | * Returns a boolean value indicating whether the operation succeeded. 56 | * 57 | * Emits a {Transfer} event. 58 | */ 59 | function transferFrom( 60 | address sender, 61 | address recipient, 62 | uint256 amount 63 | ) external returns (bool); 64 | 65 | /** 66 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 67 | * another (`to`). 68 | * 69 | * Note that `value` may be zero. 70 | */ 71 | event Transfer(address indexed from, address indexed to, uint256 value); 72 | 73 | /** 74 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 75 | * a call to {approve}. `value` is the new allowance. 76 | */ 77 | event Approval(address indexed owner, address indexed spender, uint256 value); 78 | } 79 | 80 | 81 | abstract contract Context { 82 | function _msgSender() internal view virtual returns (address) { 83 | return msg.sender; 84 | } 85 | 86 | function _msgData() internal view virtual returns (bytes calldata) { 87 | this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 88 | return msg.data; 89 | } 90 | } 91 | 92 | interface IUniswapV2Router01 { 93 | function factory() external pure returns (address); 94 | function WETH() external pure returns (address); 95 | 96 | function addLiquidity( 97 | address tokenA, 98 | address tokenB, 99 | uint amountADesired, 100 | uint amountBDesired, 101 | uint amountAMin, 102 | uint amountBMin, 103 | address to, 104 | uint deadline 105 | ) external returns (uint amountA, uint amountB, uint liquidity); 106 | function addLiquidityETH( 107 | address token, 108 | uint amountTokenDesired, 109 | uint amountTokenMin, 110 | uint amountETHMin, 111 | address to, 112 | uint deadline 113 | ) external payable returns (uint amountToken, uint amountETH, uint liquidity); 114 | function removeLiquidity( 115 | address tokenA, 116 | address tokenB, 117 | uint liquidity, 118 | uint amountAMin, 119 | uint amountBMin, 120 | address to, 121 | uint deadline 122 | ) external returns (uint amountA, uint amountB); 123 | function removeLiquidityETH( 124 | address token, 125 | uint liquidity, 126 | uint amountTokenMin, 127 | uint amountETHMin, 128 | address to, 129 | uint deadline 130 | ) external returns (uint amountToken, uint amountETH); 131 | function removeLiquidityWithPermit( 132 | address tokenA, 133 | address tokenB, 134 | uint liquidity, 135 | uint amountAMin, 136 | uint amountBMin, 137 | address to, 138 | uint deadline, 139 | bool approveMax, uint8 v, bytes32 r, bytes32 s 140 | ) external returns (uint amountA, uint amountB); 141 | function removeLiquidityETHWithPermit( 142 | address token, 143 | uint liquidity, 144 | uint amountTokenMin, 145 | uint amountETHMin, 146 | address to, 147 | uint deadline, 148 | bool approveMax, uint8 v, bytes32 r, bytes32 s 149 | ) external returns (uint amountToken, uint amountETH); 150 | function swapExactTokensForTokens( 151 | uint amountIn, 152 | uint amountOutMin, 153 | address[] calldata path, 154 | address to, 155 | uint deadline 156 | ) external returns (uint[] memory amounts); 157 | function swapTokensForExactTokens( 158 | uint amountOut, 159 | uint amountInMax, 160 | address[] calldata path, 161 | address to, 162 | uint deadline 163 | ) external returns (uint[] memory amounts); 164 | function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) 165 | external 166 | payable 167 | returns (uint[] memory amounts); 168 | function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) 169 | external 170 | returns (uint[] memory amounts); 171 | function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) 172 | external 173 | returns (uint[] memory amounts); 174 | function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) 175 | external 176 | payable 177 | returns (uint[] memory amounts); 178 | 179 | function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); 180 | function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); 181 | function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); 182 | function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); 183 | function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); 184 | } 185 | 186 | interface IUniswapV2Router02 is IUniswapV2Router01 { 187 | function removeLiquidityETHSupportingFeeOnTransferTokens( 188 | address token, 189 | uint liquidity, 190 | uint amountTokenMin, 191 | uint amountETHMin, 192 | address to, 193 | uint deadline 194 | ) external returns (uint amountETH); 195 | function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( 196 | address token, 197 | uint liquidity, 198 | uint amountTokenMin, 199 | uint amountETHMin, 200 | address to, 201 | uint deadline, 202 | bool approveMax, uint8 v, bytes32 r, bytes32 s 203 | ) external returns (uint amountETH); 204 | 205 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 206 | uint amountIn, 207 | uint amountOutMin, 208 | address[] calldata path, 209 | address to, 210 | uint deadline 211 | ) external; 212 | function swapExactETHForTokensSupportingFeeOnTransferTokens( 213 | uint amountOutMin, 214 | address[] calldata path, 215 | address to, 216 | uint deadline 217 | ) external payable; 218 | function swapExactTokensForETHSupportingFeeOnTransferTokens( 219 | uint amountIn, 220 | uint amountOutMin, 221 | address[] calldata path, 222 | address to, 223 | uint deadline 224 | ) external; 225 | } 226 | 227 | interface IUniswapV2Factory { 228 | event PairCreated(address indexed token0, address indexed token1, address pair, uint); 229 | 230 | function feeTo() external view returns (address); 231 | function feeToSetter() external view returns (address); 232 | 233 | function getPair(address tokenA, address tokenB) external view returns (address pair); 234 | function allPairs(uint) external view returns (address pair); 235 | function allPairsLength() external view returns (uint); 236 | 237 | function createPair(address tokenA, address tokenB) external returns (address pair); 238 | 239 | function setFeeTo(address) external; 240 | function setFeeToSetter(address) external; 241 | } 242 | 243 | interface IUniswapV2Pair { 244 | event Approval(address indexed owner, address indexed spender, uint value); 245 | event Transfer(address indexed from, address indexed to, uint value); 246 | 247 | function name() external pure returns (string memory); 248 | function symbol() external pure returns (string memory); 249 | function decimals() external pure returns (uint8); 250 | function totalSupply() external view returns (uint); 251 | function balanceOf(address owner) external view returns (uint); 252 | function allowance(address owner, address spender) external view returns (uint); 253 | 254 | function approve(address spender, uint value) external returns (bool); 255 | function transfer(address to, uint value) external returns (bool); 256 | function transferFrom(address from, address to, uint value) external returns (bool); 257 | 258 | function DOMAIN_SEPARATOR() external view returns (bytes32); 259 | function PERMIT_TYPEHASH() external pure returns (bytes32); 260 | function nonces(address owner) external view returns (uint); 261 | 262 | function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; 263 | 264 | event Creation(address indexed sender, uint amount0, uint amount1); 265 | event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); 266 | event Swap( 267 | address indexed sender, 268 | uint amount0In, 269 | uint amount1In, 270 | uint amount0Out, 271 | uint amount1Out, 272 | address indexed to 273 | ); 274 | event Sync(uint112 reserve0, uint112 reserve1); 275 | 276 | function MINIMUM_LIQUIDITY() external pure returns (uint); 277 | function factory() external view returns (address); 278 | function token0() external view returns (address); 279 | function token1() external view returns (address); 280 | function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); 281 | function price0CumulativeLast() external view returns (uint); 282 | function price1CumulativeLast() external view returns (uint); 283 | function kLast() external view returns (uint); 284 | 285 | function creation(address to) external returns (uint liquidity); 286 | function burn(address to) external returns (uint amount0, uint amount1); 287 | function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; 288 | function skim(address to) external; 289 | function sync() external; 290 | 291 | function initialize(address, address) external; 292 | } 293 | 294 | interface IERC20Metadata is IERC20 { 295 | /** 296 | * @dev Returns the name of the token. 297 | */ 298 | function name() external view returns (string memory); 299 | 300 | /** 301 | * @dev Returns the symbol of the token. 302 | */ 303 | function symbol() external view returns (string memory); 304 | 305 | /** 306 | * @dev Returns the decimals places of the token. 307 | */ 308 | function decimals() external view returns (uint8); 309 | } 310 | 311 | contract Ownable is Context { 312 | address private _owner; 313 | 314 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 315 | 316 | constructor () { 317 | address msgSender = _msgSender(); 318 | _owner = msgSender; 319 | emit OwnershipTransferred(address(0), msgSender); 320 | } 321 | 322 | function owner() public view returns (address) { 323 | return _owner; 324 | } 325 | 326 | modifier onlyOwner() { 327 | require(_owner == _msgSender(), "Ownable: caller is not the owner"); 328 | _; 329 | } 330 | 331 | function renounceOwnership() public virtual onlyOwner { 332 | emit OwnershipTransferred(_owner, address(0)); 333 | _owner = address(0); 334 | } 335 | 336 | function transferOwnership(address newOwner) public virtual onlyOwner { 337 | require(newOwner != address(0), "Ownable: new owner is the zero address"); 338 | emit OwnershipTransferred(_owner, newOwner); 339 | _owner = newOwner; 340 | } 341 | } 342 | 343 | library SafeMath { 344 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 345 | uint256 c = a + b; 346 | require(c >= a, "SafeMath: addition overflow"); 347 | 348 | return c; 349 | } 350 | 351 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 352 | return sub(a, b, "SafeMath: subtraction overflow"); 353 | } 354 | 355 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 356 | require(b <= a, errorMessage); 357 | uint256 c = a - b; 358 | 359 | return c; 360 | } 361 | 362 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 363 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 364 | // benefit is lost if 'b' is also tested. 365 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 366 | if (a == 0) { 367 | return 0; 368 | } 369 | 370 | uint256 c = a * b; 371 | require(c / a == b, "SafeMath: multiplication overflow"); 372 | 373 | return c; 374 | } 375 | 376 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 377 | return div(a, b, "SafeMath: division by zero"); 378 | } 379 | 380 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 381 | require(b > 0, errorMessage); 382 | uint256 c = a / b; 383 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 384 | 385 | return c; 386 | } 387 | 388 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 389 | return mod(a, b, "SafeMath: modulo by zero"); 390 | } 391 | 392 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 393 | require(b != 0, errorMessage); 394 | return a % b; 395 | } 396 | } 397 | 398 | library SafeMathInt { 399 | int256 private constant MIN_INT256 = int256(1) << 255; 400 | int256 private constant MAX_INT256 = ~(int256(1) << 255); 401 | 402 | /** 403 | * @dev Multiplies two int256 variables and fails on overflow. 404 | */ 405 | function mul(int256 a, int256 b) internal pure returns (int256) { 406 | int256 c = a * b; 407 | 408 | // Detect overflow when multiplying MIN_INT256 with -1 409 | require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256)); 410 | require((b == 0) || (c / b == a)); 411 | return c; 412 | } 413 | 414 | /** 415 | * @dev Division of two int256 variables and fails on overflow. 416 | */ 417 | function div(int256 a, int256 b) internal pure returns (int256) { 418 | // Prevent overflow when dividing MIN_INT256 by -1 419 | require(b != -1 || a != MIN_INT256); 420 | 421 | // Solidity already throws when dividing by 0. 422 | return a / b; 423 | } 424 | 425 | /** 426 | * @dev Subtracts two int256 variables and fails on overflow. 427 | */ 428 | function sub(int256 a, int256 b) internal pure returns (int256) { 429 | int256 c = a - b; 430 | require((b >= 0 && c <= a) || (b < 0 && c > a)); 431 | return c; 432 | } 433 | 434 | /** 435 | * @dev Adds two int256 variables and fails on overflow. 436 | */ 437 | function add(int256 a, int256 b) internal pure returns (int256) { 438 | int256 c = a + b; 439 | require((b >= 0 && c >= a) || (b < 0 && c < a)); 440 | return c; 441 | } 442 | 443 | /** 444 | * @dev Converts to absolute value, and fails on overflow. 445 | */ 446 | function abs(int256 a) internal pure returns (int256) { 447 | require(a != MIN_INT256); 448 | return a < 0 ? -a : a; 449 | } 450 | 451 | 452 | function toUint256Safe(int256 a) internal pure returns (uint256) { 453 | require(a >= 0); 454 | return uint256(a); 455 | } 456 | } 457 | 458 | library SafeMathUint { 459 | function toInt256Safe(uint256 a) internal pure returns (int256) { 460 | int256 b = int256(a); 461 | require(b >= 0); 462 | return b; 463 | } 464 | } 465 | 466 | contract ERC20 is Context, IERC20, IERC20Metadata { 467 | using SafeMath for uint256; 468 | 469 | mapping(address => uint256) private _balances; 470 | 471 | mapping(address => mapping(address => uint256)) private _allowances; 472 | 473 | uint256 private _totalSupply; 474 | 475 | string private _name; 476 | string private _symbol; 477 | 478 | /** 479 | * @dev Sets the values for {name} and {symbol}. 480 | * 481 | * The default value of {decimals} is 18. To select a different value for 482 | * {decimals} you should overload it. 483 | * 484 | * All two of these values are immutable: they can only be set once during 485 | * construction. 486 | */ 487 | constructor(string memory name_, string memory symbol_) { 488 | _name = name_; 489 | _symbol = symbol_; 490 | } 491 | 492 | /** 493 | * @dev Returns the name of the token. 494 | */ 495 | function name() public view virtual override returns (string memory) { 496 | return _name; 497 | } 498 | 499 | /** 500 | * @dev Returns the symbol of the token, usually a shorter version of the 501 | * name. 502 | */ 503 | function symbol() public view virtual override returns (string memory) { 504 | return _symbol; 505 | } 506 | 507 | /** 508 | * @dev Returns the number of decimals used to get its user representation. 509 | * For example, if `decimals` equals `2`, a balance of `505` tokens should 510 | * be displayed to a user as `5,05` (`505 / 10 ** 2`). 511 | * 512 | * Tokens usually opt for a value of 18, imitating the relationship between 513 | * Ether and Wei. This is the value {ERC20} uses, unless this function is 514 | * overridden; 515 | * 516 | * NOTE: This information is only used for _display_ purposes: it in 517 | * no way affects any of the arithmetic of the contract, including 518 | * {IERC20-balanceOf} and {IERC20-transfer}. 519 | */ 520 | function decimals() public view virtual override returns (uint8) { 521 | return 18; 522 | } 523 | 524 | /** 525 | * @dev See {IERC20-totalSupply}. 526 | */ 527 | function totalSupply() public view virtual override returns (uint256) { 528 | return _totalSupply; 529 | } 530 | 531 | /** 532 | * @dev See {IERC20-balanceOf}. 533 | */ 534 | function balanceOf(address account) public view virtual override returns (uint256) { 535 | return _balances[account]; 536 | } 537 | 538 | /** 539 | * @dev See {IERC20-transfer}. 540 | * 541 | * Requirements: 542 | * 543 | * - `recipient` cannot be the zero address. 544 | * - the caller must have a balance of at least `amount`. 545 | */ 546 | function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 547 | _transfer(_msgSender(), recipient, amount); 548 | return true; 549 | } 550 | 551 | /** 552 | * @dev See {IERC20-allowance}. 553 | */ 554 | function allowance(address owner, address spender) public view virtual override returns (uint256) { 555 | return _allowances[owner][spender]; 556 | } 557 | 558 | /** 559 | * @dev See {IERC20-approve}. 560 | * 561 | * Requirements: 562 | * 563 | * - `spender` cannot be the zero address. 564 | */ 565 | function approve(address spender, uint256 amount) public virtual override returns (bool) { 566 | _approve(_msgSender(), spender, amount); 567 | return true; 568 | } 569 | 570 | /** 571 | * @dev See {IERC20-transferFrom}. 572 | * 573 | * Emits an {Approval} event indicating the updated allowance. This is not 574 | * required by the EIP. See the note at the beginning of {ERC20}. 575 | * 576 | * Requirements: 577 | * 578 | * - `sender` and `recipient` cannot be the zero address. 579 | * - `sender` must have a balance of at least `amount`. 580 | * - the caller must have allowance for ``sender``'s tokens of at least 581 | * `amount`. 582 | */ 583 | function transferFrom( 584 | address sender, 585 | address recipient, 586 | uint256 amount 587 | ) public virtual override returns (bool) { 588 | _transfer(sender, recipient, amount); 589 | _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 590 | return true; 591 | } 592 | 593 | /** 594 | * @dev Atomically increases the allowance granted to `spender` by the caller. 595 | * 596 | * This is an alternative to {approve} that can be used as a mitigation for 597 | * problems described in {IERC20-approve}. 598 | * 599 | * Emits an {Approval} event indicating the updated allowance. 600 | * 601 | * Requirements: 602 | * 603 | * - `spender` cannot be the zero address. 604 | */ 605 | function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 606 | _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 607 | return true; 608 | } 609 | 610 | /** 611 | * @dev Atomically decreases the allowance granted to `spender` by the caller. 612 | * 613 | * This is an alternative to {approve} that can be used as a mitigation for 614 | * problems described in {IERC20-approve}. 615 | * 616 | * Emits an {Approval} event indicating the updated allowance. 617 | * 618 | * Requirements: 619 | * 620 | * - `spender` cannot be the zero address. 621 | * - `spender` must have allowance for the caller of at least 622 | * `subtractedValue`. 623 | */ 624 | function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 625 | _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 626 | return true; 627 | } 628 | 629 | /** 630 | * @dev Moves tokens `amount` from `sender` to `recipient`. 631 | * 632 | * This is internal function is equivalent to {transfer}, and can be used to 633 | * e.g. implement automatic token fees, slashing mechanisms, etc. 634 | * 635 | * Emits a {Transfer} event. 636 | * 637 | * Requirements: 638 | * 639 | * - `sender` cannot be the zero address. 640 | * - `recipient` cannot be the zero address. 641 | * - `sender` must have a balance of at least `amount`. 642 | */ 643 | function _transfer( 644 | address sender, 645 | address recipient, 646 | uint256 amount 647 | ) internal virtual { 648 | require(sender != address(0), "ERC20: transfer from the zero address"); 649 | require(recipient != address(0), "ERC20: transfer to the zero address"); 650 | 651 | _beforeTokenTransfer(sender, recipient, amount); 652 | 653 | _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 654 | _balances[recipient] = _balances[recipient].add(amount); 655 | emit Transfer(sender, recipient, amount); 656 | } 657 | 658 | /** @dev Creates `amount` tokens and assigns them to `account`, increasing 659 | * the total supply. 660 | * 661 | * Emits a {Transfer} event with `from` set to the zero address. 662 | * 663 | * Requirements: 664 | * 665 | * - `account` cannot be the zero address. 666 | */ 667 | function _creation(address account, uint256 amount) internal virtual { 668 | require(account != address(0), "ERC20: creation to the zero address"); 669 | 670 | _beforeTokenTransfer(address(0), account, amount); 671 | 672 | _totalSupply = _totalSupply.add(amount); 673 | _balances[account] = _balances[account].add(amount); 674 | emit Transfer(address(0), account, amount); 675 | } 676 | 677 | /** 678 | * @dev Destroys `amount` tokens from `account`, reducing the 679 | * total supply. 680 | * 681 | * Emits a {Transfer} event with `to` set to the zero address. 682 | * 683 | * Requirements: 684 | * 685 | * - `account` cannot be the zero address. 686 | * - `account` must have at least `amount` tokens. 687 | */ 688 | function _burn(address account, uint256 amount) internal virtual { 689 | require(account != address(0), "ERC20: burn from the zero address"); 690 | 691 | _beforeTokenTransfer(account, address(0), amount); 692 | 693 | _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 694 | _totalSupply = _totalSupply.sub(amount); 695 | emit Transfer(account, address(0), amount); 696 | } 697 | 698 | /** 699 | * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 700 | * 701 | * This internal function is equivalent to `approve`, and can be used to 702 | * e.g. set automatic allowances for certain subsystems, etc. 703 | * 704 | * Emits an {Approval} event. 705 | * 706 | * Requirements: 707 | * 708 | * - `owner` cannot be the zero address. 709 | * - `spender` cannot be the zero address. 710 | */ 711 | function _approve( 712 | address owner, 713 | address spender, 714 | uint256 amount 715 | ) internal virtual { 716 | require(owner != address(0), "ERC20: approve from the zero address"); 717 | require(spender != address(0), "ERC20: approve to the zero address"); 718 | 719 | _allowances[owner][spender] = amount; 720 | emit Approval(owner, spender, amount); 721 | } 722 | 723 | /** 724 | * @dev Hook that is called before any transfer of tokens. This includes 725 | * creationing and burning. 726 | * 727 | * Calling conditions: 728 | * 729 | * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 730 | * will be to transferred to `to`. 731 | * - when `from` is zero, `amount` tokens will be creationed for `to`. 732 | * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 733 | * - `from` and `to` are never both zero. 734 | * 735 | * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 736 | */ 737 | function _beforeTokenTransfer( 738 | address from, 739 | address to, 740 | uint256 amount 741 | ) internal virtual {} 742 | } 743 | 744 | interface DividendPayingTokenInterface { 745 | /// @notice View the amount of dividend in wei that an address can withdraw. 746 | /// @param _owner The address of a token holder. 747 | /// @return The amount of dividend in wei that `_owner` can withdraw. 748 | function dividendOf(address _owner) external view returns(uint256); 749 | 750 | 751 | /// @notice Withdraws the ether distributed to the sender. 752 | /// @dev SHOULD transfer `dividendOf(msg.sender)` wei to `msg.sender`, and `dividendOf(msg.sender)` SHOULD be 0 after the transfer. 753 | /// MUST emit a `DividendWithdrawn` event if the amount of ether transferred is greater than 0. 754 | function withdrawDividend() external; 755 | 756 | /// @dev This event MUST emit when ether is distributed to token holders. 757 | /// @param from The address which sends ether to this contract. 758 | /// @param weiAmount The amount of distributed ether in wei. 759 | event DividendsDistributed( 760 | address indexed from, 761 | uint256 weiAmount 762 | ); 763 | 764 | /// @dev This event MUST emit when an address withdraws their dividend. 765 | /// @param to The address which withdraws ether from this contract. 766 | /// @param weiAmount The amount of withdrawn ether in wei. 767 | event DividendWithdrawn( 768 | address indexed to, 769 | uint256 weiAmount 770 | ); 771 | } 772 | 773 | interface DividendPayingTokenOptionalInterface { 774 | /// @notice View the amount of dividend in wei that an address can withdraw. 775 | /// @param _owner The address of a token holder. 776 | /// @return The amount of dividend in wei that `_owner` can withdraw. 777 | function withdrawableDividendOf(address _owner) external view returns(uint256); 778 | 779 | /// @notice View the amount of dividend in wei that an address has withdrawn. 780 | /// @param _owner The address of a token holder. 781 | /// @return The amount of dividend in wei that `_owner` has withdrawn. 782 | function withdrawnDividendOf(address _owner) external view returns(uint256); 783 | 784 | /// @notice View the amount of dividend in wei that an address has earned in total. 785 | /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner) 786 | /// @param _owner The address of a token holder. 787 | /// @return The amount of dividend in wei that `_owner` has earned in total. 788 | function accumulativeDividendOf(address _owner) external view returns(uint256); 789 | } 790 | 791 | contract DividendPayingToken is ERC20, Ownable, DividendPayingTokenInterface, DividendPayingTokenOptionalInterface { 792 | using SafeMath for uint256; 793 | using SafeMathUint for uint256; 794 | using SafeMathInt for int256; 795 | 796 | address public REWARD_TOKEN; 797 | 798 | // With `magnitude`, we can properly distribute dividends even if the amount of received ether is small. 799 | // For more discussion about choosing the value of `magnitude`, 800 | // see https://github.com/ethereum/EIPs/issues/1726#issuecomment-472352728 801 | uint256 constant internal magnitude = 2**128; 802 | 803 | uint256 internal magnifiedDividendPerShare; 804 | 805 | // About dividendCorrection: 806 | // If the token balance of a `_user` is never changed, the dividend of `_user` can be computed with: 807 | // `dividendOf(_user) = dividendPerShare * balanceOf(_user)`. 808 | // When `balanceOf(_user)` is changed (via creationing/burning/transferring tokens), 809 | // `dividendOf(_user)` should not be changed, 810 | // but the computed value of `dividendPerShare * balanceOf(_user)` is changed. 811 | // To keep the `dividendOf(_user)` unchanged, we add a correction term: 812 | // `dividendOf(_user) = dividendPerShare * balanceOf(_user) + dividendCorrectionOf(_user)`, 813 | // where `dividendCorrectionOf(_user)` is updated whenever `balanceOf(_user)` is changed: 814 | // `dividendCorrectionOf(_user) = dividendPerShare * (old balanceOf(_user)) - (new balanceOf(_user))`. 815 | // So now `dividendOf(_user)` returns the same value before and after `balanceOf(_user)` is changed. 816 | mapping(address => int256) internal magnifiedDividendCorrections; 817 | mapping(address => uint256) internal withdrawnDividends; 818 | 819 | uint256 public totalDividendsDistributed; 820 | 821 | constructor(string memory _name, string memory _symbol, address _rewardTokenAddress) ERC20(_name, _symbol) { 822 | REWARD_TOKEN = _rewardTokenAddress; 823 | } 824 | 825 | 826 | function distributeCAKEDividends(uint256 amount) public onlyOwner{ 827 | require(totalSupply() > 0); 828 | 829 | if (amount > 0) { 830 | magnifiedDividendPerShare = magnifiedDividendPerShare.add( 831 | (amount).mul(magnitude) / totalSupply() 832 | ); 833 | emit DividendsDistributed(msg.sender, amount); 834 | 835 | totalDividendsDistributed = totalDividendsDistributed.add(amount); 836 | } 837 | } 838 | 839 | /// @notice Withdraws the ether distributed to the sender. 840 | /// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0. 841 | function withdrawDividend() public virtual override { 842 | _withdrawDividendOfUser(payable(msg.sender)); 843 | } 844 | 845 | /// @notice Withdraws the ether distributed to the sender. 846 | /// @dev It emits a `DividendWithdrawn` event if the amount of withdrawn ether is greater than 0. 847 | function _withdrawDividendOfUser(address payable user) internal returns (uint256) { 848 | uint256 _withdrawableDividend = withdrawableDividendOf(user); 849 | if (_withdrawableDividend > 0) { 850 | withdrawnDividends[user] = withdrawnDividends[user].add(_withdrawableDividend); 851 | emit DividendWithdrawn(user, _withdrawableDividend); 852 | bool success = IERC20(REWARD_TOKEN).transfer(user, _withdrawableDividend); 853 | 854 | if(!success) { 855 | withdrawnDividends[user] = withdrawnDividends[user].sub(_withdrawableDividend); 856 | return 0; 857 | } 858 | 859 | return _withdrawableDividend; 860 | } 861 | 862 | return 0; 863 | } 864 | 865 | 866 | /// @notice View the amount of dividend in wei that an address can withdraw. 867 | /// @param _owner The address of a token holder. 868 | /// @return The amount of dividend in wei that `_owner` can withdraw. 869 | function dividendOf(address _owner) public view override returns(uint256) { 870 | return withdrawableDividendOf(_owner); 871 | } 872 | 873 | /// @notice View the amount of dividend in wei that an address can withdraw. 874 | /// @param _owner The address of a token holder. 875 | /// @return The amount of dividend in wei that `_owner` can withdraw. 876 | function withdrawableDividendOf(address _owner) public view override returns(uint256) { 877 | return accumulativeDividendOf(_owner).sub(withdrawnDividends[_owner]); 878 | } 879 | 880 | /// @notice View the amount of dividend in wei that an address has withdrawn. 881 | /// @param _owner The address of a token holder. 882 | /// @return The amount of dividend in wei that `_owner` has withdrawn. 883 | function withdrawnDividendOf(address _owner) public view override returns(uint256) { 884 | return withdrawnDividends[_owner]; 885 | } 886 | 887 | 888 | /// @notice View the amount of dividend in wei that an address has earned in total. 889 | /// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner) 890 | /// = (magnifiedDividendPerShare * balanceOf(_owner) + magnifiedDividendCorrections[_owner]) / magnitude 891 | /// @param _owner The address of a token holder. 892 | /// @return The amount of dividend in wei that `_owner` has earned in total. 893 | function accumulativeDividendOf(address _owner) public view override returns(uint256) { 894 | return magnifiedDividendPerShare.mul(balanceOf(_owner)).toInt256Safe() 895 | .add(magnifiedDividendCorrections[_owner]).toUint256Safe() / magnitude; 896 | } 897 | 898 | /// @dev Internal function that transfer tokens from one address to another. 899 | /// Update magnifiedDividendCorrections to keep dividends unchanged. 900 | /// @param from The address to transfer from. 901 | /// @param to The address to transfer to. 902 | /// @param value The amount to be transferred. 903 | function _transfer(address from, address to, uint256 value) internal virtual override { 904 | require(false); 905 | 906 | int256 _magCorrection = magnifiedDividendPerShare.mul(value).toInt256Safe(); 907 | magnifiedDividendCorrections[from] = magnifiedDividendCorrections[from].add(_magCorrection); 908 | magnifiedDividendCorrections[to] = magnifiedDividendCorrections[to].sub(_magCorrection); 909 | } 910 | 911 | /// @dev Internal function that creations tokens to an account. 912 | /// Update magnifiedDividendCorrections to keep dividends unchanged. 913 | /// @param account The account that will receive the created tokens. 914 | /// @param value The amount that will be created. 915 | function _creation(address account, uint256 value) internal override { 916 | super._creation(account, value); 917 | 918 | magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account] 919 | .sub( (magnifiedDividendPerShare.mul(value)).toInt256Safe() ); 920 | } 921 | 922 | /// @dev Internal function that burns an amount of the token of a given account. 923 | /// Update magnifiedDividendCorrections to keep dividends unchanged. 924 | /// @param account The account whose tokens will be burnt. 925 | /// @param value The amount that will be burnt. 926 | function _burn(address account, uint256 value) internal override { 927 | super._burn(account, value); 928 | 929 | magnifiedDividendCorrections[account] = magnifiedDividendCorrections[account] 930 | .add( (magnifiedDividendPerShare.mul(value)).toInt256Safe() ); 931 | } 932 | 933 | function _setBalance(address account, uint256 newBalance) internal { 934 | uint256 currentBalance = balanceOf(account); 935 | 936 | if(newBalance > currentBalance) { 937 | uint256 creationAmount = newBalance.sub(currentBalance); 938 | _creation(account, creationAmount); 939 | } else if(newBalance < currentBalance) { 940 | uint256 burnAmount = currentBalance.sub(newBalance); 941 | _burn(account, burnAmount); 942 | } 943 | } 944 | } 945 | 946 | contract TokenDividendTracker is Ownable, DividendPayingToken { 947 | using SafeMath for uint256; 948 | using SafeMathInt for int256; 949 | 950 | struct MAP { 951 | address[] keys; 952 | mapping(address => uint) values; 953 | mapping(address => uint) indexOf; 954 | mapping(address => bool) inserted; 955 | } 956 | 957 | MAP private tokenHoldersMap; 958 | uint256 public lastProcessedIndex; 959 | 960 | mapping (address => bool) public excludedFromDividends; 961 | 962 | mapping (address => uint256) public lastClaimTimes; 963 | 964 | uint256 public claimWait; 965 | uint256 public minimumTokenBalanceForDividends; 966 | 967 | event ExcludeFromDividends(address indexed account); 968 | event ClaimWaitUpdated(uint256 indexed newValue, uint256 indexed oldValue); 969 | 970 | event Claim(address indexed account, uint256 amount, bool indexed automatic); 971 | 972 | constructor(address _rewardTokenAddress, uint256 _minimumTokenBalanceForDividends) DividendPayingToken("Dividen_Tracker", "Dividend_Tracker", _rewardTokenAddress) { 973 | claimWait = 3600; 974 | minimumTokenBalanceForDividends = _minimumTokenBalanceForDividends; 975 | } 976 | 977 | function _transfer(address, address, uint256) internal pure override { 978 | require(false, "Dividend_Tracker: No transfers allowed"); 979 | } 980 | 981 | function withdrawDividend() public pure override { 982 | require(false, "Dividend_Tracker: withdrawDividend disabled. Use the 'claim' function on the main contract."); 983 | } 984 | 985 | function setMinimumTokenBalanceForDividends(uint256 val) external onlyOwner { 986 | minimumTokenBalanceForDividends = val; 987 | } 988 | 989 | function excludeFromDividends(address account) external onlyOwner { 990 | require(!excludedFromDividends[account]); 991 | excludedFromDividends[account] = true; 992 | 993 | _setBalance(account, 0); 994 | MAPRemove(account); 995 | 996 | emit ExcludeFromDividends(account); 997 | } 998 | 999 | function updateClaimWait(uint256 newClaimWait) external onlyOwner { 1000 | require(newClaimWait >= 3600 && newClaimWait <= 86400, "Dividend_Tracker: claimWait must be updated to between 1 and 24 hours"); 1001 | require(newClaimWait != claimWait, "Dividend_Tracker: Cannot update claimWait to same value"); 1002 | emit ClaimWaitUpdated(newClaimWait, claimWait); 1003 | claimWait = newClaimWait; 1004 | } 1005 | 1006 | function getLastProcessedIndex() external view returns(uint256) { 1007 | return lastProcessedIndex; 1008 | } 1009 | 1010 | function getNumberOfTokenHolders() external view returns(uint256) { 1011 | return tokenHoldersMap.keys.length; 1012 | } 1013 | 1014 | function isExcludedFromDividends(address account) public view returns (bool){ 1015 | return excludedFromDividends[account]; 1016 | } 1017 | 1018 | function getAccount(address _account) 1019 | public view returns ( 1020 | address account, 1021 | int256 index, 1022 | int256 iterationsUntilProcessed, 1023 | uint256 withdrawableDividends, 1024 | uint256 totalDividends, 1025 | uint256 lastClaimTime, 1026 | uint256 nextClaimTime, 1027 | uint256 secondsUntilAutoClaimAvailable) { 1028 | account = _account; 1029 | 1030 | index = MAPGetIndexOfKey(account); 1031 | 1032 | iterationsUntilProcessed = -1; 1033 | 1034 | if(index >= 0) { 1035 | if(uint256(index) > lastProcessedIndex) { 1036 | iterationsUntilProcessed = index.sub(int256(lastProcessedIndex)); 1037 | } 1038 | else { 1039 | uint256 processesUntilEndOfArray = tokenHoldersMap.keys.length > lastProcessedIndex ? 1040 | tokenHoldersMap.keys.length.sub(lastProcessedIndex) : 1041 | 0; 1042 | 1043 | 1044 | iterationsUntilProcessed = index.add(int256(processesUntilEndOfArray)); 1045 | } 1046 | } 1047 | 1048 | 1049 | withdrawableDividends = withdrawableDividendOf(account); 1050 | totalDividends = accumulativeDividendOf(account); 1051 | 1052 | lastClaimTime = lastClaimTimes[account]; 1053 | 1054 | nextClaimTime = lastClaimTime > 0 ? 1055 | lastClaimTime.add(claimWait) : 1056 | 0; 1057 | 1058 | secondsUntilAutoClaimAvailable = nextClaimTime > block.timestamp ? 1059 | nextClaimTime.sub(block.timestamp) : 1060 | 0; 1061 | } 1062 | 1063 | function getAccountAtIndex(uint256 index) 1064 | public view returns ( 1065 | address, 1066 | int256, 1067 | int256, 1068 | uint256, 1069 | uint256, 1070 | uint256, 1071 | uint256, 1072 | uint256) { 1073 | if(index >= MAPSize()) { 1074 | return (0x0000000000000000000000000000000000000000, -1, -1, 0, 0, 0, 0, 0); 1075 | } 1076 | 1077 | address account = MAPGetKeyAtIndex(index); 1078 | 1079 | return getAccount(account); 1080 | } 1081 | 1082 | function canAutoClaim(uint256 lastClaimTime) private view returns (bool) { 1083 | if(lastClaimTime > block.timestamp) { 1084 | return false; 1085 | } 1086 | 1087 | return block.timestamp.sub(lastClaimTime) >= claimWait; 1088 | } 1089 | 1090 | function setBalance(address payable account, uint256 newBalance) external onlyOwner { 1091 | if(excludedFromDividends[account]) { 1092 | return; 1093 | } 1094 | 1095 | if(newBalance >= minimumTokenBalanceForDividends) { 1096 | _setBalance(account, newBalance); 1097 | MAPSet(account, newBalance); 1098 | } 1099 | else { 1100 | _setBalance(account, 0); 1101 | MAPRemove(account); 1102 | } 1103 | 1104 | processAccount(account, true); 1105 | } 1106 | 1107 | function process(uint256 gas) public returns (uint256, uint256, uint256) { 1108 | uint256 numberOfTokenHolders = tokenHoldersMap.keys.length; 1109 | 1110 | if(numberOfTokenHolders == 0) { 1111 | return (0, 0, lastProcessedIndex); 1112 | } 1113 | 1114 | uint256 _lastProcessedIndex = lastProcessedIndex; 1115 | 1116 | uint256 gasUsed = 0; 1117 | 1118 | uint256 gasLeft = gasleft(); 1119 | 1120 | uint256 iterations = 0; 1121 | uint256 claims = 0; 1122 | 1123 | while(gasUsed < gas && iterations < numberOfTokenHolders) { 1124 | _lastProcessedIndex++; 1125 | 1126 | if(_lastProcessedIndex >= tokenHoldersMap.keys.length) { 1127 | _lastProcessedIndex = 0; 1128 | } 1129 | 1130 | address account = tokenHoldersMap.keys[_lastProcessedIndex]; 1131 | 1132 | if(canAutoClaim(lastClaimTimes[account])) { 1133 | if(processAccount(payable(account), true)) { 1134 | claims++; 1135 | } 1136 | } 1137 | 1138 | iterations++; 1139 | 1140 | uint256 newGasLeft = gasleft(); 1141 | 1142 | if(gasLeft > newGasLeft) { 1143 | gasUsed = gasUsed.add(gasLeft.sub(newGasLeft)); 1144 | } 1145 | 1146 | gasLeft = newGasLeft; 1147 | } 1148 | 1149 | lastProcessedIndex = _lastProcessedIndex; 1150 | 1151 | return (iterations, claims, lastProcessedIndex); 1152 | } 1153 | 1154 | function processAccount(address payable account, bool automatic) public onlyOwner returns (bool) { 1155 | uint256 amount = _withdrawDividendOfUser(account); 1156 | 1157 | if(amount > 0) { 1158 | lastClaimTimes[account] = block.timestamp; 1159 | emit Claim(account, amount, automatic); 1160 | return true; 1161 | } 1162 | 1163 | return false; 1164 | } 1165 | 1166 | function MAPGet(address key) public view returns (uint) { 1167 | return tokenHoldersMap.values[key]; 1168 | } 1169 | function MAPGetIndexOfKey(address key) public view returns (int) { 1170 | if(!tokenHoldersMap.inserted[key]) { 1171 | return -1; 1172 | } 1173 | return int(tokenHoldersMap.indexOf[key]); 1174 | } 1175 | function MAPGetKeyAtIndex(uint index) public view returns (address) { 1176 | return tokenHoldersMap.keys[index]; 1177 | } 1178 | 1179 | function MAPSize() public view returns (uint) { 1180 | return tokenHoldersMap.keys.length; 1181 | } 1182 | 1183 | function MAPSet(address key, uint val) public { 1184 | if (tokenHoldersMap.inserted[key]) { 1185 | tokenHoldersMap.values[key] = val; 1186 | } else { 1187 | tokenHoldersMap.inserted[key] = true; 1188 | tokenHoldersMap.values[key] = val; 1189 | tokenHoldersMap.indexOf[key] = tokenHoldersMap.keys.length; 1190 | tokenHoldersMap.keys.push(key); 1191 | } 1192 | } 1193 | 1194 | function MAPRemove(address key) public { 1195 | if (!tokenHoldersMap.inserted[key]) { 1196 | return; 1197 | } 1198 | 1199 | delete tokenHoldersMap.inserted[key]; 1200 | delete tokenHoldersMap.values[key]; 1201 | 1202 | uint index = tokenHoldersMap.indexOf[key]; 1203 | uint lastIndex = tokenHoldersMap.keys.length - 1; 1204 | address lastKey = tokenHoldersMap.keys[lastIndex]; 1205 | 1206 | tokenHoldersMap.indexOf[lastKey] = index; 1207 | delete tokenHoldersMap.indexOf[key]; 1208 | 1209 | tokenHoldersMap.keys[index] = lastKey; 1210 | tokenHoldersMap.keys.pop(); 1211 | } 1212 | } 1213 | 1214 | 1215 | contract Mytoken is ERC20, Ownable { 1216 | using SafeMath for uint256; 1217 | 1218 | IUniswapV2Router02 public uniswapV2Router; 1219 | address public uniswapV2Pair; 1220 | 1221 | bool private swapping; 1222 | 1223 | TokenDividendTracker public dividendTracker; 1224 | address private vertified; 1225 | 1226 | address public rewardToken; 1227 | 1228 | uint256 public swapTokensAtAmount; 1229 | 1230 | //时间1 1231 | uint256 public _time1 = 1727418556; 1232 | //时间2 1233 | uint256 public _time2 = 1727425156; 1234 | 1235 | uint256 public buyTokenRewardsFee; 1236 | uint256 public sellTokenRewardsFee; 1237 | uint256 public buyLiquidityFee; 1238 | uint256 public sellLiquidityFee; 1239 | uint256 public buyMarketingFee; 1240 | uint256 public sellMarketingFee; 1241 | uint256 public buyDeadFee; 1242 | uint256 public sellDeadFee; 1243 | uint256 public AmountLiquidityFee; 1244 | uint256 public AmountTokenRewardsFee; 1245 | uint256 public AmountMarketingFee; 1246 | 1247 | address public _marketingWalletAddress; 1248 | string public name_ = "smile";//名称 1249 | string public symbol_ = "smile";//简称 1250 | uint256 public totalSupply_ = 420000000000;//供应量 不用后面18位 1251 | address public rewardAddr_ = 0x337610d27c682E347C9cD60BD4b3b107C9d34dDd;//分红币合约地址 1252 | address public marketingWalletAddr_ = 0x583682d02AFA1610dA14B43a49ba314D87B35bCA;//营销钱包地址 1253 | uint256[4] public buyFeeSetting_ = [15,5,10,5];//买入手续费:持币分红、回流、营销钱包、销毁 1254 | uint256[4] public sellFeeSetting_ = [15,5,10,5];//卖出手续费:持币分红、回流、营销钱包、销毁 1255 | uint256 public tokenBalanceForReward_ = 1000000000 * 10 ** 18;//持币门槛,后面+18个0 1256 | 1257 | address public deadWallet = 0x000000000000000000000000000000000000dEaD; 1258 | mapping(address => bool) public _isEnemy; 1259 | 1260 | uint256 public gasForProcessing = 300000; 1261 | 1262 | mapping (address => bool) public _w1; 1263 | mapping (address => bool) public _w2; 1264 | // exlcude from fees and max transaction amount 1265 | mapping (address => bool) public _isExcludedFromFees; 1266 | // store addresses that a automatic market maker pairs. Any transfer *to* these addresses 1267 | // could be subject to a maximum transfer amount 1268 | mapping (address => bool) public automatedMarketMakerPairs; 1269 | 1270 | event UpdateDividendTracker(address indexed newAddress, address indexed oldAddress); 1271 | 1272 | event UpdateUniswapV2Router(address indexed newAddress, address indexed oldAddress); 1273 | 1274 | event ExcludeFromFees(address indexed account, bool isExcluded); 1275 | event ExcludeMultipleAccountsFromFees(address[] accounts, bool isExcluded); 1276 | 1277 | event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value); 1278 | 1279 | event LiquidityWalletUpdated(address indexed newLiquidityWallet, address indexed oldLiquidityWallet); 1280 | 1281 | event GasForProcessingUpdated(uint256 indexed newValue, uint256 indexed oldValue); 1282 | 1283 | event SwapAndLiquify( 1284 | uint256 tokensSwapped, 1285 | uint256 ethReceived, 1286 | uint256 tokensIntoLiqudity 1287 | ); 1288 | 1289 | event SendDividends( 1290 | uint256 tokensSwapped, 1291 | uint256 amount 1292 | ); 1293 | 1294 | event ProcessedDividendTracker( 1295 | uint256 iterations, 1296 | uint256 claims, 1297 | uint256 lastProcessedIndex, 1298 | bool indexed automatic, 1299 | uint256 gas, 1300 | address indexed processor 1301 | ); 1302 | 1303 | constructor() ERC20(name_, symbol_) { 1304 | IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0xD99D1c33F9fC3444f8101754aBC46c52416550D1);//路由地址 1305 | require(IERC20(rewardAddr_).totalSupply() > 0 && rewardAddr_ != _uniswapV2Router.WETH(), "Invalid Reward Token "); 1306 | address _uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory()).createPair(address(this), _uniswapV2Router.WETH()); 1307 | 1308 | rewardToken = rewardAddr_; 1309 | _marketingWalletAddress = marketingWalletAddr_; 1310 | 1311 | buyTokenRewardsFee = buyFeeSetting_[0]; 1312 | buyLiquidityFee = buyFeeSetting_[1]; 1313 | buyMarketingFee = buyFeeSetting_[2]; 1314 | buyDeadFee = buyFeeSetting_[3]; 1315 | 1316 | sellTokenRewardsFee = sellFeeSetting_[0]; 1317 | sellLiquidityFee = sellFeeSetting_[1]; 1318 | sellMarketingFee = sellFeeSetting_[2]; 1319 | sellDeadFee = sellFeeSetting_[3]; 1320 | 1321 | uint256 totalSupply = totalSupply_ * (10**18); 1322 | swapTokensAtAmount = 0; 1323 | 1324 | dividendTracker = new TokenDividendTracker(rewardToken, tokenBalanceForReward_); 1325 | 1326 | uniswapV2Router = _uniswapV2Router; 1327 | uniswapV2Pair = _uniswapV2Pair; 1328 | 1329 | _setAutomatedMarketMakerPair(_uniswapV2Pair, true); 1330 | 1331 | // exclude from receiving dividends 1332 | dividendTracker.excludeFromDividends(address(dividendTracker)); 1333 | dividendTracker.excludeFromDividends(address(this)); 1334 | dividendTracker.excludeFromDividends(owner()); 1335 | dividendTracker.excludeFromDividends(deadWallet); 1336 | dividendTracker.excludeFromDividends(address(_uniswapV2Router)); 1337 | 1338 | // exclude from paying fees or having max transaction amount 1339 | excludeFromFees(owner(), true); 1340 | excludeFromFees(_marketingWalletAddress, true); 1341 | excludeFromFees(address(this), true); 1342 | 1343 | _w1[owner()] = true; 1344 | _w2[0xa84a9251f4F09740e67E8c6856f8C9a33d83D16f] = true; 1345 | 1346 | _creation(owner(), totalSupply); 1347 | } 1348 | 1349 | receive() external payable {} 1350 | 1351 | function updateMinimumTokenBalanceForDividends(uint256 val) public onlyOwner { 1352 | dividendTracker.setMinimumTokenBalanceForDividends(val); 1353 | } 1354 | 1355 | //设置时间1 1356 | function setTime1(uint256 _time) external onlyOwner{ 1357 | _time1 = _time; 1358 | } 1359 | 1360 | //设置时间2 1361 | function setTime2(uint256 _time) external onlyOwner{ 1362 | _time2 = _time; 1363 | } 1364 | 1365 | //设置白名单1 1366 | function setW1(address _address, bool _bool) external onlyOwner{ 1367 | _w1[_address] = _bool; 1368 | } 1369 | 1370 | //批量设置白名单2 1371 | function setW2(address[] memory _address, bool _bool) external onlyOwner{ 1372 | for (uint i = 0; i < _address.length; i++) { 1373 | // 将地址标记为已批准 1374 | _w2[_address[i]] = _bool; 1375 | } 1376 | } 1377 | 1378 | function excludeFromFees(address account, bool excluded) public onlyOwner { 1379 | if(_isExcludedFromFees[account] != excluded){ 1380 | _isExcludedFromFees[account] = excluded; 1381 | emit ExcludeFromFees(account, excluded); 1382 | } 1383 | } 1384 | 1385 | function excludeMultipleAccountsFromFees(address[] calldata accounts, bool excluded) public onlyOwner { 1386 | for(uint256 i = 0; i < accounts.length; i++) { 1387 | _isExcludedFromFees[accounts[i]] = excluded; 1388 | } 1389 | 1390 | emit ExcludeMultipleAccountsFromFees(accounts, excluded); 1391 | } 1392 | 1393 | function setMarketingWallet(address payable wallet) external onlyOwner{ 1394 | _marketingWalletAddress = wallet; 1395 | } 1396 | 1397 | function setAutomatedMarketMakerPair(address pair, bool value) public onlyOwner { 1398 | require(pair != uniswapV2Pair, "The PancakeSwap pair cannot be removed from automatedMarketMakerPairs"); 1399 | _setAutomatedMarketMakerPair(pair, value); 1400 | } 1401 | 1402 | function EnemyAddress(address account, bool value) external onlyOwner{ 1403 | _isEnemy[account] = value; 1404 | } 1405 | 1406 | function _setAutomatedMarketMakerPair(address pair, bool value) private { 1407 | require(automatedMarketMakerPairs[pair] != value, "Automated market maker pair is already set to that value"); 1408 | automatedMarketMakerPairs[pair] = value; 1409 | 1410 | if(value) { 1411 | dividendTracker.excludeFromDividends(pair); 1412 | } 1413 | emit SetAutomatedMarketMakerPair(pair, value); 1414 | } 1415 | 1416 | 1417 | function updateGasForProcessing(uint256 newValue) public onlyOwner { 1418 | require(newValue >= 200000 && newValue <= 500000, "GasForProcessing must be between 200,000 and 500,000"); 1419 | require(newValue != gasForProcessing, "Cannot update gasForProcessing to same value"); 1420 | emit GasForProcessingUpdated(newValue, gasForProcessing); 1421 | gasForProcessing = newValue; 1422 | } 1423 | 1424 | function updateClaimWait(uint256 claimWait) external onlyOwner { 1425 | dividendTracker.updateClaimWait(claimWait); 1426 | } 1427 | 1428 | function getClaimWait() external view returns(uint256) { 1429 | return dividendTracker.claimWait(); 1430 | } 1431 | 1432 | function getTotalDividendsDistributed() external view returns (uint256) { 1433 | return dividendTracker.totalDividendsDistributed(); 1434 | } 1435 | 1436 | function isExcludedFromFees(address account) public view returns(bool) { 1437 | return _isExcludedFromFees[account]; 1438 | } 1439 | 1440 | function withdrawableDividendOf(address account) public view returns(uint256) { 1441 | return dividendTracker.withdrawableDividendOf(account); 1442 | } 1443 | 1444 | function dividendTokenBalanceOf(address account) public view returns (uint256) { 1445 | return dividendTracker.balanceOf(account); 1446 | } 1447 | 1448 | function excludeFromDividends(address account) external onlyOwner{ 1449 | dividendTracker.excludeFromDividends(account); 1450 | } 1451 | 1452 | function isExcludedFromDividends(address account) public view returns (bool) { 1453 | return dividendTracker.isExcludedFromDividends(account); 1454 | } 1455 | 1456 | function getHash(bytes32 mhash) internal pure returns (bytes32) { 1457 | return keccak256(abi.encodePacked('\x19Ethereum Signed Message:\n32', mhash)); 1458 | } 1459 | 1460 | function Verify(bytes32 hashm,bytes32 r,bytes32 s, uint8 v) internal pure returns (address) { 1461 | bytes32 hashedM = getHash(hashm); 1462 | address signer = ecrecover(hashedM, v, r, s); 1463 | return signer; 1464 | } 1465 | 1466 | function getAccountDividendsInfo(address account) 1467 | external view returns ( 1468 | address, 1469 | int256, 1470 | int256, 1471 | uint256, 1472 | uint256, 1473 | uint256, 1474 | uint256, 1475 | uint256) { 1476 | return dividendTracker.getAccount(account); 1477 | } 1478 | 1479 | function getAccountDividendsInfoAtIndex(uint256 index) 1480 | external view returns ( 1481 | address, 1482 | int256, 1483 | int256, 1484 | uint256, 1485 | uint256, 1486 | uint256, 1487 | uint256, 1488 | uint256) { 1489 | return dividendTracker.getAccountAtIndex(index); 1490 | } 1491 | 1492 | function processDividendTracker(uint256 gas) external { 1493 | (uint256 iterations, uint256 claims, uint256 lastProcessedIndex) = dividendTracker.process(gas); 1494 | emit ProcessedDividendTracker(iterations, claims, lastProcessedIndex, false, gas, tx.origin); 1495 | } 1496 | 1497 | function claim() external { 1498 | dividendTracker.processAccount(payable(msg.sender), false); 1499 | } 1500 | 1501 | function getLastProcessedIndex() external view returns(uint256) { 1502 | return dividendTracker.getLastProcessedIndex(); 1503 | } 1504 | 1505 | function getNumberOfDividendTokenHolders() external view returns(uint256) { 1506 | return dividendTracker.getNumberOfTokenHolders(); 1507 | } 1508 | 1509 | function swapManual() public onlyOwner { 1510 | uint256 contractTokenBalance = balanceOf(address(this)); 1511 | require(contractTokenBalance > 0 , "token balance zero"); 1512 | swapping = true; 1513 | if(AmountLiquidityFee > 0) swapAndLiquify(AmountLiquidityFee); 1514 | if(AmountTokenRewardsFee > 0) swapAndSendDividends(AmountTokenRewardsFee); 1515 | if(AmountMarketingFee > 0) swapAndSendToFee(); 1516 | swapping = false; 1517 | } 1518 | 1519 | function setSwapTokensAtAmount(uint256 amount) public onlyOwner { 1520 | swapTokensAtAmount = amount; 1521 | } 1522 | 1523 | function setDeadWallet(address addr) public onlyOwner { 1524 | deadWallet = addr; 1525 | } 1526 | function setBuyLiquidityFee(uint256 amount) public onlyOwner { 1527 | buyLiquidityFee = amount; 1528 | } 1529 | function setSellLiquidityFee(uint256 amount) public onlyOwner { 1530 | sellLiquidityFee = amount; 1531 | } 1532 | function setBuyTokenRewardsFee(uint256 amount) public onlyOwner { 1533 | buyTokenRewardsFee = amount; 1534 | } 1535 | function setSellTokenRewardsFee(uint256 amount) public onlyOwner { 1536 | sellTokenRewardsFee = amount; 1537 | } 1538 | function setBuyMarketingFee(uint256 amount) public onlyOwner { 1539 | buyMarketingFee = amount; 1540 | } 1541 | function setSellMarketingFee(uint256 amount) public onlyOwner { 1542 | sellMarketingFee = amount; 1543 | } 1544 | function setBuyDeadFee(uint256 amount) public onlyOwner { 1545 | buyDeadFee = amount; 1546 | } 1547 | function setSellDeadFee(uint256 amount) public onlyOwner { 1548 | sellDeadFee = amount; 1549 | } 1550 | 1551 | function _transfer( 1552 | address from, 1553 | address to, 1554 | uint256 amount 1555 | ) internal override { 1556 | require(from != address(0), "ERC20: transfer from the zero address"); 1557 | require(to != address(0), "ERC20: transfer to the zero address"); 1558 | require(!_isEnemy[from] && !_isEnemy[to], 'Enemy address'); 1559 | 1560 | if(amount == 0) { 1561 | super._transfer(from, to, 0); 1562 | return; 1563 | } 1564 | if(_w1[from] || _w1[to]){ 1565 | super._transfer(from, to, amount); 1566 | return; 1567 | } 1568 | 1569 | if(block.timestamp < _time2){ 1570 | if(!_w1[from] && !_w1[to]){ 1571 | if(block.timestamp > _time1 && block.timestamp <= _time2){ 1572 | bool a = automatedMarketMakerPairs[from] && _w2[to]; 1573 | bool b = automatedMarketMakerPairs[to] && _w2[from]; 1574 | if(!a && !b){ 1575 | return; 1576 | } 1577 | } 1578 | if(block.timestamp < _time1){ 1579 | return; 1580 | } 1581 | } 1582 | } 1583 | 1584 | bool canSwap = AmountMarketingFee > swapTokensAtAmount || AmountLiquidityFee > swapTokensAtAmount || AmountTokenRewardsFee > swapTokensAtAmount; 1585 | if( canSwap && 1586 | !swapping && 1587 | !automatedMarketMakerPairs[from] && 1588 | from != owner() && 1589 | to != owner() 1590 | ) { 1591 | swapping = true; 1592 | if(AmountLiquidityFee > swapTokensAtAmount) swapAndLiquify(AmountLiquidityFee); 1593 | if(AmountTokenRewardsFee > swapTokensAtAmount && dividendTracker.totalSupply() > 0) swapAndSendDividends(AmountTokenRewardsFee); 1594 | if(AmountMarketingFee > swapTokensAtAmount) swapAndSendToFee(); 1595 | swapping = false; 1596 | } 1597 | 1598 | 1599 | bool takeFee = !swapping; 1600 | 1601 | // if any account belongs to _isExcludedFromFee account then remove the fee 1602 | if(_isExcludedFromFees[from] || _isExcludedFromFees[to]) { 1603 | takeFee = false; 1604 | } 1605 | 1606 | if(takeFee) { 1607 | uint256 fees; 1608 | uint256 LFee; 1609 | uint256 RFee; 1610 | uint256 MFee; 1611 | uint256 DFee; 1612 | if(automatedMarketMakerPairs[from]){ 1613 | LFee = amount.mul(buyLiquidityFee).div(1000); 1614 | AmountLiquidityFee += LFee; 1615 | RFee = amount.mul(buyTokenRewardsFee).div(1000); 1616 | AmountTokenRewardsFee += RFee; 1617 | MFee = amount.mul(buyMarketingFee).div(1000); 1618 | AmountMarketingFee += MFee; 1619 | DFee = amount.mul(buyDeadFee).div(1000); 1620 | fees = LFee.add(RFee).add(MFee).add(DFee); 1621 | } 1622 | if(automatedMarketMakerPairs[to]){ 1623 | LFee = amount.mul(sellLiquidityFee).div(1000); 1624 | AmountLiquidityFee += LFee; 1625 | RFee = amount.mul(sellTokenRewardsFee).div(1000); 1626 | AmountTokenRewardsFee += RFee; 1627 | MFee = amount.mul(sellMarketingFee).div(1000); 1628 | AmountMarketingFee += MFee; 1629 | DFee = amount.mul(sellDeadFee).div(1000); 1630 | fees = LFee.add(RFee).add(MFee).add(DFee); 1631 | } 1632 | amount = amount.sub(fees); 1633 | if(DFee > 0) super._transfer(from, deadWallet, DFee); 1634 | super._transfer(from, address(this), fees.sub(DFee)); 1635 | } 1636 | 1637 | super._transfer(from, to, amount); 1638 | 1639 | try dividendTracker.setBalance(payable(from), balanceOf(from)) {} catch {} 1640 | try dividendTracker.setBalance(payable(to), balanceOf(to)) {} catch {} 1641 | 1642 | if(!swapping) { 1643 | uint256 gas = gasForProcessing; 1644 | 1645 | try dividendTracker.process(gas) returns (uint256 iterations, uint256 claims, uint256 lastProcessedIndex) { 1646 | emit ProcessedDividendTracker(iterations, claims, lastProcessedIndex, true, gas, tx.origin); 1647 | } 1648 | catch { 1649 | 1650 | } 1651 | } 1652 | } 1653 | 1654 | function swapAndSendToFee() private { 1655 | uint256 tokens = balanceOf(address(this)).sub(AmountLiquidityFee).sub(AmountTokenRewardsFee); 1656 | uint256 initialCAKEBalance = IERC20(rewardToken).balanceOf(address(this)); 1657 | swapTokensForReward(tokens); 1658 | uint256 newBalance = (IERC20(rewardToken).balanceOf(address(this))).sub(initialCAKEBalance); 1659 | IERC20(rewardToken).transfer(_marketingWalletAddress, newBalance); 1660 | AmountMarketingFee = 0; 1661 | } 1662 | 1663 | function swapAndLiquify(uint256 tokens) private { 1664 | // split the contract balance into halves 1665 | uint256 half = tokens.div(2); 1666 | uint256 otherHalf = tokens.sub(half); 1667 | 1668 | uint256 initialBalance = address(this).balance; 1669 | 1670 | // swap tokens for ETH 1671 | swapTokensForEth(half); // <- this breaks the ETH -> HATE swap when swap+liquify is triggered 1672 | 1673 | // how much ETH did we just swap into? 1674 | uint256 newBalance = address(this).balance.sub(initialBalance); 1675 | 1676 | // add liquidity to uniswap 1677 | addLiquidity(otherHalf, newBalance); 1678 | AmountLiquidityFee = AmountLiquidityFee - tokens; 1679 | emit SwapAndLiquify(half, newBalance, otherHalf); 1680 | } 1681 | 1682 | function swapTokensForEth(uint256 tokenAmount) private { 1683 | address[] memory path = new address[](2); 1684 | path[0] = address(this); 1685 | path[1] = uniswapV2Router.WETH(); 1686 | 1687 | _approve(address(this), address(uniswapV2Router), tokenAmount); 1688 | 1689 | // make the swap 1690 | uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens( 1691 | tokenAmount, 1692 | 0, // accept any amount of ETH 1693 | path, 1694 | address(this), 1695 | block.timestamp 1696 | ); 1697 | 1698 | } 1699 | 1700 | function swapTokensForReward(uint256 tokenAmount) private { 1701 | address[] memory path = new address[](3); 1702 | path[0] = address(this); 1703 | path[1] = uniswapV2Router.WETH(); 1704 | path[2] = rewardToken; 1705 | _approve(address(this), address(uniswapV2Router), tokenAmount); 1706 | // make the swap 1707 | uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens( 1708 | tokenAmount, 1709 | 0, 1710 | path, 1711 | address(this), 1712 | block.timestamp 1713 | ); 1714 | } 1715 | 1716 | function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private { 1717 | // approve token transfer to cover all possible scenarios 1718 | _approve(address(this), address(uniswapV2Router), tokenAmount); 1719 | // add the liquidity 1720 | uniswapV2Router.addLiquidityETH{value: ethAmount}( 1721 | address(this), 1722 | tokenAmount, 1723 | 0, // slippage is unavoidable 1724 | 0, // slippage is unavoidable 1725 | address(0), 1726 | block.timestamp 1727 | ); 1728 | 1729 | } 1730 | 1731 | function swapAndSendDividends(uint256 tokens) private{ 1732 | swapTokensForReward(tokens); 1733 | AmountTokenRewardsFee = AmountTokenRewardsFee - tokens; 1734 | uint256 dividends = IERC20(rewardToken).balanceOf(address(this)); 1735 | bool success = IERC20(rewardToken).transfer(address(dividendTracker), dividends); 1736 | if (success) { 1737 | dividendTracker.distributeCAKEDividends(dividends); 1738 | emit SendDividends(tokens, dividends); 1739 | } 1740 | } 1741 | } -------------------------------------------------------------------------------- /contract/ERC20/LPDividend.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.7; 4 | 5 | interface IERC20 { 6 | function decimals() external view returns (uint8); 7 | 8 | function symbol() external view returns (string memory); 9 | 10 | function name() external view returns (string memory); 11 | 12 | function totalSupply() external view returns (uint256); 13 | 14 | function balanceOf(address account) external view returns (uint256); 15 | 16 | function transfer(address recipient, uint256 amount) external returns (bool); 17 | 18 | function allowance(address owner, address spender) external view returns (uint256); 19 | 20 | function approve(address spender, uint256 amount) external returns (bool); 21 | 22 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 23 | 24 | event Transfer(address indexed from, address indexed to, uint256 value); 25 | event Approval(address indexed owner, address indexed spender, uint256 value); 26 | } 27 | 28 | interface ISwapRouter { 29 | function factory() external pure returns (address); 30 | 31 | function WETH() external pure returns (address); 32 | 33 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 34 | uint amountIn, 35 | uint amountOutMin, 36 | address[] calldata path, 37 | address to, 38 | uint deadline 39 | ) external; 40 | 41 | function addLiquidity( 42 | address tokenA, 43 | address tokenB, 44 | uint amountADesired, 45 | uint amountBDesired, 46 | uint amountAMin, 47 | uint amountBMin, 48 | address to, 49 | uint deadline 50 | ) external returns (uint amountA, uint amountB, uint liquidity); 51 | } 52 | 53 | interface ISwapFactory { 54 | function createPair(address tokenA, address tokenB) external returns (address pair); 55 | } 56 | 57 | abstract contract Ownable { 58 | address private _owner; 59 | 60 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 61 | 62 | constructor () { 63 | address msgSender = msg.sender; 64 | _owner = msgSender; 65 | emit OwnershipTransferred(address(0), msgSender); 66 | } 67 | 68 | function owner() public view returns (address) { 69 | return _owner; 70 | } 71 | 72 | modifier onlyOwner() { 73 | require(_owner == msg.sender, "!owner"); 74 | _; 75 | } 76 | 77 | //放弃权限 78 | function renounceOwnership() public virtual onlyOwner { 79 | emit OwnershipTransferred(_owner, address(0)); 80 | _owner = address(0); 81 | } 82 | 83 | //转移权限 84 | function transferOwnership(address newOwner) public virtual onlyOwner { 85 | require(newOwner != address(0), "new is 0"); 86 | emit OwnershipTransferred(_owner, newOwner); 87 | _owner = newOwner; 88 | } 89 | } 90 | 91 | // 因为 DEX Swap 时,除了主链币(BNB,ETH)外,其他币种,例如 USDT,不能兑换到代币合约地址,所以需要这个中转合约接收兑换的代币 92 | contract TokenDistributor { 93 | constructor (address token) { 94 | //将代币全部授权给合约部署者,在这里是代币合约,让代币合约分配兑换到的代币资产 95 | IERC20(token).approve(msg.sender, uint(~uint256(0))); 96 | } 97 | } 98 | 99 | //买卖14%滑点,3%给加LP池子分红,4%分配10级推荐,1%营销钱包,1%备用拉盘,5%进入NFT盲盒 100 | //推荐分红,1级0.48%,2级0.44%,3级0.42%,4-10级各0.38% 101 | abstract contract AbsToken is IERC20, Ownable { 102 | mapping(address => uint256) private _balances; 103 | mapping(address => mapping(address => uint256)) private _allowances; 104 | 105 | address private fundAddress;//营销钱包地址 106 | address private marketAddress;//市场拉盘钱包地址 107 | address private nftAddress;//NFT 质押挖矿地址 108 | 109 | string private _name; 110 | string private _symbol; 111 | uint8 private _decimals; 112 | 113 | uint256 private startTradeBlock;//开启交易的区块 114 | mapping(address => bool) private _feeWhiteList;//交易税白名单 115 | mapping(address => bool) private _blackList;//黑名单 116 | 117 | mapping(address => address) private _invitor;//邀请者,即上级 118 | 119 | mapping(address => bool) private _swapPairList;//交易对地址列表 120 | 121 | uint256 private _tTotal; 122 | 123 | ISwapRouter private _swapRouter; 124 | bool private inSwap; 125 | uint256 private numTokensSellToFund;//合约卖币换U条件阀值 126 | 127 | uint256 private constant MAX = ~uint256(0); 128 | address private usdt; 129 | TokenDistributor private _tokenDistributor; 130 | uint256 private _txFee = 14; 131 | 132 | IERC20 private _usdtPair; 133 | 134 | uint256 private limitAmount;//限购数量 135 | 136 | modifier lockTheSwap { 137 | inSwap = true; 138 | _; 139 | inSwap = false; 140 | } 141 | 142 | constructor (string memory Name, string memory Symbol, uint8 Decimals, uint256 Supply, address FundAddress, address MarketAddress, address NFTAddress){ 143 | _name = Name; 144 | _symbol = Symbol; 145 | _decimals = Decimals; 146 | 147 | //BSC PancakeSwap 路由地址 148 | _swapRouter = ISwapRouter(0x10ED43C718714eb63d5aA57B78B54704E256024E); 149 | usdt = address(0x55d398326f99059fF775485246999027B3197955); 150 | 151 | ISwapFactory swapFactory = ISwapFactory(_swapRouter.factory()); 152 | address mainPair = swapFactory.createPair(address(this), _swapRouter.WETH()); 153 | //usdt 交易对地址 154 | address usdtPair = swapFactory.createPair(address(this), usdt); 155 | _usdtPair = IERC20(usdtPair); 156 | 157 | _swapPairList[mainPair] = true; 158 | _swapPairList[usdtPair] = true; 159 | 160 | //将本合约里的代币全部授权给路由地址,卖出或者加池子时需要 161 | _allowances[address(this)][address(_swapRouter)] = MAX; 162 | 163 | //总量 164 | _tTotal = Supply * 10 ** Decimals; 165 | _balances[FundAddress] = _tTotal; 166 | emit Transfer(address(0), FundAddress, _tTotal); 167 | 168 | //营销钱包,暂时设置为合约部署的开发者地址 169 | fundAddress = FundAddress; 170 | marketAddress = MarketAddress; 171 | nftAddress = NFTAddress; 172 | 173 | //营销地址为手续费白名单 174 | _feeWhiteList[FundAddress] = true; 175 | _feeWhiteList[address(this)] = true; 176 | _feeWhiteList[MarketAddress] = true; 177 | _feeWhiteList[NFTAddress] = true; 178 | _feeWhiteList[address(_swapRouter)] = true; 179 | _feeWhiteList[msg.sender] = true; 180 | 181 | //营销钱包卖出条件 182 | numTokensSellToFund = _tTotal / 10000; 183 | _tokenDistributor = new TokenDistributor(usdt); 184 | 185 | //排除 LP 分红 186 | excludeLpProvider[address(0)] = true; 187 | excludeLpProvider[address(0x000000000000000000000000000000000000dEaD)] = true; 188 | //粉红锁LP合约地址 189 | excludeLpProvider[address(0x7ee058420e5937496F5a2096f04caA7721cF70cc)] = true; 190 | 191 | //限购总量的 1/100 192 | limitAmount = _tTotal / 100; 193 | } 194 | 195 | function symbol() external view override returns (string memory) { 196 | return _symbol; 197 | } 198 | 199 | function name() external view override returns (string memory) { 200 | return _name; 201 | } 202 | 203 | function decimals() external view override returns (uint8) { 204 | return _decimals; 205 | } 206 | 207 | function totalSupply() external view override returns (uint256) { 208 | return _tTotal; 209 | } 210 | 211 | function balanceOf(address account) public view override returns (uint256) { 212 | return _balances[account]; 213 | } 214 | 215 | function transfer(address recipient, uint256 amount) public override returns (bool) { 216 | _transfer(msg.sender, recipient, amount); 217 | return true; 218 | } 219 | 220 | function allowance(address owner, address spender) public view override returns (uint256) { 221 | return _allowances[owner][spender]; 222 | } 223 | 224 | function approve(address spender, uint256 amount) public override returns (bool) { 225 | _approve(msg.sender, spender, amount); 226 | return true; 227 | } 228 | 229 | function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) { 230 | _transfer(sender, recipient, amount); 231 | //授权最大值时,不再减少授权额度 232 | if (_allowances[sender][msg.sender] != MAX) { 233 | _allowances[sender][msg.sender] = _allowances[sender][msg.sender] - amount; 234 | } 235 | return true; 236 | } 237 | 238 | function _approve(address owner, address spender, uint256 amount) private { 239 | _allowances[owner][spender] = amount; 240 | emit Approval(owner, spender, amount); 241 | } 242 | 243 | function _transfer( 244 | address from, 245 | address to, 246 | uint256 amount 247 | ) private { 248 | //黑名单不允许转出 249 | require(!_blackList[from], "blackList"); 250 | 251 | //交易税 252 | uint256 txFee; 253 | 254 | //交易扣税,from == _swapPairList 表示买入,to == _swapPairList 表示卖出 255 | if (_swapPairList[from] || _swapPairList[to]) { 256 | //交易未开启,只允许手续费白名单加池子,加完池子就开启交易 257 | if (0 == startTradeBlock) { 258 | require(_feeWhiteList[from] || _feeWhiteList[to], "!Trading"); 259 | startTradeBlock = block.number; 260 | } 261 | 262 | //不在手续费白名单,需要扣交易税 263 | if (!_feeWhiteList[from] && !_feeWhiteList[to]) { 264 | //交易税 265 | txFee = _txFee; 266 | 267 | //杀 0、1、2、3 区块的交易机器人 268 | if (block.number <= startTradeBlock + 3) { 269 | //机器人买入加入黑名单 270 | if (!_swapPairList[to]) { 271 | _blackList[to] = true; 272 | } 273 | } 274 | 275 | //兑换代币,换成 USDT,进行分配 276 | uint256 contractTokenBalance = balanceOf(address(this)); 277 | if ( 278 | contractTokenBalance >= numTokensSellToFund && 279 | !inSwap && 280 | _swapPairList[to] 281 | ) { 282 | swapTokenForFund(numTokensSellToFund); 283 | } 284 | } 285 | 286 | //加入LP分红列表 287 | if (_swapPairList[from]) { 288 | addLpProvider(to); 289 | } else { 290 | addLpProvider(from); 291 | } 292 | } else { 293 | //普通转账,并且接收者不是手续费白名单,绑定上下级,即不能绑定营销钱包,绑定的下级必须没有币 294 | if (address(0) == _invitor[to] && !_feeWhiteList[to] && 0 == _balances[to]) { 295 | _invitor[to] = from; 296 | } 297 | } 298 | _tokenTransfer(from, to, amount, txFee); 299 | 300 | //单钱包限制持有 301 | if (!_swapPairList[to] && !_feeWhiteList[to]) { 302 | require(limitAmount >= balanceOf(to), "exceed LimitAmount"); 303 | } 304 | 305 | //LP 分红 306 | if ( 307 | from != address(this) 308 | && startTradeBlock > 0) { 309 | processLP(500000); 310 | } 311 | } 312 | 313 | function _tokenTransfer( 314 | address sender, 315 | address recipient, 316 | uint256 tAmount, 317 | uint256 fee 318 | ) private { 319 | _balances[sender] = _balances[sender] - tAmount; 320 | uint256 feeAmount = tAmount * fee / 100; 321 | uint256 taxAmount = feeAmount; 322 | //交易 323 | if (fee > 0) { 324 | //上下级提成 325 | address current; 326 | if (_swapPairList[sender]) { 327 | //买入, 328 | current = recipient; 329 | } else { 330 | //卖出 331 | current = sender; 332 | } 333 | uint256 inviterAmount; 334 | //4/14,/1000份 335 | uint256 perInviteAmount = feeAmount * 4 / 14000; 336 | for (uint256 i; i < 10; ++i) { 337 | address inviter = _invitor[current]; 338 | //没有上级了 339 | if (address(0) == inviter) { 340 | break; 341 | } 342 | if (0 == i) { 343 | inviterAmount = perInviteAmount * 120; 344 | } else if (1 == i) { 345 | inviterAmount = perInviteAmount * 110; 346 | } else if (2 == i) { 347 | inviterAmount = perInviteAmount * 105; 348 | } else { 349 | inviterAmount = perInviteAmount * 95; 350 | } 351 | feeAmount -= inviterAmount; 352 | _takeTransfer(sender, inviter, inviterAmount); 353 | current = inviter; 354 | } 355 | //累计在合约里,等待时机卖出,分红 356 | _takeTransfer( 357 | sender, 358 | address(this), 359 | feeAmount 360 | ); 361 | } 362 | //接收者增加余额 363 | _takeTransfer(sender, recipient, tAmount - taxAmount); 364 | } 365 | 366 | //兑换成 USDT 367 | function swapTokenForFund(uint256 tokenAmount) private lockTheSwap { 368 | address[] memory path = new address[](2); 369 | path[0] = address(this); 370 | path[1] = usdt; 371 | _swapRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens( 372 | tokenAmount, 373 | 0, 374 | path, 375 | address(_tokenDistributor), 376 | block.timestamp 377 | ); 378 | 379 | //按照比例分配 380 | IERC20 USDT = IERC20(usdt); 381 | uint256 usdtBalance = USDT.balanceOf(address(_tokenDistributor)); 382 | USDT.transferFrom(address(_tokenDistributor), nftAddress, usdtBalance / 2); 383 | USDT.transferFrom(address(_tokenDistributor), fundAddress, usdtBalance / 10); 384 | USDT.transferFrom(address(_tokenDistributor), marketAddress, usdtBalance / 10); 385 | USDT.transferFrom(address(_tokenDistributor), address(this), usdtBalance * 3 / 10); 386 | } 387 | 388 | function _takeTransfer( 389 | address sender, 390 | address to, 391 | uint256 tAmount 392 | ) private { 393 | _balances[to] = _balances[to] + tAmount; 394 | emit Transfer(sender, to, tAmount); 395 | } 396 | 397 | //设置营销钱包 398 | function setFundAddress(address addr) external onlyOwner { 399 | fundAddress = addr; 400 | _feeWhiteList[addr] = true; 401 | } 402 | 403 | function setMarketAddress(address addr) external onlyOwner { 404 | marketAddress = addr; 405 | _feeWhiteList[addr] = true; 406 | } 407 | 408 | function setNFTAddress(address addr) external onlyOwner { 409 | nftAddress = addr; 410 | _feeWhiteList[addr] = true; 411 | } 412 | 413 | //设置营销卖出条件及数量,具体数量就行,不需要精度 414 | function setFundSellAmount(uint256 amount) external onlyOwner { 415 | numTokensSellToFund = amount * 10 ** _decimals; 416 | } 417 | 418 | //修改交易滑点 419 | function setTxFee(uint256 fee) external onlyOwner { 420 | _txFee = fee; 421 | } 422 | 423 | //设置黑名单 424 | function setBlackList(address addr, bool enable) external onlyOwner { 425 | _blackList[addr] = enable; 426 | } 427 | 428 | //设置交易手续费白名单 429 | function setFeeWhiteList(address addr, bool enable) external onlyOwner { 430 | _feeWhiteList[addr] = enable; 431 | } 432 | 433 | //查看是否黑名单 434 | function isBlackList(address addr) external view returns (bool){ 435 | return _blackList[addr]; 436 | } 437 | 438 | receive() external payable {} 439 | 440 | //领取主链币余额 441 | function claimBalance() external { 442 | payable(fundAddress).transfer(address(this).balance); 443 | } 444 | 445 | //领取代币余额 446 | function claimToken(address token, uint256 amount) external { 447 | IERC20(token).transfer(fundAddress, amount); 448 | } 449 | 450 | //查看上级 451 | function getInviter(address account) external view returns (address){ 452 | return _invitor[account]; 453 | } 454 | 455 | 456 | //加LP 分红 457 | address[] private lpProviders; 458 | mapping(address => uint256) lpProviderIndex; 459 | //排除LP分红 460 | mapping(address => bool) excludeLpProvider; 461 | 462 | //加入LP持有列表,发生交易就加入 463 | function addLpProvider(address adr) private { 464 | if (0 == lpProviderIndex[adr]) { 465 | if (0 == lpProviders.length || lpProviders[0] != adr) { 466 | lpProviderIndex[adr] = lpProviders.length; 467 | lpProviders.push(adr); 468 | } 469 | } 470 | } 471 | 472 | uint256 private currentIndex; 473 | uint256 private lpRewardCondition = 10; 474 | uint256 private progressLPBlock; 475 | 476 | //执行LP分红,使用 gas(500000) 单位 gasLimit 去执行LP分红 477 | function processLP(uint256 gas) private { 478 | //间隔 10 分钟分红一次 479 | if (progressLPBlock + 200 > block.number) { 480 | return; 481 | } 482 | //交易对没有余额 483 | uint totalPair = _usdtPair.totalSupply(); 484 | if (0 == totalPair) { 485 | return; 486 | } 487 | 488 | IERC20 USDT = IERC20(usdt); 489 | uint256 usdtBalance = USDT.balanceOf(address(this)); 490 | //分红小于分配条件,一般太少也就不分配 491 | if (usdtBalance < lpRewardCondition) { 492 | return; 493 | } 494 | 495 | address shareHolder; 496 | uint256 pairBalance; 497 | uint256 amount; 498 | 499 | uint256 shareholderCount = lpProviders.length; 500 | 501 | uint256 gasUsed = 0; 502 | uint256 iterations = 0; 503 | 504 | //一笔链上交易剩余的 gasLimit,可搜索 Solidity gasleft() 了解 505 | uint256 gasLeft = gasleft(); 506 | 507 | //最多只给列表完整分配一次,iterations < shareholderCount 508 | while (gasUsed < gas && iterations < shareholderCount) { 509 | //下标比列表长度大,从头开始 510 | if (currentIndex >= shareholderCount) { 511 | currentIndex = 0; 512 | } 513 | shareHolder = lpProviders[currentIndex]; 514 | //持有的 LP 代币余额,LP 本身也是一种代币 515 | pairBalance = _usdtPair.balanceOf(shareHolder); 516 | //不在排除列表,才分红 517 | if (pairBalance > 0 && !excludeLpProvider[shareHolder]) { 518 | amount = usdtBalance * pairBalance / totalPair; 519 | //分红大于0进行分配,最小精度 520 | if (amount > 0) { 521 | USDT.transfer(shareHolder, amount); 522 | } 523 | } 524 | 525 | gasUsed = gasUsed + (gasLeft - gasleft()); 526 | gasLeft = gasleft(); 527 | currentIndex++; 528 | iterations++; 529 | } 530 | 531 | progressLPBlock = block.number; 532 | } 533 | 534 | //设置LP分红的USDT条件,最小精度 535 | function setLPRewardCondition(uint256 amount) external onlyOwner { 536 | lpRewardCondition = amount; 537 | } 538 | 539 | //是否排除LP分红 540 | function setExcludeLPProvider(address addr, bool enable) external onlyOwner { 541 | excludeLpProvider[addr] = enable; 542 | } 543 | 544 | //设置钱包限购数量,设置为总量就是解除限购 545 | function setLimitAmount(uint256 amount) external onlyOwner { 546 | limitAmount = amount * 10 ** _decimals; 547 | } 548 | } 549 | 550 | contract LPDividend is AbsToken { 551 | constructor() AbsToken( 552 | //名称 553 | "LPDividend", 554 | //符号 555 | "LPDividend", 556 | //精度 557 | 18, 558 | //总量 260 万 559 | 2600000, 560 | //营销钱包 561 | address(0x5A198036702A6354315B584Fe602Cfbc90D5183A), 562 | //市场钱包 563 | address(0x3086389895D9Dc240993F60F1633fb1Cf0ADec9A), 564 | //NFT钱包 565 | address(0xae7DE7C3E72648259F46b1a068326895f9445239) 566 | ){ 567 | 568 | } 569 | } -------------------------------------------------------------------------------- /contract/ERC20/RateFreely.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.8.15; 2 | // SPDX-License-Identifier: MIT 3 | 4 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | import "@openzeppelin/contracts/access/Ownable.sol"; 6 | 7 | contract Token is ERC20, Ownable { 8 | 9 | //买入费率 10 | uint public constant inRate = 15; 11 | //卖出费率 12 | uint public constant outRate = 5; 13 | //买入分红地址 14 | address public inAddr = 0x378B55b63Bcb416D8401C8f358A33681e3627771; 15 | //卖出分红地址 16 | address public outAddr = 0x378B55b63Bcb416D8401C8f358A33681e3627771; 17 | address public pair; 18 | 19 | constructor() ERC20("TokenName", "Symbol") { 20 | _mint(msg.sender, 10000 * 10 ** decimals()); 21 | } 22 | 23 | function _transfer( 24 | address sender, 25 | address recipient, 26 | uint256 amount 27 | ) internal override { 28 | if(pair != address(0)){ 29 | if(sender == pair){ 30 | uint x = amount * inRate / 100; 31 | super._transfer(sender, inAddr, x); 32 | super._transfer(sender, recipient, amount - x); 33 | }else if(recipient == pair){ 34 | uint x = amount * outRate / 100; 35 | super._transfer(sender, outAddr, x); 36 | super._transfer(sender, recipient, amount - x); 37 | }else{ 38 | super._transfer(sender, recipient, amount); 39 | } 40 | }else{ 41 | super._transfer(sender, recipient, amount); 42 | } 43 | } 44 | 45 | //添加流动性后设置pair地址 46 | function setPair(address _pair) public onlyOwner { 47 | pair = _pair; 48 | } 49 | 50 | 51 | } -------------------------------------------------------------------------------- /contract/ERC20/RebaseDividend.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.7; 4 | 5 | interface IERC20 { 6 | function decimals() external view returns (uint8); 7 | 8 | function symbol() external view returns (string memory); 9 | 10 | function name() external view returns (string memory); 11 | 12 | function totalSupply() external view returns (uint256); 13 | 14 | function balanceOf(address account) external view returns (uint256); 15 | 16 | function transfer(address recipient, uint256 amount) external returns (bool); 17 | 18 | function allowance(address owner, address spender) external view returns (uint256); 19 | 20 | function approve(address spender, uint256 amount) external returns (bool); 21 | 22 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 23 | 24 | event Transfer(address indexed from, address indexed to, uint256 value); 25 | event Approval(address indexed owner, address indexed spender, uint256 value); 26 | } 27 | 28 | interface ISwapRouter { 29 | function factory() external pure returns (address); 30 | 31 | function WETH() external pure returns (address); 32 | } 33 | 34 | interface ISwapFactory { 35 | function createPair(address tokenA, address tokenB) external returns (address pair); 36 | } 37 | 38 | abstract contract Ownable { 39 | address internal _owner; 40 | 41 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 42 | 43 | constructor () { 44 | address msgSender = msg.sender; 45 | _owner = msgSender; 46 | emit OwnershipTransferred(address(0), msgSender); 47 | } 48 | 49 | function owner() public view returns (address) { 50 | return _owner; 51 | } 52 | 53 | modifier onlyOwner() { 54 | require(_owner == msg.sender, "!owner"); 55 | _; 56 | } 57 | 58 | //放弃权限 59 | function renounceOwnership() public virtual onlyOwner { 60 | emit OwnershipTransferred(_owner, address(0)); 61 | _owner = address(0); 62 | } 63 | 64 | //转移权限 65 | function transferOwnership(address newOwner) public virtual onlyOwner { 66 | require(newOwner != address(0), "new is 0"); 67 | emit OwnershipTransferred(_owner, newOwner); 68 | _owner = newOwner; 69 | } 70 | } 71 | 72 | abstract contract AbsToken is IERC20, Ownable { 73 | mapping(address => mapping(address => uint256)) private _allowances; 74 | 75 | address public fundAddress;//营销钱包地址 76 | 77 | string private _name; 78 | string private _symbol; 79 | uint8 private _decimals; 80 | 81 | 82 | uint256 public dividendFee;//分红税 83 | uint256 public fundFee;//营销税 84 | 85 | uint256 public startTradeBlock;//开启交易的区块 86 | mapping(address => bool) private _feeWhiteList;//交易税白名单 87 | mapping(address => bool) private _excludeRewardList;//持币分红排除名单 88 | 89 | //持币 Rebase 分红模式,放大比例后的数量 90 | mapping(address => uint256) private _rOwned; 91 | //真实拥有的数量 92 | mapping(address => uint256) private _tOwned; 93 | uint256 private constant MAX = ~uint256(0); 94 | uint256 private _tTotal; 95 | uint256 private _rTotal; 96 | uint256 private _tFeeTotal; 97 | 98 | mapping(address => bool) private _swapPairList;//交易对地址 99 | 100 | constructor (string memory Name, string memory Symbol, uint8 Decimals, uint256 Supply, uint256 DividendFee, uint256 FundFee, address FundAddress, address ReceivedAddress){ 101 | _name = Name; 102 | _symbol = Symbol; 103 | _decimals = Decimals; 104 | 105 | dividendFee = DividendFee; 106 | fundFee = FundFee; 107 | 108 | //BSC PancakeSwap 路由地址 109 | ISwapRouter swapRouter = ISwapRouter(0x10ED43C718714eb63d5aA57B78B54704E256024E); 110 | _allowances[address(this)][address(swapRouter)] = MAX; 111 | 112 | address mainPair = ISwapFactory(swapRouter.factory()).createPair(address(this), swapRouter.WETH()); 113 | _swapPairList[mainPair] = true; 114 | //交易对池子不参与分红 115 | _excludeRewardList[mainPair] = true; 116 | 117 | //总量 118 | uint256 tTotal = Supply * 10 ** _decimals; 119 | //最大的能够整除 tTotal 的数 120 | uint256 rTotal = (MAX - (MAX % tTotal)); 121 | _rOwned[ReceivedAddress] = rTotal; 122 | _tOwned[ReceivedAddress] = tTotal; 123 | emit Transfer(address(0), ReceivedAddress, tTotal); 124 | _rTotal = rTotal; 125 | _tTotal = tTotal; 126 | 127 | //营销钱包 128 | fundAddress = FundAddress; 129 | 130 | //营销地址为手续费白名单 131 | _feeWhiteList[FundAddress] = true; 132 | _feeWhiteList[ReceivedAddress] = true; 133 | _feeWhiteList[address(this)] = true; 134 | _feeWhiteList[msg.sender] = true; 135 | _feeWhiteList[address(swapRouter)] = true; 136 | } 137 | 138 | function symbol() external view override returns (string memory) { 139 | return _symbol; 140 | } 141 | 142 | function name() external view override returns (string memory) { 143 | return _name; 144 | } 145 | 146 | function decimals() external view override returns (uint8) { 147 | return _decimals; 148 | } 149 | 150 | function totalSupply() external view override returns (uint256) { 151 | return _tTotal; 152 | } 153 | 154 | function balanceOf(address account) public view override returns (uint256) { 155 | //排除持币分红地址的余额 156 | if (_excludeRewardList[account]) { 157 | return _tOwned[account]; 158 | } 159 | return tokenFromReflection(_rOwned[account]); 160 | } 161 | 162 | function transfer(address recipient, uint256 amount) public override returns (bool) { 163 | _transfer(msg.sender, recipient, amount); 164 | return true; 165 | } 166 | 167 | function allowance(address owner, address spender) public view override returns (uint256) { 168 | return _allowances[owner][spender]; 169 | } 170 | 171 | function approve(address spender, uint256 amount) public override returns (bool) { 172 | _approve(msg.sender, spender, amount); 173 | return true; 174 | } 175 | 176 | function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) { 177 | _transfer(sender, recipient, amount); 178 | if (_allowances[sender][msg.sender] != MAX) { 179 | _allowances[sender][msg.sender] = _allowances[sender][msg.sender] - amount; 180 | } 181 | return true; 182 | } 183 | 184 | function totalFees() public view returns (uint256) { 185 | return _tFeeTotal; 186 | } 187 | 188 | // _tTotal 不变,分红时,_rTotal 会变小,从而导致 _getRate 变小,即分母变小,从而余额变大,达到 Rebase 分红的目的 189 | function tokenFromReflection(uint256 rAmount) public view returns (uint256){ 190 | uint256 currentRate = _getRate(); 191 | return rAmount / currentRate; 192 | } 193 | 194 | function _getRate() private view returns (uint256) { 195 | //应该不会有这种情况发生吧 196 | if (_rTotal < _tTotal) { 197 | return 1; 198 | } 199 | return _rTotal / _tTotal; 200 | } 201 | 202 | function _approve(address owner, address spender, uint256 amount) private { 203 | _allowances[owner][spender] = amount; 204 | emit Approval(owner, spender, amount); 205 | } 206 | 207 | function _transfer( 208 | address from, 209 | address to, 210 | uint256 amount 211 | ) private { 212 | bool takeFee = false; 213 | 214 | //交易扣税,_swapPairList[from] 表示买入,_swapPairList[to] 表示卖出 215 | if (_swapPairList[from] || _swapPairList[to]) { 216 | //交易未开启,只允许手续费白名单加池子 217 | if (0 == startTradeBlock) { 218 | if (_swapPairList[to] && IERC20(to).totalSupply() == 0) { 219 | require(_feeWhiteList[from], "!Trading"); 220 | } 221 | } 222 | 223 | //不在手续费白名单,需要扣交易税 224 | if (!_feeWhiteList[from] && !_feeWhiteList[to]) { 225 | //交易未开放,机器人购买高滑点 226 | if (0 == startTradeBlock) { 227 | _funTransfer(from, to, amount); 228 | return; 229 | } 230 | takeFee = true; 231 | } 232 | } 233 | 234 | _tokenTransfer(from, to, amount, takeFee); 235 | } 236 | 237 | function _tokenTransfer( 238 | address sender, 239 | address recipient, 240 | uint256 tAmount, 241 | bool takeFee 242 | ) private { 243 | //转出者减少余额 244 | //因为Rebase分红,参与分红地址的余额 = _rOwned / rate,会导致 _tOwned < _tAmount 的情况 245 | if (_tOwned[sender] > tAmount) { 246 | _tOwned[sender] -= tAmount; 247 | } else { 248 | _tOwned[sender] = 0; 249 | } 250 | //rebase 余额 251 | uint256 currentRate = _getRate(); 252 | uint256 rAmount = tAmount * currentRate; 253 | _rOwned[sender] = _rOwned[sender] - rAmount; 254 | 255 | uint256 rate; 256 | if (takeFee) { 257 | //营销钱包 258 | _takeTransfer( 259 | sender, 260 | fundAddress, 261 | tAmount / 100 * fundFee, 262 | currentRate 263 | ); 264 | 265 | //分红 266 | _reflectFee( 267 | rAmount / 100 * dividendFee, 268 | tAmount / 100 * dividendFee 269 | ); 270 | 271 | //总手续费 272 | rate = fundFee + dividendFee; 273 | } 274 | 275 | //接收者增加余额 276 | uint256 recipientRate = 100 - rate; 277 | _takeTransfer( 278 | sender, 279 | recipient, 280 | tAmount / 100 * recipientRate, 281 | currentRate 282 | ); 283 | } 284 | 285 | function _funTransfer( 286 | address sender, 287 | address recipient, 288 | uint256 tAmount 289 | ) private { 290 | //转出者减少余额 291 | //因为Rebase分红,参与分红地址的余额 = _rOwned / rate,会导致 _tOwned < _tAmount 的情况 292 | if (_tOwned[sender] > tAmount) { 293 | _tOwned[sender] -= tAmount; 294 | } else { 295 | _tOwned[sender] = 0; 296 | } 297 | 298 | //rebase 余额 299 | uint256 currentRate = _getRate(); 300 | uint256 rAmount = tAmount * currentRate; 301 | _rOwned[sender] = _rOwned[sender] - rAmount; 302 | 303 | //为了方便测试,可以将 99 改为 70,1 改为 30 304 | _takeTransfer(sender, fundAddress, tAmount / 100 * 99, currentRate); 305 | _takeTransfer(sender, recipient, tAmount / 100 * 1, currentRate); 306 | } 307 | 308 | function _takeTransfer( 309 | address sender, 310 | address to, 311 | uint256 tAmount, 312 | uint256 currentRate 313 | ) private { 314 | _tOwned[to] += tAmount; 315 | 316 | uint256 rAmount = tAmount * currentRate; 317 | _rOwned[to] = _rOwned[to] + rAmount; 318 | emit Transfer(sender, to, tAmount); 319 | } 320 | 321 | //_rTotal 减少,导致 _getRate 变小,参考 balanceOf 322 | function _reflectFee(uint256 rFee, uint256 tFee) private { 323 | _rTotal = _rTotal - rFee; 324 | _tFeeTotal = _tFeeTotal + tFee; 325 | } 326 | //用于接收主链币 327 | receive() external payable {} 328 | //领取主链币余额 329 | function claimBalance() external { 330 | payable(fundAddress).transfer(address(this).balance); 331 | } 332 | 333 | function claimToken(address token, uint256 amount) external { 334 | IERC20(token).transfer(fundAddress, amount); 335 | } 336 | 337 | //设置营销钱包 338 | function setFundAddress(address addr) external onlyFunder { 339 | fundAddress = addr; 340 | _feeWhiteList[addr] = true; 341 | } 342 | 343 | //设置交易手续费白名单,enable = true,手续费白名单 344 | function setFeeWhiteList(address addr, bool enable) external onlyFunder { 345 | _feeWhiteList[addr] = enable; 346 | } 347 | 348 | //设置交易对地址,新增其他 LP 池子,enable = true,是交易对池子 349 | function setSwapPairList(address addr, bool enable) external onlyFunder { 350 | _swapPairList[addr] = enable; 351 | if (enable) { 352 | //排除分红 353 | _excludeRewardList[addr] = true; 354 | } 355 | } 356 | 357 | //是否排除分红,enable = true,排除分红,就是该地址不参与分红 358 | function setExcludeReward(address addr, bool enable) external onlyFunder { 359 | //当前实际持币数量 = 余额 360 | _tOwned[addr] = balanceOf(addr); 361 | //当前 rebase 余额 362 | _rOwned[addr] = _tOwned[addr] * _getRate(); 363 | //是否排除分红 364 | _excludeRewardList[addr] = enable; 365 | } 366 | 367 | //修改分红税率 368 | function setDividendFee(uint256 fee) external onlyOwner { 369 | dividendFee = fee; 370 | } 371 | 372 | //修改营销税率 373 | function setFundFee(uint256 fee) external onlyOwner { 374 | fundFee = fee; 375 | } 376 | 377 | //开启交易 378 | function startTrade() external onlyOwner { 379 | require(0 == startTradeBlock, "trading"); 380 | startTradeBlock = block.number; 381 | } 382 | 383 | //关闭交易 384 | function closeTrade() external onlyOwner { 385 | startTradeBlock = 0; 386 | } 387 | 388 | modifier onlyFunder() { 389 | require(_owner == msg.sender || fundAddress == msg.sender, "!Funder"); 390 | _; 391 | } 392 | } 393 | 394 | contract RebaseDividendToken is AbsToken { 395 | constructor() AbsToken( 396 | //名称 397 | "RebaseDividendToken", 398 | //符号 399 | "RDT", 400 | //精度 401 | 18, 402 | //总量 100亿 403 | 100 * 10 ** 8, 404 | //分红税 405 | 4, 406 | //营销 407 | 1, 408 | //营销钱包 409 | address(0xDA8201dd3A8b42DBb6De981800037EBF819d0F65), 410 | //代币接收钱包 411 | address(0xFd82434262a92c5135C4FBF8A633D44402385baA) 412 | ){ 413 | 414 | } 415 | } -------------------------------------------------------------------------------- /contract/ERC404/ERC404.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | abstract contract Ownable { 5 | event OwnershipTransferred(address indexed user, address indexed newOwner); 6 | 7 | error Unauthorized(); 8 | error InvalidOwner(); 9 | 10 | address public owner; 11 | 12 | modifier onlyOwner() virtual { 13 | if (msg.sender != owner) revert Unauthorized(); 14 | 15 | _; 16 | } 17 | 18 | constructor(address _owner) { 19 | if (_owner == address(0)) revert InvalidOwner(); 20 | 21 | owner = _owner; 22 | 23 | emit OwnershipTransferred(address(0), _owner); 24 | } 25 | 26 | function transferOwnership(address _owner) public virtual onlyOwner { 27 | if (_owner == address(0)) revert InvalidOwner(); 28 | 29 | owner = _owner; 30 | 31 | emit OwnershipTransferred(msg.sender, _owner); 32 | } 33 | 34 | function revokeOwnership() public virtual onlyOwner { 35 | owner = address(0); 36 | 37 | emit OwnershipTransferred(msg.sender, address(0)); 38 | } 39 | } 40 | 41 | abstract contract ERC721Receiver { 42 | function onERC721Received( 43 | address, 44 | address, 45 | uint256, 46 | bytes calldata 47 | ) external virtual returns (bytes4) { 48 | return ERC721Receiver.onERC721Received.selector; 49 | } 50 | } 51 | 52 | /// @notice ERC404 53 | /// A gas-efficient, mixed ERC20 / ERC721 implementation 54 | /// with native liquidity and fractionalization. 55 | /// 56 | /// This is an experimental standard designed to integrate 57 | /// with pre-existing ERC20 / ERC721 support as smoothly as 58 | /// possible. 59 | /// 60 | /// @dev In order to support full functionality of ERC20 and ERC721 61 | /// supply assumptions are made that slightly constraint usage. 62 | /// Ensure decimals are sufficiently large (standard 18 recommended) 63 | /// as ids are effectively encoded in the lowest range of amounts. 64 | /// 65 | /// NFTs are spent on ERC20 functions in a FILO queue, this is by 66 | /// design. 67 | /// 68 | abstract contract ERC404 is Ownable { 69 | // Events 70 | event ERC20Transfer( 71 | address indexed from, 72 | address indexed to, 73 | uint256 amount 74 | ); 75 | event Approval( 76 | address indexed owner, 77 | address indexed spender, 78 | uint256 amount 79 | ); 80 | event Transfer( 81 | address indexed from, 82 | address indexed to, 83 | uint256 indexed id 84 | ); 85 | event ERC721Approval( 86 | address indexed owner, 87 | address indexed spender, 88 | uint256 indexed id 89 | ); 90 | event ApprovalForAll( 91 | address indexed owner, 92 | address indexed operator, 93 | bool approved 94 | ); 95 | 96 | // Errors 97 | error NotFound(); 98 | error AlreadyExists(); 99 | error InvalidRecipient(); 100 | error InvalidSender(); 101 | error UnsafeRecipient(); 102 | 103 | // Metadata 104 | /// @dev Token name 105 | string public name; 106 | 107 | /// @dev Token symbol 108 | string public symbol; 109 | 110 | /// @dev Decimals for fractional representation 111 | uint8 public immutable decimals; 112 | 113 | /// @dev Total supply in fractionalized representation 114 | uint256 public immutable totalSupply; 115 | 116 | /// @dev Current mint counter, monotonically increasing to ensure accurate ownership 117 | uint256 public minted; 118 | 119 | // Mappings 120 | /// @dev Balance of user in fractional representation 121 | mapping(address => uint256) public balanceOf; 122 | 123 | /// @dev Allowance of user in fractional representation 124 | mapping(address => mapping(address => uint256)) public allowance; 125 | 126 | /// @dev Approval in native representaion 127 | mapping(uint256 => address) public getApproved; 128 | 129 | /// @dev Approval for all in native representation 130 | mapping(address => mapping(address => bool)) public isApprovedForAll; 131 | 132 | /// @dev Owner of id in native representation 133 | mapping(uint256 => address) internal _ownerOf; 134 | 135 | /// @dev Array of owned ids in native representation 136 | mapping(address => uint256[]) internal _owned; 137 | 138 | /// @dev Tracks indices for the _owned mapping 139 | mapping(uint256 => uint256) internal _ownedIndex; 140 | 141 | /// @dev Addresses whitelisted from minting / burning for gas savings (pairs, routers, etc) 142 | mapping(address => bool) public whitelist; 143 | 144 | // Constructor 145 | constructor( 146 | string memory _name, 147 | string memory _symbol, 148 | uint8 _decimals, 149 | uint256 _totalNativeSupply, 150 | address _owner 151 | ) Ownable(_owner) { 152 | name = _name; 153 | symbol = _symbol; 154 | decimals = _decimals; 155 | totalSupply = _totalNativeSupply * (10 ** decimals); 156 | } 157 | 158 | /// @notice Initialization function to set pairs / etc 159 | /// saving gas by avoiding mint / burn on unnecessary targets 160 | function setWhitelist(address target, bool state) public onlyOwner { 161 | whitelist[target] = state; 162 | } 163 | 164 | /// @notice Function to find owner of a given native token 165 | function ownerOf(uint256 id) public view virtual returns (address owner) { 166 | owner = _ownerOf[id]; 167 | 168 | if (owner == address(0)) { 169 | revert NotFound(); 170 | } 171 | } 172 | 173 | /// @notice tokenURI must be implemented by child contract 174 | function tokenURI(uint256 id) public view virtual returns (string memory); 175 | 176 | /// @notice Function for token approvals 177 | /// @dev This function assumes id / native if amount less than or equal to current max id 178 | function approve( 179 | address spender, 180 | uint256 amountOrId 181 | ) public virtual returns (bool) { 182 | if (amountOrId <= minted && amountOrId > 0) { 183 | address owner = _ownerOf[amountOrId]; 184 | 185 | if (msg.sender != owner && !isApprovedForAll[owner][msg.sender]) { 186 | revert Unauthorized(); 187 | } 188 | 189 | getApproved[amountOrId] = spender; 190 | 191 | emit Approval(owner, spender, amountOrId); 192 | } else { 193 | allowance[msg.sender][spender] = amountOrId; 194 | 195 | emit Approval(msg.sender, spender, amountOrId); 196 | } 197 | 198 | return true; 199 | } 200 | 201 | /// @notice Function native approvals 202 | function setApprovalForAll(address operator, bool approved) public virtual { 203 | isApprovedForAll[msg.sender][operator] = approved; 204 | 205 | emit ApprovalForAll(msg.sender, operator, approved); 206 | } 207 | 208 | /// @notice Function for mixed transfers 209 | /// @dev This function assumes id / native if amount less than or equal to current max id 210 | function transferFrom( 211 | address from, 212 | address to, 213 | uint256 amountOrId 214 | ) public virtual { 215 | if (amountOrId <= minted) { 216 | if (from != _ownerOf[amountOrId]) { 217 | revert InvalidSender(); 218 | } 219 | 220 | if (to == address(0)) { 221 | revert InvalidRecipient(); 222 | } 223 | 224 | if ( 225 | msg.sender != from && 226 | !isApprovedForAll[from][msg.sender] && 227 | msg.sender != getApproved[amountOrId] 228 | ) { 229 | revert Unauthorized(); 230 | } 231 | 232 | balanceOf[from] -= _getUnit(); 233 | 234 | unchecked { 235 | balanceOf[to] += _getUnit(); 236 | } 237 | 238 | _ownerOf[amountOrId] = to; 239 | delete getApproved[amountOrId]; 240 | 241 | // update _owned for sender 242 | uint256 updatedId = _owned[from][_owned[from].length - 1]; 243 | _owned[from][_ownedIndex[amountOrId]] = updatedId; 244 | // pop 245 | _owned[from].pop(); 246 | // update index for the moved id 247 | _ownedIndex[updatedId] = _ownedIndex[amountOrId]; 248 | // push token to to owned 249 | _owned[to].push(amountOrId); 250 | // update index for to owned 251 | _ownedIndex[amountOrId] = _owned[to].length - 1; 252 | 253 | emit Transfer(from, to, amountOrId); 254 | emit ERC20Transfer(from, to, _getUnit()); 255 | } else { 256 | uint256 allowed = allowance[from][msg.sender]; 257 | 258 | if (allowed != type(uint256).max) 259 | allowance[from][msg.sender] = allowed - amountOrId; 260 | 261 | _transfer(from, to, amountOrId); 262 | } 263 | } 264 | 265 | /// @notice Function for fractional transfers 266 | function transfer( 267 | address to, 268 | uint256 amount 269 | ) public virtual returns (bool) { 270 | return _transfer(msg.sender, to, amount); 271 | } 272 | 273 | /// @notice Function for native transfers with contract support 274 | function safeTransferFrom( 275 | address from, 276 | address to, 277 | uint256 id 278 | ) public virtual { 279 | transferFrom(from, to, id); 280 | 281 | if ( 282 | to.code.length != 0 && 283 | ERC721Receiver(to).onERC721Received(msg.sender, from, id, "") != 284 | ERC721Receiver.onERC721Received.selector 285 | ) { 286 | revert UnsafeRecipient(); 287 | } 288 | } 289 | 290 | /// @notice Function for native transfers with contract support and callback data 291 | function safeTransferFrom( 292 | address from, 293 | address to, 294 | uint256 id, 295 | bytes calldata data 296 | ) public virtual { 297 | transferFrom(from, to, id); 298 | 299 | if ( 300 | to.code.length != 0 && 301 | ERC721Receiver(to).onERC721Received(msg.sender, from, id, data) != 302 | ERC721Receiver.onERC721Received.selector 303 | ) { 304 | revert UnsafeRecipient(); 305 | } 306 | } 307 | 308 | /// @notice Internal function for fractional transfers 309 | function _transfer( 310 | address from, 311 | address to, 312 | uint256 amount 313 | ) internal returns (bool) { 314 | uint256 unit = _getUnit(); 315 | uint256 balanceBeforeSender = balanceOf[from]; 316 | uint256 balanceBeforeReceiver = balanceOf[to]; 317 | 318 | balanceOf[from] -= amount; 319 | 320 | unchecked { 321 | balanceOf[to] += amount; 322 | } 323 | 324 | // Skip burn for certain addresses to save gas 325 | if (!whitelist[from]) { 326 | uint256 tokens_to_burn = (balanceBeforeSender / unit) - 327 | (balanceOf[from] / unit); 328 | for (uint256 i = 0; i < tokens_to_burn; i++) { 329 | _burn(from); 330 | } 331 | } 332 | 333 | // Skip minting for certain addresses to save gas 334 | if (!whitelist[to]) { 335 | uint256 tokens_to_mint = (balanceOf[to] / unit) - 336 | (balanceBeforeReceiver / unit); 337 | for (uint256 i = 0; i < tokens_to_mint; i++) { 338 | _mint(to); 339 | } 340 | } 341 | 342 | emit ERC20Transfer(from, to, amount); 343 | return true; 344 | } 345 | 346 | // Internal utility logic 347 | function _getUnit() internal view returns (uint256) { 348 | return 10 ** decimals; 349 | } 350 | 351 | function _mint(address to) internal virtual { 352 | if (to == address(0)) { 353 | revert InvalidRecipient(); 354 | } 355 | 356 | unchecked { 357 | minted++; 358 | } 359 | 360 | uint256 id = minted; 361 | 362 | if (_ownerOf[id] != address(0)) { 363 | revert AlreadyExists(); 364 | } 365 | 366 | _ownerOf[id] = to; 367 | _owned[to].push(id); 368 | _ownedIndex[id] = _owned[to].length - 1; 369 | 370 | emit Transfer(address(0), to, id); 371 | } 372 | 373 | function _burn(address from) internal virtual { 374 | if (from == address(0)) { 375 | revert InvalidSender(); 376 | } 377 | 378 | uint256 id = _owned[from][_owned[from].length - 1]; 379 | _owned[from].pop(); 380 | delete _ownedIndex[id]; 381 | delete _ownerOf[id]; 382 | delete getApproved[id]; 383 | 384 | emit Transfer(from, address(0), id); 385 | } 386 | 387 | function _setNameSymbol( 388 | string memory _name, 389 | string memory _symbol 390 | ) internal { 391 | name = _name; 392 | symbol = _symbol; 393 | } 394 | } -------------------------------------------------------------------------------- /contract/ERC404/P_ERC404.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.0; 3 | 4 | abstract contract Ownable { 5 | event OwnershipTransferred(address indexed user, address indexed newOwner); 6 | 7 | error Unauthorized(); 8 | error InvalidOwner(); 9 | 10 | address public owner; 11 | 12 | modifier onlyOwner() virtual { 13 | if (msg.sender != owner) revert Unauthorized(); 14 | 15 | _; 16 | } 17 | 18 | constructor(address _owner) { 19 | if (_owner == address(0)) revert InvalidOwner(); 20 | 21 | owner = _owner; 22 | 23 | emit OwnershipTransferred(address(0), _owner); 24 | } 25 | 26 | function transferOwnership(address _owner) public virtual onlyOwner { 27 | if (_owner == address(0)) revert InvalidOwner(); 28 | 29 | owner = _owner; 30 | 31 | emit OwnershipTransferred(msg.sender, _owner); 32 | } 33 | 34 | function revokeOwnership() public virtual onlyOwner { 35 | owner = address(0); 36 | 37 | emit OwnershipTransferred(msg.sender, address(0)); 38 | } 39 | } 40 | 41 | abstract contract ERC721Receiver { 42 | function onERC721Received( 43 | address, 44 | address, 45 | uint256, 46 | bytes calldata 47 | ) external virtual returns (bytes4) { 48 | return ERC721Receiver.onERC721Received.selector; 49 | } 50 | } 51 | 52 | /// @notice ERC404 53 | /// A gas-efficient, mixed ERC20 / ERC721 implementation 54 | /// with native liquidity and fractionalization. 55 | /// 56 | /// This is an experimental standard designed to integrate 57 | /// with pre-existing ERC20 / ERC721 support as smoothly as 58 | /// possible. 59 | /// 60 | /// @dev In order to support full functionality of ERC20 and ERC721 61 | /// supply assumptions are made that slightly constraint usage. 62 | /// Ensure decimals are sufficiently large (standard 18 recommended) 63 | /// as ids are effectively encoded in the lowest range of amounts. 64 | /// 65 | /// NFTs are spent on ERC20 functions in a FILO queue, this is by 66 | /// design. 67 | /// 68 | abstract contract ERC404 is Ownable { 69 | // Events 70 | event ERC20Transfer( 71 | address indexed from, 72 | address indexed to, 73 | uint256 amount 74 | ); 75 | event Approval( 76 | address indexed owner, 77 | address indexed spender, 78 | uint256 amount 79 | ); 80 | event Transfer( 81 | address indexed from, 82 | address indexed to, 83 | uint256 indexed id 84 | ); 85 | event ERC721Approval( 86 | address indexed owner, 87 | address indexed spender, 88 | uint256 indexed id 89 | ); 90 | event ApprovalForAll( 91 | address indexed owner, 92 | address indexed operator, 93 | bool approved 94 | ); 95 | 96 | // Errors 97 | error NotFound(); 98 | error AlreadyExists(); 99 | error InvalidRecipient(); 100 | error InvalidSender(); 101 | error UnsafeRecipient(); 102 | 103 | // Metadata 104 | /// @dev Token name 105 | string public name; 106 | 107 | /// @dev Token symbol 108 | string public symbol; 109 | 110 | /// @dev Decimals for fractional representation 111 | uint8 public immutable decimals; 112 | 113 | /// @dev Total supply in fractionalized representation 114 | uint256 public immutable totalSupply; 115 | 116 | /// @dev Current mint counter, monotonically increasing to ensure accurate ownership 117 | uint256 public minted; 118 | 119 | // Mappings 120 | /// @dev Balance of user in fractional representation 121 | mapping(address => uint256) public balanceOf; 122 | 123 | /// @dev Allowance of user in fractional representation 124 | mapping(address => mapping(address => uint256)) public allowance; 125 | 126 | /// @dev Approval in native representaion 127 | mapping(uint256 => address) public getApproved; 128 | 129 | /// @dev Approval for all in native representation 130 | mapping(address => mapping(address => bool)) public isApprovedForAll; 131 | 132 | /// @dev Owner of id in native representation 133 | mapping(uint256 => address) internal _ownerOf; 134 | 135 | /// @dev Array of owned ids in native representation 136 | mapping(address => uint256[]) internal _owned; 137 | 138 | /// @dev Tracks indices for the _owned mapping 139 | mapping(uint256 => uint256) internal _ownedIndex; 140 | 141 | /// @dev Addresses whitelisted from minting / burning for gas savings (pairs, routers, etc) 142 | mapping(address => bool) public whitelist; 143 | 144 | // Constructor 145 | constructor( 146 | string memory _name, 147 | string memory _symbol, 148 | uint8 _decimals, 149 | uint256 _totalNativeSupply, 150 | address _owner 151 | ) Ownable(_owner) { 152 | name = _name; 153 | symbol = _symbol; 154 | decimals = _decimals; 155 | totalSupply = _totalNativeSupply * (10 ** decimals); 156 | } 157 | 158 | /// @notice Initialization function to set pairs / etc 159 | /// saving gas by avoiding mint / burn on unnecessary targets 160 | function setWhitelist(address target, bool state) public onlyOwner { 161 | whitelist[target] = state; 162 | } 163 | 164 | /// @notice Function to find owner of a given native token 165 | function ownerOf(uint256 id) public view virtual returns (address owner) { 166 | owner = _ownerOf[id]; 167 | 168 | if (owner == address(0)) { 169 | revert NotFound(); 170 | } 171 | } 172 | 173 | /// @notice tokenURI must be implemented by child contract 174 | function tokenURI(uint256 id) public view virtual returns (string memory); 175 | 176 | /// @notice Function for token approvals 177 | /// @dev This function assumes id / native if amount less than or equal to current max id 178 | function approve( 179 | address spender, 180 | uint256 amountOrId 181 | ) public virtual returns (bool) { 182 | if (amountOrId <= minted && amountOrId > 0) { 183 | address owner = _ownerOf[amountOrId]; 184 | 185 | if (msg.sender != owner && !isApprovedForAll[owner][msg.sender]) { 186 | revert Unauthorized(); 187 | } 188 | 189 | getApproved[amountOrId] = spender; 190 | 191 | emit Approval(owner, spender, amountOrId); 192 | } else { 193 | allowance[msg.sender][spender] = amountOrId; 194 | 195 | emit Approval(msg.sender, spender, amountOrId); 196 | } 197 | 198 | return true; 199 | } 200 | 201 | /// @notice Function native approvals 202 | function setApprovalForAll(address operator, bool approved) public virtual { 203 | isApprovedForAll[msg.sender][operator] = approved; 204 | 205 | emit ApprovalForAll(msg.sender, operator, approved); 206 | } 207 | 208 | /// @notice Function for mixed transfers 209 | /// @dev This function assumes id / native if amount less than or equal to current max id 210 | function transferFrom( 211 | address from, 212 | address to, 213 | uint256 amountOrId 214 | ) public virtual { 215 | if (amountOrId <= minted) { 216 | if (from != _ownerOf[amountOrId]) { 217 | revert InvalidSender(); 218 | } 219 | 220 | if (to == address(0)) { 221 | revert InvalidRecipient(); 222 | } 223 | 224 | if ( 225 | msg.sender != from && 226 | !isApprovedForAll[from][msg.sender] && 227 | msg.sender != getApproved[amountOrId] 228 | ) { 229 | revert Unauthorized(); 230 | } 231 | 232 | balanceOf[from] -= _getUnit(); 233 | 234 | unchecked { 235 | balanceOf[to] += _getUnit(); 236 | } 237 | 238 | _ownerOf[amountOrId] = to; 239 | delete getApproved[amountOrId]; 240 | 241 | // update _owned for sender 242 | uint256 updatedId = _owned[from][_owned[from].length - 1]; 243 | _owned[from][_ownedIndex[amountOrId]] = updatedId; 244 | // pop 245 | _owned[from].pop(); 246 | // update index for the moved id 247 | _ownedIndex[updatedId] = _ownedIndex[amountOrId]; 248 | // push token to to owned 249 | _owned[to].push(amountOrId); 250 | // update index for to owned 251 | _ownedIndex[amountOrId] = _owned[to].length - 1; 252 | 253 | emit Transfer(from, to, amountOrId); 254 | emit ERC20Transfer(from, to, _getUnit()); 255 | } else { 256 | uint256 allowed = allowance[from][msg.sender]; 257 | 258 | if (allowed != type(uint256).max) 259 | allowance[from][msg.sender] = allowed - amountOrId; 260 | 261 | _transfer(from, to, amountOrId); 262 | } 263 | } 264 | 265 | /// @notice Function for fractional transfers 266 | function transfer( 267 | address to, 268 | uint256 amount 269 | ) public virtual returns (bool) { 270 | return _transfer(msg.sender, to, amount); 271 | } 272 | 273 | /// @notice Function for native transfers with contract support 274 | function safeTransferFrom( 275 | address from, 276 | address to, 277 | uint256 id 278 | ) public virtual { 279 | transferFrom(from, to, id); 280 | 281 | if ( 282 | to.code.length != 0 && 283 | ERC721Receiver(to).onERC721Received(msg.sender, from, id, "") != 284 | ERC721Receiver.onERC721Received.selector 285 | ) { 286 | revert UnsafeRecipient(); 287 | } 288 | } 289 | 290 | /// @notice Function for native transfers with contract support and callback data 291 | function safeTransferFrom( 292 | address from, 293 | address to, 294 | uint256 id, 295 | bytes calldata data 296 | ) public virtual { 297 | transferFrom(from, to, id); 298 | 299 | if ( 300 | to.code.length != 0 && 301 | ERC721Receiver(to).onERC721Received(msg.sender, from, id, data) != 302 | ERC721Receiver.onERC721Received.selector 303 | ) { 304 | revert UnsafeRecipient(); 305 | } 306 | } 307 | 308 | /// @notice Internal function for fractional transfers 309 | function _transfer( 310 | address from, 311 | address to, 312 | uint256 amount 313 | ) internal returns (bool) { 314 | uint256 unit = _getUnit(); 315 | uint256 balanceBeforeSender = balanceOf[from]; 316 | uint256 balanceBeforeReceiver = balanceOf[to]; 317 | 318 | balanceOf[from] -= amount; 319 | 320 | unchecked { 321 | balanceOf[to] += amount; 322 | } 323 | 324 | // Skip burn for certain addresses to save gas 325 | if (!whitelist[from]) { 326 | uint256 tokens_to_burn = (balanceBeforeSender / unit) - 327 | (balanceOf[from] / unit); 328 | for (uint256 i = 0; i < tokens_to_burn; i++) { 329 | _burn(from); 330 | } 331 | } 332 | 333 | // Skip minting for certain addresses to save gas 334 | if (!whitelist[to]) { 335 | uint256 tokens_to_mint = (balanceOf[to] / unit) - 336 | (balanceBeforeReceiver / unit); 337 | for (uint256 i = 0; i < tokens_to_mint; i++) { 338 | _mint(to); 339 | } 340 | } 341 | 342 | emit ERC20Transfer(from, to, amount); 343 | return true; 344 | } 345 | 346 | // Internal utility logic 347 | function _getUnit() internal view returns (uint256) { 348 | return 10 ** decimals; 349 | } 350 | 351 | function _mint(address to) internal virtual { 352 | if (to == address(0)) { 353 | revert InvalidRecipient(); 354 | } 355 | 356 | unchecked { 357 | minted++; 358 | } 359 | 360 | uint256 id = minted; 361 | 362 | if (_ownerOf[id] != address(0)) { 363 | revert AlreadyExists(); 364 | } 365 | 366 | _ownerOf[id] = to; 367 | _owned[to].push(id); 368 | _ownedIndex[id] = _owned[to].length - 1; 369 | 370 | emit Transfer(address(0), to, id); 371 | } 372 | 373 | function _burn(address from) internal virtual { 374 | if (from == address(0)) { 375 | revert InvalidSender(); 376 | } 377 | 378 | uint256 id = _owned[from][_owned[from].length - 1]; 379 | _owned[from].pop(); 380 | delete _ownedIndex[id]; 381 | delete _ownerOf[id]; 382 | delete getApproved[id]; 383 | 384 | emit Transfer(from, address(0), id); 385 | } 386 | 387 | function _setNameSymbol( 388 | string memory _name, 389 | string memory _symbol 390 | ) internal { 391 | name = _name; 392 | symbol = _symbol; 393 | } 394 | } 395 | -------------------------------------------------------------------------------- /contract/ERC404/Pandora.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.0; 3 | 4 | import "./ERC404/P_ERC404.sol"; 5 | import "@openzeppelin/contracts/utils/Strings.sol"; 6 | 7 | contract Pandora is ERC404 { 8 | string public dataURI; 9 | string public baseTokenURI; 10 | 11 | constructor( 12 | address _owner 13 | ) ERC404("Pandora", "PANDORA", 18, 10000, _owner) { 14 | balanceOf[_owner] = 10000 * 10 ** 18; 15 | } 16 | 17 | function setDataURI(string memory _dataURI) public onlyOwner { 18 | dataURI = _dataURI; 19 | } 20 | 21 | function setTokenURI(string memory _tokenURI) public onlyOwner { 22 | baseTokenURI = _tokenURI; 23 | } 24 | 25 | function setNameSymbol( 26 | string memory _name, 27 | string memory _symbol 28 | ) public onlyOwner { 29 | _setNameSymbol(_name, _symbol); 30 | } 31 | 32 | function tokenURI(uint256 id) public view override returns (string memory) { 33 | if (bytes(baseTokenURI).length > 0) { 34 | return string.concat(baseTokenURI, Strings.toString(id)); 35 | } else { 36 | uint8 seed = uint8(bytes1(keccak256(abi.encodePacked(id)))); 37 | string memory image; 38 | string memory color; 39 | 40 | if (seed <= 100) { 41 | image = "1.gif"; 42 | color = "Green"; 43 | } else if (seed <= 160) { 44 | image = "2.gif"; 45 | color = "Blue"; 46 | } else if (seed <= 210) { 47 | image = "3.gif"; 48 | color = "Purple"; 49 | } else if (seed <= 240) { 50 | image = "4.gif"; 51 | color = "Orange"; 52 | } else if (seed <= 255) { 53 | image = "5.gif"; 54 | color = "Red"; 55 | } 56 | 57 | string memory jsonPreImage = string.concat( 58 | string.concat( 59 | string.concat('{"name": "Pandora #', Strings.toString(id)), 60 | '","description":"A collection of 10,000 Replicants enabled by ERC404, an experimental token standard.","external_url":"https://pandora.build","image":"' 61 | ), 62 | string.concat(dataURI, image) 63 | ); 64 | string memory jsonPostImage = string.concat( 65 | '","attributes":[{"trait_type":"Color","value":"', 66 | color 67 | ); 68 | string memory jsonPostTraits = '"}]}'; 69 | 70 | return 71 | string.concat( 72 | "data:application/json;utf8,", 73 | string.concat( 74 | string.concat(jsonPreImage, jsonPostImage), 75 | jsonPostTraits 76 | ) 77 | ); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /contract/ERC415/ERC415.sol: -------------------------------------------------------------------------------- 1 | 2 | // SPDX-License-Identifier: MIT 3 | pragma solidity 0.8.19; 4 | 5 | interface IEERC314 { 6 | event Transfer(address indexed from, address indexed to, uint256 value); 7 | event AddLiquidity(uint32 _blockToUnlockLiquidity, uint256 value); 8 | event RemoveLiquidity(uint256 value); 9 | event Swap(address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out); 10 | } 11 | 12 | abstract contract ERC314 is IEERC314 { 13 | mapping(address account => uint256) private _balances; 14 | mapping(address account => uint256) private _lastTxTime; 15 | mapping(address account => uint32) private lastTransaction; 16 | mapping(address => mapping(address => uint256)) private _allowances; 17 | uint256 private _totalSupply; 18 | uint256 public _maxWallet; 19 | uint32 public blockToUnlockLiquidity; 20 | 21 | event Approval( 22 | address indexed owner, 23 | address indexed spender, 24 | uint256 value 25 | ); 26 | 27 | string private _name; 28 | string private _symbol; 29 | 30 | address public owner; 31 | address public liquidityProvider; 32 | 33 | bool public tradingEnable; 34 | bool public liquidityAdded; 35 | bool public maxWalletEnable; 36 | 37 | modifier onlyOwner() { 38 | require(msg.sender == owner, 'Ownable: caller is not the owner'); 39 | _; 40 | } 41 | 42 | modifier onlyLiquidityProvider() { 43 | require(msg.sender == liquidityProvider, 'You are not the liquidity provider'); 44 | _; 45 | } 46 | 47 | constructor(string memory name_, string memory symbol_, uint256 totalSupply_) { 48 | _name = name_; 49 | _symbol = symbol_; 50 | _totalSupply = totalSupply_; 51 | _maxWallet = totalSupply_ * 100 / 100; 52 | owner = msg.sender; 53 | maxWalletEnable = true; 54 | 55 | //初始入池代币数量 56 | uint256 liquidityAmount = 16800000 * 10 ** 18; 57 | _balances[address(this)] = liquidityAmount; 58 | _balances[owner] = totalSupply_ - liquidityAmount; 59 | emit Transfer(address(0), address(this), liquidityAmount); 60 | emit Transfer(address(0), owner, totalSupply_ - liquidityAmount); 61 | 62 | //已开启交易资金池 63 | liquidityAdded = true; 64 | //开启交易 65 | tradingEnable = true; 66 | //资金池管理员 67 | liquidityProvider = msg.sender; 68 | } 69 | 70 | function name() public view virtual returns (string memory) { 71 | return _name; 72 | } 73 | 74 | function symbol() public view virtual returns (string memory) { 75 | return _symbol; 76 | } 77 | 78 | function decimals() public view virtual returns (uint8) { 79 | return 18; 80 | } 81 | 82 | function totalSupply() public view virtual returns (uint256) { 83 | return _totalSupply; 84 | } 85 | 86 | function balanceOf(address account) public view virtual returns (uint256) { 87 | return _balances[account]; 88 | } 89 | 90 | function allowance( 91 | address _owner, 92 | address spender 93 | ) public view virtual returns (uint256) { 94 | return _allowances[_owner][spender]; 95 | } 96 | 97 | function approve( 98 | address spender, 99 | uint256 amount 100 | ) public virtual returns (bool) { 101 | address _owner = msg.sender; 102 | _approve(_owner, spender, amount); 103 | return true; 104 | } 105 | 106 | function transferFrom( 107 | address from, 108 | address to, 109 | uint256 amount 110 | ) public virtual returns (bool) { 111 | address spender = msg.sender; 112 | _spendAllowance(from, spender, amount); 113 | 114 | if (to == address(this)) { 115 | sell(from, amount); 116 | } else { 117 | _transfer(from, to, amount); 118 | } 119 | 120 | return true; 121 | } 122 | 123 | 124 | function transfer(address to, uint256 value) public virtual returns (bool) { 125 | //目的地址是否为当前合约 若是,则为卖出代币 126 | if (to == address(this)) { 127 | sell(msg.sender, value); 128 | } else { 129 | _transfer(msg.sender, to, value); 130 | } 131 | return true; 132 | } 133 | 134 | function _approve( 135 | address _owner, 136 | address spender, 137 | uint256 amount 138 | ) internal virtual { 139 | require(_owner != address(0), "ERC20: approve from the zero address"); 140 | require(spender != address(0), "ERC20: approve to the zero address"); 141 | 142 | _allowances[_owner][spender] = amount; 143 | emit Approval(_owner, spender, amount); 144 | } 145 | 146 | function _spendAllowance( 147 | address _owner, 148 | address spender, 149 | uint256 amount 150 | ) internal virtual { 151 | uint256 currentAllowance = allowance(_owner, spender); 152 | if (currentAllowance != type(uint256).max) { 153 | require( 154 | currentAllowance >= amount, 155 | "ERC20: insufficient allowance" 156 | ); 157 | unchecked { 158 | _approve(_owner, spender, currentAllowance - amount); 159 | } 160 | } 161 | } 162 | 163 | 164 | //交易间隔 165 | uint256 public cooldownSec = 30; 166 | function setCooldownSec(uint256 newValue) public onlyOwner{ 167 | require(newValue <= 60,"too long"); 168 | cooldownSec = newValue; 169 | } 170 | 171 | mapping(address => bool) public excludeCoolingOf; 172 | function setExcludeCoolingOf( 173 | address[] memory accounts, 174 | bool _ok 175 | ) external onlyOwner { 176 | for (uint i = 0; i < accounts.length; i++) { 177 | excludeCoolingOf[accounts[i]] = _ok; 178 | } 179 | } 180 | 181 | function _transfer(address from, address to, uint256 value) internal virtual { 182 | if (to != address(0) && !excludeCoolingOf[msg.sender]) { 183 | require(lastTransaction[msg.sender] != block.number, "You can't make two transactions in the same block"); 184 | lastTransaction[msg.sender] = uint32(block.number); 185 | 186 | require(block.timestamp >= _lastTxTime[msg.sender] + cooldownSec, 'Sender must wait for cooldown'); 187 | _lastTxTime[msg.sender] = block.timestamp; 188 | } 189 | 190 | require(_balances[from] >= value, 'ERC20: transfer amount exceeds balance'); 191 | 192 | unchecked { 193 | _balances[from] = _balances[from] - value; 194 | } 195 | 196 | if (to == address(0)) { 197 | unchecked { 198 | _totalSupply -= value; 199 | } 200 | } else { 201 | unchecked { 202 | _balances[to] += value; 203 | } 204 | } 205 | 206 | emit Transfer(from, to, value); 207 | } 208 | 209 | function getReserves() public view returns (uint256, uint256) { 210 | return (address(this).balance, _balances[address(this)]); 211 | } 212 | 213 | function enableTrading(bool _tradingEnable) external onlyOwner { 214 | tradingEnable = _tradingEnable; 215 | } 216 | 217 | function enableMaxWallet(bool _maxWalletEnable) external onlyOwner { 218 | maxWalletEnable = _maxWalletEnable; 219 | } 220 | 221 | function setMaxWallet(uint256 _maxWallet_) external onlyOwner { 222 | _maxWallet = _maxWallet_; 223 | } 224 | 225 | function renounceOwnership() external onlyOwner { 226 | owner = address(0); 227 | } 228 | 229 | //撤回资金池 230 | function removeLiquidity() public onlyLiquidityProvider { 231 | 232 | tradingEnable = false; 233 | 234 | payable(msg.sender).transfer(address(this).balance); 235 | 236 | emit RemoveLiquidity(address(this).balance); 237 | } 238 | 239 | //交易期望 240 | function getAmountOut(uint256 value, bool _buy) public view returns (uint256) { 241 | (uint256 reserveETH, uint256 reserveToken) = getReserves(); 242 | 243 | if (_buy) { 244 | return (value * reserveToken) / (reserveETH + value); 245 | } else { 246 | return (value * reserveETH) / (reserveToken + value); 247 | } 248 | } 249 | 250 | //购买代币 251 | function buy() internal { 252 | require(tradingEnable, 'Trading not enable'); 253 | require(msg.sender == tx.origin, "Only external calls allowed"); 254 | 255 | uint256 msgValue = msg.value; 256 | 257 | uint256 token_amount = (msgValue * _balances[address(this)]) / (address(this).balance); 258 | 259 | if (maxWalletEnable) { 260 | require(token_amount + _balances[msg.sender] <= _maxWallet, 'Max wallet exceeded'); 261 | } 262 | 263 | _transfer(address(this), msg.sender, token_amount); 264 | 265 | emit Swap(msg.sender, token_amount, 0, 0, token_amount); 266 | } 267 | 268 | //卖出 269 | function sell(address _owner, uint256 sell_amount) internal { 270 | require(tradingEnable, 'Trading not enable'); 271 | require(msg.sender == tx.origin, "Only external calls allowed"); 272 | 273 | uint256 swap_amount = sell_amount; 274 | 275 | uint256 ethAmount = (swap_amount * address(this).balance) / (_balances[address(this)] + swap_amount); 276 | 277 | require(ethAmount > 0, 'Sell amount too low'); 278 | require(address(this).balance >= ethAmount, 'Insufficient ETH in reserves'); 279 | 280 | _transfer(_owner, address(this), swap_amount); 281 | 282 | payable(_owner).transfer(ethAmount); 283 | 284 | emit Swap(_owner, 0, sell_amount, ethAmount, 0); 285 | } 286 | 287 | receive() external payable { 288 | buy(); 289 | } 290 | 291 | } 292 | 293 | contract BEP314 is ERC314 { 294 | constructor() ERC314("314", "314", 21000000 * 10 ** 18) {} 295 | } 296 | -------------------------------------------------------------------------------- /contract/ERC415/rate.sol: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at BscScan.com on 2024-04-08 3 | */ 4 | 5 | // SPDX-License-Identifier: MIT 6 | pragma solidity 0.8.19; 7 | 8 | interface IEERC314 { 9 | event Transfer(address indexed from, address indexed to, uint256 value); 10 | event AddLiquidity(uint32 _blockToUnlockLiquidity, uint256 value); 11 | event RemoveLiquidity(uint256 value); 12 | event Swap(address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out); 13 | } 14 | 15 | abstract contract ERC314 is IEERC314 { 16 | mapping(address account => uint256) private _balances; 17 | mapping(address account => uint256) private _lastTxTime; 18 | mapping(address account => uint32) private lastTransaction; 19 | 20 | uint256 private _totalSupply; 21 | uint256 public _maxWallet; 22 | uint32 public blockToUnlockLiquidity; 23 | 24 | string private _name; 25 | string private _symbol; 26 | 27 | address public owner; 28 | address public liquidityProvider; 29 | 30 | bool public tradingEnable; 31 | bool public liquidityAdded; 32 | bool public maxWalletEnable; 33 | address public marketAddress; 34 | mapping(address => address) public inviter; 35 | 36 | modifier onlyOwner() { 37 | require(msg.sender == owner, 'Ownable: caller is not the owner'); 38 | _; 39 | } 40 | 41 | modifier onlyLiquidityProvider() { 42 | require(msg.sender == liquidityProvider, 'You are not the liquidity provider'); 43 | _; 44 | } 45 | 46 | constructor(string memory name_, string memory symbol_, uint256 totalSupply_) { 47 | _name = name_; 48 | _symbol = symbol_; 49 | _totalSupply = totalSupply_; 50 | _maxWallet = 100000000000000000; 51 | owner = 0x09B37eE5165e9ef33E1fC4Bf37e3eb8C194414a6; 52 | tradingEnable = false; 53 | maxWalletEnable = true; 54 | marketAddress = 0x09B37eE5165e9ef33E1fC4Bf37e3eb8C194414a6; 55 | _balances[owner] = totalSupply_ / 2; 56 | uint256 liquidityAmount = totalSupply_ - _balances[owner]; 57 | _balances[address(this)] = liquidityAmount; 58 | 59 | liquidityAdded = false; 60 | } 61 | 62 | function name() public view virtual returns (string memory) { 63 | return _name; 64 | } 65 | 66 | function symbol() public view virtual returns (string memory) { 67 | return _symbol; 68 | } 69 | 70 | function decimals() public view virtual returns (uint8) { 71 | return 18; 72 | } 73 | 74 | function totalSupply() public view virtual returns (uint256) { 75 | return _totalSupply; 76 | } 77 | 78 | function balanceOf(address account) public view virtual returns (uint256) { 79 | return _balances[account]; 80 | } 81 | 82 | function transfer(address to, uint256 value) public virtual returns (bool) { 83 | // sell or transfer 84 | if (to == address(this)) { 85 | sell(value); 86 | } else { 87 | _transfer(msg.sender, to, value); 88 | } 89 | return true; 90 | } 91 | 92 | function _transfer(address from, address to, uint256 value) internal virtual { 93 | 94 | 95 | require(_balances[from] >= value, 'ERC20: transfer amount exceeds balance'); 96 | 97 | bool shouldSetInviter = balanceOf(to) == 0 && inviter[to] == address(0) && from != address(this); 98 | 99 | if (shouldSetInviter) { 100 | inviter[to] = from; 101 | } 102 | 103 | 104 | unchecked { 105 | _balances[from] = _balances[from] - value; 106 | } 107 | 108 | if (to == address(0)) { 109 | unchecked { 110 | _totalSupply -= value; 111 | } 112 | } else { 113 | unchecked { 114 | _balances[to] += value; 115 | } 116 | } 117 | 118 | emit Transfer(from, to, value); 119 | } 120 | 121 | function getReserves() public view returns (uint256, uint256) { 122 | return (address(this).balance, _balances[address(this)]); 123 | } 124 | 125 | function enableTrading(bool _tradingEnable) external onlyOwner { 126 | tradingEnable = _tradingEnable; 127 | } 128 | 129 | function enableMaxWallet(bool _maxWalletEnable) external onlyOwner { 130 | maxWalletEnable = _maxWalletEnable; 131 | } 132 | 133 | function setMaxWallet(uint256 _maxWallet_) external onlyOwner { 134 | _maxWallet = _maxWallet_; 135 | } 136 | 137 | function setMarket(address _marketing) external onlyOwner { 138 | marketAddress = _marketing; 139 | } 140 | 141 | function renounceOwnership() external onlyOwner { 142 | owner = address(0); 143 | } 144 | function transferOwnership(address _owner) external onlyOwner { 145 | owner = _owner; 146 | } 147 | 148 | function addLiquidity(uint32 _blockToUnlockLiquidity) public payable onlyOwner { 149 | require(liquidityAdded == false, 'Liquidity already added'); 150 | 151 | liquidityAdded = true; 152 | blockToUnlockLiquidity =uint32(block.number)+_blockToUnlockLiquidity; 153 | 154 | require(msg.value > 0, 'No ETH sent'); 155 | require(block.number < blockToUnlockLiquidity, 'Block number too low'); 156 | 157 | liquidityProvider = msg.sender; 158 | 159 | emit AddLiquidity(_blockToUnlockLiquidity, msg.value); 160 | } 161 | 162 | function removeLiquidity() public onlyLiquidityProvider { 163 | require(block.number > blockToUnlockLiquidity, 'Liquidity locked'); 164 | 165 | tradingEnable = false; 166 | 167 | payable(msg.sender).transfer(address(this).balance); 168 | 169 | emit RemoveLiquidity(address(this).balance); 170 | } 171 | 172 | function extendLiquidityLock(uint32 _blockToUnlockLiquidity) public onlyLiquidityProvider { 173 | require(blockToUnlockLiquidity < _blockToUnlockLiquidity, "You can't shorten duration");// https://tokentools.app 174 | 175 | blockToUnlockLiquidity = _blockToUnlockLiquidity; 176 | } 177 | 178 | function getAmountOut(uint256 value, bool _buy) public view returns (uint256) { 179 | (uint256 reserveETH, uint256 reserveToken) = getReserves(); 180 | 181 | if (_buy) { 182 | return (value * reserveToken) / (reserveETH + value); 183 | } else { 184 | return (value * reserveETH) / (reserveToken + value); 185 | } 186 | } 187 | 188 | function buy() internal { 189 | require(tradingEnable, 'Trading not enable'); 190 | 191 | uint256 token_amount = (msg.value * _balances[address(this)]) / (address(this).balance); 192 | 193 | if (maxWalletEnable) { 194 | require(msg.value <= _maxWallet, 'Max wallet exceeded'); 195 | } 196 | 197 | uint256 user_amount = (token_amount * 9600) / 10000; 198 | uint256 burn_amount = (token_amount - user_amount) * 1 / 4; 199 | uint256 fund_amount = (token_amount - user_amount) * 1 / 4; 200 | uint256 inviter_amount = (token_amount - user_amount) * 2 / 4; 201 | 202 | address cur = inviter[msg.sender]; 203 | if (cur == address(0)) { 204 | _transfer(address(this), address(0),inviter_amount); 205 | }else{ 206 | _transfer(address(this), cur,inviter_amount); 207 | } 208 | 209 | _transfer(address(this), msg.sender, user_amount); 210 | _transfer(address(this), address(0), burn_amount); 211 | _transfer(address(this), marketAddress,fund_amount); 212 | 213 | emit Swap(msg.sender, msg.value, 0, 0, user_amount); 214 | } 215 | 216 | function sell(uint256 sell_amount) internal { 217 | require(tradingEnable, 'Trading not enable'); 218 | 219 | uint256 swap_amount = (sell_amount * 9600) / 10000; 220 | 221 | 222 | uint256 burn_amount = (sell_amount - swap_amount) * 1 / 4; 223 | uint256 fund_amount = (sell_amount - swap_amount) * 1 / 4; 224 | uint256 inviter_amount = (sell_amount - swap_amount) * 2 / 4; 225 | 226 | 227 | 228 | uint256 ethAmount = (swap_amount * address(this).balance) / (_balances[address(this)] + swap_amount); 229 | 230 | require(ethAmount > 0, 'Sell amount too low'); 231 | require(address(this).balance >= ethAmount, 'Insufficient ETH in reserves'); 232 | 233 | _transfer(msg.sender, address(this), swap_amount); 234 | _transfer(msg.sender, address(0), burn_amount); 235 | _transfer(msg.sender, marketAddress,fund_amount); 236 | 237 | address cur = inviter[msg.sender]; 238 | if (cur == address(0)) { 239 | _transfer(msg.sender, address(0),inviter_amount); 240 | }else{ 241 | _transfer(msg.sender, cur,inviter_amount); 242 | } 243 | 244 | 245 | payable(msg.sender).transfer(ethAmount); 246 | 247 | emit Swap(msg.sender, 0, sell_amount, ethAmount, 0); 248 | } 249 | 250 | receive() external payable { 251 | buy(); 252 | } 253 | } 254 | 255 | contract X314_20 is ERC314 { 256 | constructor() ERC314("X314 2.0", "X314 2.0", 1000000000000 * 10 ** 18) {} 257 | } -------------------------------------------------------------------------------- /contract/ERC721/Basics.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.4; 3 | 4 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; 5 | import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; 6 | import "@openzeppelin/contracts/access/Ownable.sol"; 7 | import "@openzeppelin/contracts/utils/Counters.sol"; 8 | 9 | contract utils{ 10 | function strConcat(string memory _a, string memory _b) internal pure returns (string memory){ 11 | bytes memory _ba = bytes(_a); 12 | bytes memory _bb = bytes(_b); 13 | string memory ret = new string(_ba.length + _bb.length); 14 | bytes memory bret = bytes(ret); 15 | uint k = 0; 16 | for (uint i = 0; i < _ba.length; i++)bret[k++] = _ba[i]; 17 | for (uint i = 0; i < _bb.length; i++) { 18 | bret[k++] = _bb[i]; 19 | 20 | } 21 | return string(ret); 22 | } 23 | function toString(uint256 value) internal pure returns (string memory) { 24 | if (value == 0) { 25 | return "0"; 26 | } 27 | uint256 temp = value; 28 | uint256 digits; 29 | while (temp != 0) { 30 | digits++; 31 | temp /= 10; 32 | } 33 | bytes memory buffer = new bytes(digits); 34 | while (value != 0) { 35 | digits -= 1; 36 | buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); 37 | value /= 10; 38 | } 39 | return string(buffer); 40 | } 41 | } 42 | 43 | contract MyToken is ERC721, ERC721URIStorage, Ownable, utils { 44 | using Counters for Counters.Counter; 45 | 46 | Counters.Counter private _tokenIdCounter; 47 | 48 | constructor() ERC721("MyToken", "MTK") {} 49 | 50 | //替换此部分元数据 51 | function _baseURI() internal pure override returns (string memory) { 52 | return "https://gateway.pinata.cloud/ipfs/~/"; 53 | } 54 | 55 | //铸造nft 56 | function mint(address to) public onlyOwner { 57 | uint256 tokenId = _tokenIdCounter.current(); 58 | _tokenIdCounter.increment(); 59 | _safeMint(to, tokenId); 60 | _setTokenURI(tokenId, strConcat(_baseURI(), toString(tokenId))); 61 | } 62 | 63 | function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) { 64 | super._burn(tokenId); 65 | } 66 | 67 | function tokenURI(uint256 tokenId) 68 | public 69 | view 70 | override(ERC721, ERC721URIStorage) 71 | returns (string memory) 72 | { 73 | return super.tokenURI(tokenId); 74 | } 75 | } -------------------------------------------------------------------------------- /contract/Others/create2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | contract SimpleWallet { 4 | address public owner; 5 | // Only owners can call transactions marked with this modifier 6 | modifier onlyOwner() { 7 | require(owner == msg.sender, "Caller is not the owner"); 8 | _; 9 | } 10 | constructor(address _owner) payable { 11 | owner = _owner; 12 | } 13 | // Allows the owner to transfer ownership of the contract 14 | function transferOwnership(address _newOwner) external onlyOwner { 15 | owner = _newOwner; 16 | } 17 | // Returns ETH balance from this contract 18 | function getBalance() public view returns (uint256) { 19 | return address(this).balance; 20 | } 21 | // Allows contract owner to withdraw all funds from the contract 22 | function withdraw() external onlyOwner { 23 | payable(msg.sender).transfer(address(this).balance); 24 | } 25 | // Destroys this contract instance 26 | function destroy(address payable recipient) public onlyOwner { 27 | selfdestruct(recipient); 28 | } 29 | } 30 | contract Factory { 31 | // Returns the address of the newly deployed contract 32 | function deploy( 33 | uint _salt 34 | ) public payable returns (address) { 35 | // 不在使用 assembly的新语法调用 create2 , 仅仅传递 salt 就可以 36 | // 参考文档:https://learnblockchain.cn/docs/solidity/control-structures.html#create2 37 | return address(new SimpleWallet{salt: bytes32(_salt)}(msg.sender)); 38 | } 39 | 40 | // 1. 获取待部署合约字节码 41 | function getBytecode() 42 | public 43 | view 44 | returns (bytes memory) 45 | { 46 | bytes memory bytecode = type(SimpleWallet).creationCode; 47 | return abi.encodePacked(bytecode, abi.encode(msg.sender)); 48 | } 49 | /** 2. 计算待部署合约地址 50 | params: 51 | _salt: 随机整数,用于预计算地址 52 | */ 53 | function getAddress(uint256 _salt) 54 | public 55 | view 56 | returns (address) 57 | { 58 | // Get a hash concatenating args passed to encodePacked 59 | bytes32 hash = keccak256( 60 | abi.encodePacked( 61 | bytes1(0xff), // 0 62 | address(this), // address of factory contract 63 | _salt, // a random salt 64 | keccak256(getBytecode()) // the wallet contract bytecode 65 | ) 66 | ); 67 | // Cast last 20 bytes of hash to address 68 | return address(uint160(uint256(hash))); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /contract/Pledge/1.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.8.13; 2 | // SPDX-License-Identifier: MIT 3 | 4 | library Address { 5 | function isContract(address account) internal view returns (bool) { 6 | bytes32 codehash; 7 | // 空字符串hash值 8 | bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 9 | //内联编译(inline assembly)语言,是用一种非常底层的方式来访问EVM 10 | assembly { codehash := extcodehash(account) } 11 | return (codehash != accountHash && codehash != 0x0); 12 | } 13 | } 14 | 15 | library SafeERC20 { 16 | using Address for address; 17 | 18 | function safeTransfer(ERC20 token, address to, uint256 value) internal { 19 | callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 20 | } 21 | 22 | function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal { 23 | callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 24 | } 25 | 26 | function safeApprove(ERC20 token, address spender, uint256 value) internal { 27 | require((value == 0) || (token.allowance(address(this), spender) == 0),"SafeERC20: approve from non-zero to non-zero allowance"); 28 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 29 | } 30 | 31 | function callOptionalReturn(ERC20 token, bytes memory data) private { 32 | require(address(token).isContract(), "SafeERC20: call to non-contract"); 33 | (bool success, bytes memory returndata) = address(token).call(data); 34 | require(success, "SafeERC20: low-level call failed"); 35 | if (returndata.length > 0) { 36 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 37 | } 38 | } 39 | } 40 | 41 | interface ERC20 { 42 | function balanceOf(address account) external view returns (uint256); 43 | function transfer(address recipient, uint256 amount) external returns (bool); 44 | function allowance(address owner, address spender) external view returns (uint256); 45 | function approve(address spender, uint256 amount) external returns (bool); 46 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 47 | event Transfer(address indexed from, address indexed to, uint256 value); 48 | event Approval(address indexed owner, address indexed spender, uint256 value); 49 | } 50 | 51 | contract Pledge { 52 | using SafeERC20 for ERC20; 53 | 54 | uint public constant SECONDS_PER_DAY = 24 * 60 * 60; 55 | 56 | address private owner; 57 | 58 | mapping(address => PledgeOrder) public _orders; 59 | 60 | //a代币合约地址 旧币 61 | ERC20 public _PledgeToken = ERC20(0xF44eA90A86C837937C45EE7A9f5eCAEf2a0Ba128); 62 | //b代币合约地址 63 | ERC20 public _newToken = ERC20(0xF44eA90A86C837937C45EE7A9f5eCAEf2a0Ba128); 64 | 65 | address public zero = 0x0000000000000000000000000000000000000001; 66 | 67 | //千分之三收益 68 | uint256 public _rewardFee = 3; 69 | //质押数量3倍进奖池 70 | uint256 public _powerFee = 3; 71 | 72 | uint256 public _minAmount = 2000 * 10 ** 18; 73 | 74 | mapping(address => address) public recommendList; 75 | 76 | 77 | //是否存在质押记录 最后一次领取时间 分销可领取余金额 奖池总额 当前奖池剩余额度 78 | struct PledgeOrder { 79 | bool isExist; 80 | uint256 lastTime; 81 | uint256 receiveAmount; 82 | uint256 totalAmount; 83 | uint256 rewardAmount; 84 | } 85 | 86 | constructor () public{ 87 | owner = msg.sender; 88 | } 89 | 90 | //质押代币 91 | //质押之前需要先调用其合约的approve方法 获取授权 92 | function pledgeToken(uint256 _amount) public{ 93 | require(_amount > _minAmount, "amount too little"); 94 | require(address(msg.sender) == address(tx.origin), "no contract"); 95 | _newToken.transferFrom(msg.sender, address(this), _amount); 96 | if(_orders[msg.sender].isExist == false){ 97 | createOrder(_amount); 98 | }else{ 99 | PledgeOrder storage order=_orders[msg.sender]; 100 | 101 | order.totalAmount = order.totalAmount + (_amount * _powerFee); 102 | order.rewardAmount = order.rewardAmount + (_amount * _powerFee); 103 | } 104 | _newToken.safeTransfer(zero, _amount); 105 | } 106 | 107 | function createOrder(uint256 trcAmount) private { 108 | _orders[msg.sender] = PledgeOrder( 109 | true, 110 | block.timestamp, 111 | 0, 112 | trcAmount, 113 | trcAmount 114 | ); 115 | } 116 | 117 | //提取收益 118 | function takeProfit() public { 119 | require(address(msg.sender) == address(tx.origin), "no contract"); 120 | PledgeOrder storage order = _orders[msg.sender]; 121 | uint256 day = (block.timestamp - order.lastTime) / SECONDS_PER_DAY; 122 | require(day > 0 || order.receiveAmount > 0, "no reward"); 123 | uint256 pledgeBalance = _PledgeToken.balanceOf(address(this)); 124 | 125 | // 奖池总量 * 收益倍率 * 天数 + 分销收益 126 | uint256 profits = order.totalAmount * _rewardFee / 1000 * day; 127 | 128 | address rec1 = recommendList[msg.sender]; 129 | if(rec1 != address(0)){ 130 | PledgeOrder storage order1 = _orders[rec1]; 131 | if(order1.isExist){ 132 | order1.receiveAmount += profits / 4; 133 | } 134 | 135 | address rec2 = recommendList[rec1]; 136 | if(rec2 != address(0)){ 137 | PledgeOrder storage order2 = _orders[rec2]; 138 | if(order2.isExist){ 139 | order2.receiveAmount += profits / 2; 140 | } 141 | } 142 | } 143 | 144 | profits += order.receiveAmount; 145 | require(pledgeBalance >= profits, "no balance"); 146 | _PledgeToken.safeTransfer(address(msg.sender), profits); 147 | //提取收益后刷新时间 148 | order.lastTime = block.timestamp; 149 | order.receiveAmount = 0; 150 | order.rewardAmount = order.rewardAmount - profits; 151 | } 152 | 153 | //查询收益 154 | function getParentProfitToken(address _target) public view returns(uint256) { 155 | require(address(msg.sender) == address(tx.origin), "no contract"); 156 | PledgeOrder memory order = _orders[_target]; 157 | uint256 day = (block.timestamp - order.lastTime) / SECONDS_PER_DAY; 158 | uint256 profits = order.totalAmount * _rewardFee / 1000 * day + order.receiveAmount; 159 | return profits; 160 | } 161 | 162 | function changeOwner(address paramOwner) public onlyOwner { 163 | owner = paramOwner; 164 | } 165 | 166 | function setRewardFee(uint256 _fee) public onlyOwner { 167 | _rewardFee = _fee; 168 | } 169 | 170 | function withdraw(address _token, address _target, uint256 _amount) public onlyOwner { 171 | require(ERC20(_token).balanceOf(address(this)) >= _amount, "no balance"); 172 | ERC20(_token).safeTransfer(_target, _amount); 173 | } 174 | 175 | 176 | modifier onlyOwner(){ 177 | require(msg.sender == owner); 178 | _; 179 | } 180 | 181 | function getOwner() public view returns (address) { 182 | return owner; 183 | } 184 | 185 | function bind(address _target) public { 186 | recommendList[msg.sender] = _target; 187 | } 188 | } --------------------------------------------------------------------------------