文件 1 的 1:Trend.sol
pragma solidity >=0.8.2 <0.9.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function decimals() external view returns (uint8);
function symbol() external view returns (string memory);
function name() external view returns (string memory);
function getOwner() external view returns (address);
function balanceOf(address _account) external view returns (uint256);
function transfer(address _recipient, uint256 _amount) external returns (bool);
function allowance(address _owner, address _spender) external view returns (uint256);
function approve(address _spender, uint256 _amount) external returns (bool);
function transferFrom(address _sender, address _recipient, uint256 _amount) external returns (bool);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
abstract contract Auth {
address internal m_Owner;
mapping(address => bool) internal m_Admins;
event OwnershipTransferred(address _owner);
constructor(address _owner) {
m_Owner = _owner;
}
modifier onlyOwner() {
require(msg.sender == m_Owner, "!Owner");
_;
}
modifier onlyAdmin() {
require(m_Admins[msg.sender] == true || msg.sender == m_Owner, "!Admin");
_;
}
function transferOwnership(address payable _addr) onlyOwner public {
m_Owner = _addr;
emit OwnershipTransferred(_addr);
}
function isAdmin(address _addr) onlyAdmin external view returns (bool) {
return m_Admins[_addr];
}
function _updateAdmin(address _addr, bool _status) internal {
require(msg.sender != _addr || msg.sender == m_Owner, "!AdminSelf");
m_Admins[_addr] = _status;
}
}
interface IDEXFactory {
function createPair(address _tokenA, address _tokenB) external returns (address _pair);
}
interface IDEXRouter {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint amountADesired,
uint amountBDesired,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB, uint liquidity);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
interface IDividendDistributor {
function setShare(address _shareholder, uint256 _amount) external;
function deposit() external payable;
function claimDividend(address _shareholder) external;
}
contract DividendDistributor is IDividendDistributor {
address private m_Token;
struct Share {
uint256 amount;
uint256 totalExcluded;
uint256 totalRealised;
}
address[] private m_Shareholders;
mapping (address => uint256) private m_ShareholderIndexes;
mapping (address => Share) public m_Shares;
uint256 public m_TotalShares;
uint256 public m_TotalDividends;
uint256 public m_TotalDistributed;
uint256 public m_DividendsPerShare;
uint256 private m_DividendsPerShareAccuracyFactor = 10 ** 36;
modifier onlyToken() {
require(msg.sender == m_Token);
_;
}
constructor () {
m_Token = msg.sender;
}
function setShare(address _shareholder, uint256 _amount) external override onlyToken {
if(m_Shares[_shareholder].amount > 0){
distributeDividend(_shareholder);
}
if(_amount > 0 && m_Shares[_shareholder].amount == 0){
addShareholder(_shareholder);
}else if(_amount == 0 && m_Shares[_shareholder].amount > 0){
removeShareholder(_shareholder);
}
m_TotalShares = m_TotalShares - m_Shares[_shareholder].amount + _amount;
m_Shares[_shareholder].amount = _amount;
m_Shares[_shareholder].totalExcluded = getCumulativeDividends(m_Shares[_shareholder].amount);
}
function deposit() external payable override onlyToken {
uint256 _amount = msg.value;
if (m_TotalShares == 0) {
return;
}
m_TotalDividends = m_TotalDividends + _amount;
m_DividendsPerShare = m_DividendsPerShare + (m_DividendsPerShareAccuracyFactor * _amount / m_TotalShares);
}
function distributeDividend(address _shareholder) internal {
if(m_Shares[_shareholder].amount == 0){ return; }
uint256 _amount = getUnrealizedEarnings(_shareholder);
if(_amount > 0){
m_TotalDistributed = m_TotalDistributed + _amount;
m_Shares[_shareholder].totalRealised = m_Shares[_shareholder].totalRealised + _amount;
m_Shares[_shareholder].totalExcluded = getCumulativeDividends(m_Shares[_shareholder].amount);
payable(_shareholder).transfer(_amount);
}
}
function claimDividend(address _shareholder) external override onlyToken {
distributeDividend(_shareholder);
}
function getUnrealizedEarnings(address _shareholder) public view returns (uint256) {
if(m_Shares[_shareholder].amount == 0) {
return 0;
}
uint256 _shareholderTotalDividends = getCumulativeDividends(m_Shares[_shareholder].amount);
uint256 _shareholderTotalExcluded = m_Shares[_shareholder].totalExcluded;
if(_shareholderTotalDividends <= _shareholderTotalExcluded) {
return 0;
}
return _shareholderTotalDividends - _shareholderTotalExcluded;
}
function getCumulativeDividends(uint256 _share) internal view returns (uint256) {
return _share * m_DividendsPerShare / m_DividendsPerShareAccuracyFactor;
}
function getRealizedEarnings(address _shareholder) external view returns (uint256) {
return m_Shares[_shareholder].totalRealised;
}
function getTotalDistributed() external view returns (uint256) {
return m_TotalDistributed;
}
function addShareholder(address _shareholder) internal {
m_ShareholderIndexes[_shareholder] = m_Shareholders.length;
m_Shareholders.push(_shareholder);
}
function removeShareholder(address _shareholder) internal {
m_Shareholders[m_ShareholderIndexes[_shareholder]] = m_Shareholders[m_Shareholders.length-1];
m_ShareholderIndexes[m_Shareholders[m_Shareholders.length-1]] = m_ShareholderIndexes[_shareholder];
m_Shareholders.pop();
}
}
contract Trend is IERC20, Auth {
address private DEAD = 0x000000000000000000000000000000000000dEaD;
address private ZERO = 0x0000000000000000000000000000000000000000;
string private constant m_Name = "TREND";
string private constant m_Symbol = "TREND";
uint8 private constant m_Decimals = 9;
uint256 private m_TotalSupply = 10500000000 * (10 ** m_Decimals);
uint256 private m_MaxBuyAmount = m_TotalSupply;
uint256 private m_MaxSellAmount = m_TotalSupply;
mapping (address => uint256) private m_Balances;
mapping (address => mapping (address => uint256)) private m_Allowances;
mapping (address => bool) private m_IsFeeExempt;
mapping (address => bool) private m_IsTxLimitExempt;
mapping (address => bool) private m_IsDividendExempt;
mapping (address => bool) private m_IsBot;
mapping (address => bool) private m_Pairs;
uint256 private m_TransferOutLimitPeriod = 30 * 24 * 60 * 60;
uint256 private m_TransferOutLimit = 5000000 * (10 ** m_Decimals);
mapping (address => uint256) private m_TransferOutLimitExpiration;
mapping (address => uint256) private m_TransferOutAmount;
bool m_FeeLock;
uint256 private m_HolderFee = 2;
uint256 private m_TeamFee = 4;
uint256 private m_TotalFee = 6;
uint256 private m_FeeDenominator = 100;
address private m_TeamReceiver;
IDEXRouter private m_Router;
address public router;
address public initialPair;
uint256 public launchedAt;
address public WETH;
DividendDistributor private m_Distributor;
bool public swapEnabled = true;
uint256 public swapThreshold = 1000000 * (10 ** m_Decimals);
bool private m_InSwap;
modifier swapping() {
m_InSwap = true;
_;
m_InSwap = false;
}
constructor (
address _owner,
address _teamWallet,
address _airdropWallet,
address _router
) Auth(_owner) {
m_IsDividendExempt[address(this)] = true;
m_IsDividendExempt[DEAD] = true;
m_IsTxLimitExempt[DEAD] = true;
m_IsDividendExempt[ZERO] = true;
m_IsTxLimitExempt[ZERO] = true;
m_Admins[_owner] = true;
setAdminStatus(_owner, true);
setAdminStatus(_teamWallet, true);
setAdminStatus(_airdropWallet, true);
m_TeamReceiver = _teamWallet;
router = _router;
_initRouter();
m_Distributor = new DividendDistributor();
m_Balances[_airdropWallet] = m_TotalSupply;
emit Transfer(address(0), _airdropWallet, m_TotalSupply);
}
receive() external payable { }
function totalSupply() external view override returns (uint256) { return m_TotalSupply; }
function decimals() external pure override returns (uint8) { return m_Decimals; }
function symbol() external pure override returns (string memory) { return m_Symbol; }
function name() external pure override returns (string memory) { return m_Name; }
function getOwner() external view override returns (address) { return m_Owner; }
function balanceOf(address _account) public view override returns (uint256) { return m_Balances[_account]; }
function allowance(address _holder, address _spender) external view override returns (uint256) { return m_Allowances[_holder][_spender]; }
function approve(address _spender, uint256 _amount) public override returns (bool) {
m_Allowances[msg.sender][_spender] = _amount;
emit Approval(msg.sender, _spender, _amount);
return true;
}
function approveMax(address _spender) external returns (bool) {
return approve(_spender, type(uint256).max);
}
function transfer(address _recipient, uint256 amount) external override returns (bool) {
return _transferFrom(msg.sender, _recipient, amount);
}
function transferFrom(address _sender, address _recipient, uint256 _amount) external override returns (bool) {
if(m_Allowances[_sender][msg.sender] != type(uint256).max){
m_Allowances[_sender][msg.sender] = m_Allowances[_sender][msg.sender] - _amount;
}
return _transferFrom(_sender, _recipient, _amount);
}
function _transferFrom(address _sender, address _recipient, uint256 _amount) internal returns (bool) {
if(m_InSwap) {
return _basicTransfer(_sender, _recipient, _amount);
}
_checkTxLimit(_sender, _recipient, _amount);
_checkTransferOutLimit(_sender, _amount);
if(_shouldEmitFees()) {
_emitFees();
}
if(!_isLaunched() && _isPair(_recipient)) {
require(m_Balances[_sender] > 0);
_launch();
}
m_Balances[_sender] = m_Balances[_sender] - _amount;
uint256 _amountReceived = _shouldTakeFee(_sender, _recipient) ? _takeFee(_sender, _recipient, _amount) : _amount;
m_Balances[_recipient] = m_Balances[_recipient] + _amountReceived;
if(!_isPair(_sender) && !m_IsDividendExempt[_sender]) {
try m_Distributor.setShare(_sender, m_Balances[_sender]) {
} catch {}
}
if(!_isPair(_recipient) && !m_IsDividendExempt[_recipient]) {
try m_Distributor.setShare(_recipient, m_Balances[_recipient]) {
} catch {}
}
emit Transfer(_sender, _recipient, _amountReceived);
return true;
}
function _basicTransfer(address _sender, address _recipient, uint256 _amount) internal returns (bool) {
m_Balances[_sender] = m_Balances[_sender] - _amount;
m_Balances[_recipient] = m_Balances[_recipient] + _amount;
emit Transfer(_sender, _recipient, _amount);
return true;
}
function _checkTxLimit(address _sender, address _recipient, uint256 _amount) internal view {
_isPair(_sender) ?
require(_amount <= m_MaxBuyAmount || m_IsTxLimitExempt[_recipient], "Buy Limit Exceeded") :
require(_amount <= m_MaxSellAmount || m_IsTxLimitExempt[_sender], "Sell Limit Exceeded");
}
function _checkTransferOutLimit(address _sender, uint256 _amount) internal {
if (!_isLaunched()) return;
if (_sender == address(this)) return;
if (_isPair(_sender)) return;
if (m_IsTxLimitExempt[_sender]) return;
if (m_Admins[_sender]) return;
if (block.timestamp > m_TransferOutLimitExpiration[_sender]) {
m_TransferOutLimitExpiration[_sender] = block.timestamp + m_TransferOutLimitPeriod;
m_TransferOutAmount[_sender] = _amount;
} else {
m_TransferOutAmount[_sender] += _amount;
}
require(m_TransferOutAmount[_sender] <= m_TransferOutLimit, "TRANSFER_OUT_LIMIT_EXCEEDED_FOR_PERIOD");
}
function getTransferOutStatusForSender(address _sender)
onlyAdmin
external
view
returns (
uint256 _transferOutAmount,
uint256 _transferOutExpiration,
uint256 _transferOutLimit,
uint256 _blockTime
)
{
return (
m_TransferOutAmount[_sender],
m_TransferOutLimitExpiration[_sender],
m_TransferOutLimit,
block.timestamp
);
}
function getTransferOutStatus()
external
view
returns (
uint256 _transferOutAmount,
uint256 _transferOutExpiration,
uint256 _transferOutLimit,
uint256 _blockTime
)
{
return (
m_TransferOutAmount[msg.sender],
m_TransferOutLimitExpiration[msg.sender],
m_TransferOutLimit,
block.timestamp
);
}
function isTransferOutLimited(address _sender) onlyAdmin external view returns (bool) {
return m_TransferOutAmount[_sender] > m_TransferOutLimit;
}
function liftTransferOutLimit(address _sender) onlyAdmin external {
m_TransferOutAmount[_sender] = 0;
m_TransferOutLimitExpiration[_sender] = block.timestamp + m_TransferOutLimitPeriod;
}
function setTransferOutLimits(uint256 _amount, uint256 _period) external onlyAdmin {
m_TransferOutLimit = _amount;
m_TransferOutLimitPeriod = _period;
}
function transferOutLimitPeriod() external view returns (uint256) {
return m_TransferOutLimitPeriod;
}
function transferOutLimit() external view returns (uint256) {
return m_TransferOutLimit;
}
function _shouldTakeFee(address _sender, address _recipient) internal view returns (bool) {
return !(m_IsFeeExempt[_sender] || m_IsFeeExempt[_recipient]) && !m_FeeLock;
}
function _takeFee(address _sender, address _recipient, uint256 _amount) internal returns (uint256) {
uint256 _feeAmount;
bool _bot;
if (!_isPair(_sender)) {
_bot = m_IsBot[_sender];
} else {
_bot = m_IsBot[_recipient];
}
if (_bot) {
_feeAmount = _amount * (m_FeeDenominator - 1) / m_FeeDenominator;
m_Balances[DEAD] = m_Balances[DEAD] + _feeAmount;
emit Transfer(_sender, DEAD, _feeAmount);
}
else {
_feeAmount = _isTransfer(_sender, _recipient) ? 0 : _amount * m_TotalFee / m_FeeDenominator;
m_Balances[address(this)] = m_Balances[address(this)] + _feeAmount;
emit Transfer(_sender, address(this), _feeAmount);
}
return _amount - _feeAmount;
}
function _shouldEmitFees() internal view returns (bool) {
return
!_isPair(msg.sender)
&& !m_InSwap
&& swapEnabled
&& m_Balances[address(this)] >= swapThreshold
&& !m_FeeLock;
}
function _emitFees() internal swapping {
address[] memory _path = new address[](2);
_path[0] = address(this);
_path[1] = WETH;
uint256 _balanceBefore = address(this).balance;
m_FeeLock = true;
m_Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
swapThreshold,
0,
_path,
address(this),
block.timestamp
);
m_FeeLock = false;
uint256 _amountETH = address(this).balance - _balanceBefore;
uint256 _amountReflection = _amountETH * m_HolderFee / m_TotalFee;
uint256 _amountTeam = _amountETH - _amountReflection;
try m_Distributor.deposit{value: _amountReflection}() {
} catch {}
payable(m_TeamReceiver).transfer(_amountTeam);
}
function _isLaunched() internal view returns (bool) {
return launchedAt != 0;
}
function _launch() internal {
launchedAt = block.number;
}
function _isPair(address _addr) internal view returns (bool) {
return m_Pairs[_addr];
}
function _isTransfer(address _sender, address _recipient) internal view returns (bool) {
return !_isPair(_sender) && !_isPair(_recipient);
}
function setPair(address _pair, bool _status) onlyAdmin public {
m_Pairs[_pair] = _status;
m_IsDividendExempt[_pair] = _status;
m_IsTxLimitExempt[_pair] = _status;
}
function setBuyTxLimit(uint256 _amount) external onlyAdmin {
m_MaxBuyAmount = _amount;
}
function setSellTxLimit(uint256 _amount) external onlyAdmin {
m_MaxSellAmount = _amount;
}
function setBot(address _address, bool _toggle) external onlyAdmin {
m_IsBot[_address] = _toggle;
_setIsDividendExempt(_address, _toggle);
}
function isBot(address _address) external view onlyAdmin returns (bool) {
return m_IsBot[_address];
}
function _setIsDividendExempt(address _holder, bool _exempt) internal {
require(_holder != address(this) && !_isPair(_holder));
m_IsDividendExempt[_holder] = _exempt;
if(_exempt){
m_Distributor.setShare(_holder, 0);
}else{
m_Distributor.setShare(_holder, m_Balances[_holder]);
}
}
function setIsDividendExempt(address _holder, bool _exempt) external onlyAdmin {
_setIsDividendExempt(_holder, _exempt);
}
function setIsFeeExempt(address _holder, bool _exempt) external onlyAdmin {
m_IsFeeExempt[_holder] = _exempt;
}
function setIsTxLimitExempt(address _holder, bool _exempt) external onlyAdmin {
m_IsTxLimitExempt[_holder] = _exempt;
}
function setFees(uint256 _holderFee, uint256 _teamFee, uint256 _feeDenominator) external onlyAdmin {
m_HolderFee = _holderFee;
m_TeamFee = _teamFee;
m_TotalFee = _holderFee + _teamFee;
m_FeeDenominator = _feeDenominator;
require(m_TotalFee < m_FeeDenominator/2);
}
function setFeeReceiver(address _teamReceiver) external onlyAdmin {
m_TeamReceiver = _teamReceiver;
}
function manualSend() external onlyAdmin {
uint256 _contractETHBalance = address(this).balance;
payable(m_TeamReceiver).transfer(_contractETHBalance);
}
function setFeeEmitSettings(bool _enabled, uint256 _emissionThresholdAmount) external onlyAdmin {
swapEnabled = _enabled;
swapThreshold = _emissionThresholdAmount;
}
function claimDividend() external {
m_Distributor.claimDividend(msg.sender);
}
function claimDividendForHolder(address _holder) external onlyAdmin {
m_Distributor.claimDividend(_holder);
}
function getUnpaidEarnings(address _shareholder) public view returns (uint256) {
return m_Distributor.getUnrealizedEarnings(_shareholder);
}
function getPaidEarnings(address _shareholder) public view returns (uint256) {
return m_Distributor.getRealizedEarnings(_shareholder);
}
function getTotalPaidEarnings() public view returns (uint256) {
return m_Distributor.getTotalDistributed();
}
function manualBurn(uint256 _amount) external onlyAdmin returns (bool) {
return _basicTransfer(address(this), DEAD, _amount);
}
function getCirculatingSupply() public view returns (uint256) {
return m_TotalSupply - balanceOf(DEAD) - balanceOf(ZERO);
}
function setTeamReceiver(address _addr) external onlyAdmin {
m_TeamReceiver = _addr;
}
function isLaunched() external view returns (bool) {
return launchedAt != 0;
}
function _initRouter() internal {
m_Router = IDEXRouter(router);
WETH = m_Router.WETH();
initialPair = IDEXFactory(m_Router.factory()).createPair(WETH, address(this));
setPair(initialPair, true);
m_Allowances[address(this)][router] = type(uint256).max;
}
function addLiquidityOnce() external payable onlyAdmin {
require(!_isLaunched(), "ALREADY_LAUNCHED");
require(balanceOf(address(this)) > 0, "LIQUIDITY_BALANCE_MISSING");
m_FeeLock = true;
try m_Router.addLiquidityETH{value: msg.value}(
address(this),
balanceOf(address(this)),
balanceOf(address(this)),
msg.value,
msg.sender,
block.timestamp + 60*10
) {
} catch {
revert("addLiquidityOnce failed");
}
m_FeeLock = false;
}
function panic() onlyAdmin external {
payable(msg.sender).transfer(address(this).balance);
}
function distributor() onlyAdmin external view returns (address) {
return address(m_Distributor);
}
function setAdminStatus(address _admin, bool _status) onlyAdmin public {
_updateAdmin(_admin, _status);
m_IsDividendExempt[_admin] = _status;
m_IsFeeExempt[_admin] = _status;
m_IsTxLimitExempt[_admin] = _status;
}
}