💡 本文由领先的区块链技术服务商 Crypto8848 技术团队出品。我们专注于 DeFi、DApp、算法 Token 等 Web3 核心技术开发,提供全方位的区块链解决方案。Telegram:@recoverybtc
SafeMoon是一个创新的DeFi代币项目,于2021年3月8日在币安智能链(BSC)上线。在2021年牛市期间,SafeMoon创造了惊人的市场表现:
- 在2021年3月12日至4月20日期间,价格飙升超过55,000%
- 市值一度达到57亿美元
- 曾超越「狗狗币」(Dogecoin)成为搜索量最大的加密货币
- 后因流动性池锁定问题导致价格暴跌近50%
SafeMoon最大的创新在于其独特的代币经济学模型和分红机制,这也引发了市场上大量的模仿项目。其核心特点包括:
- 惩罚交易、奖励持有:合约会对交易行为收取费用,并将部分费用分配给持币者
- 自动流动性添加:交易税的一部分会自动注入流动性池
- 被动收益:用户只需持有代币,无需任何操作即可获得分红收益
通过这种创新的代币经济学模型,SafeMoon实现了以下核心特性:
-
反射机制(Reflection)
- 持有者可以通过持有获得被动收益
- 交易费用的一部分会按比例分配给所有持有者
- 长期持有者获得更多收益
-
自动流动性生成(Auto LP)
- 每笔交易自动向流动性池注入资金
- 提高代币价格稳定性
- 降低大额交易的价格影响
-
多级费用系统
- 交易费用分配给反射、流动性池和项目发展基金
- 动态调节的费率机制
- 防止投机和倾销
SafeMoon Token Contract
├── 代币基础功能 (ERC20/BEP20)
├── 反射机制模块
├── 自动流动性模块
└── 费用处理模块
- SafeMathUpgradeable:安全数学运算
- AddressUpgradeable:地址相关操作
- IERC20:代币标准接口
- IPancakeRouter02:DEX路由接口
- IPancakePair:交易对接口
- 代币信息(名称、符号、总供应量)
- 费率配置
- 排除名单(不参与反射/费用)
- 流动性池地址
- 路由合约地址
struct ReflectionValues {
uint256 rAmount; // 反射数量
uint256 rTransferAmount; // 实际转账数量
uint256 rFee; // 反射费用
uint256 tTransferAmount; // 代币转账数量
uint256 tFee; // 代币费用
uint256 tLiquidity; // 流动性数量
}- 收集交易费用
- 将BNB和代币添加到流动性池
- 锁定LP代币
- 计算各类费用
- 分配反射收益
- 处理流动性注入
反射机制基于以下公式:
反射率 = 总反射数量 / 代币总供应量
即: Rrate = totalReflections / totalSupply
参数说明:
- Rrate: 反射率 - 决定每个持有者能获得的反射收益比例
- totalReflections: 总反射数量 - 所有交易产生的反射总量
- totalSupply: 代币总供应量 - 当前流通的代币总量
这个公式表示:
- 每个代币持有者获得的反射比例取决于其持有的代币数量
- 反射率是动态的,会随着交易而变化
- 总反射量会随着每笔交易的费用而增加
- 跟踪总反射量
- 计算每个地址的反射份额
- 动态更新反射率
- 收集交易费用
- 累积到阈值
- 自动添加流动性
- 锁定LP代币
// 添加流动性的核心逻辑
function swapAndLiquify(uint256 contractTokenBalance) private {
// 将一半代币换成BNB
uint256 half = contractTokenBalance.div(2);
uint256 otherHalf = contractTokenBalance.sub(half);
// 添加流动性
// ...
}- 反射费用:奖励持有者
- 流动性费用:增加流动性
- 营销费用:项目发展
- 基于交易量调整费率
- 特殊地址豁免机制
- 紧急调整功能
- 所有者权限限制
- 多重签名机制
- 时间锁定
- 重入攻击防护
- 整数溢出保护
- 地址验证
- 交易暂停
- 费率调整
- 黑名单管理
- 批量操作合并
- 存储优化
- 循环优化
- 缓存中间结果
- 避免重复计算
- 使用位运算
- 配置参数
- 依赖检查
- 网络选择
- 部署主合约
- 初始化参数
- 配置路由
- 添加初始流动性
- 功能测试
- 安全审计
- 性能测试
- 基础功能测试
- 反射机制测试
- 流动性测试
- 交易流程测试
- 费用系统测试
- 紧急功能测试
- 大额交易测试
- 高频交易测试
- 极限条件测试
contract Safemoon is ISafemoon, Initializable, ContextUpgradeable, OwnableUpgradeable {
// 使用安全数学库
using SafeMathUpgradeable for uint256;
using AddressUpgradeable for address;
// 费用等级结构体
struct FeeTier {
uint256 ecoSystemFee; // 生态系统费用
uint256 liquidityFee; // 流动性费用
uint256 taxFee; // 税费
uint256 ownerFee; // 所有者费用
uint256 burnFee; // 销毁费用
address ecoSystem; // 生态系统地址
address owner; // 所有者地址
}
// 反射值结构体
struct FeeValues {
uint256 rAmount; // 反射总量
uint256 rTransferAmount; // 反射转账量
uint256 rFee; // 反射费用
uint256 tTransferAmount;// 代币转账量
uint256 tEchoSystem; // 生态系统费用
uint256 tLiquidity; // 流动性费用
uint256 tFee; // 税费
uint256 tOwner; // 所有者费用
uint256 tBurn; // 销毁费用
}
} // 反射值映射
mapping(address => uint256) private _rOwned;
// 代币余额映射
mapping(address => uint256) private _tOwned;
// 授权映射
mapping(address => mapping(address => uint256)) private _allowances;
// 免费用地址映射
mapping(address => bool) private _isExcludedFromFee;
// 排除地址映射
mapping(address => bool) private _isExcluded;
// 黑名单地址映射
mapping(address => bool) private _isBlacklisted;
// 地址费用等级映射
mapping(address => uint256) private _accountsTier;
// 常量和配置
uint256 private constant MAX = ~uint256(0);
uint256 private _tTotal; // 代币总供应量
uint256 private _rTotal; // 反射值总量
uint256 private _maxFee; // 最大费用
uint256 public _maxTxAmount; // 最大交易量 function __Safemoon_v2_init_unchained() internal initializer {
// 设置代币基本信息
_name = "SafeMoon";
_symbol = "SFM";
_decimals = 9;
// 初始化总供应量和反射值
_tTotal = 1000000 * 10**6 * 10**9;
_rTotal = (MAX - (MAX % _tTotal));
_maxFee = 1000;
// 设置交易限制
_maxTxAmount = 5000 * 10**6 * 10**9;
numTokensSellToAddToLiquidity = 500 * 10**6 * 10**9;
// 设置基础地址
_burnAddress = 0x000000000000000000000000000000000000dEaD;
_initializerAccount = _msgSender();
_rOwned[_initializerAccount] = _rTotal;
// 初始化费用豁免
_isExcludedFromFee[owner()] = true;
_isExcludedFromFee[address(this)] = true;
// 初始化费用等级
__Safemoon_tiers_init();
emit Transfer(address(0), _msgSender(), _tTotal);
} function _transfer(
address sender,
address recipient,
uint256 amount
) private {
// 基本检查
require(sender != address(0), "转账发送方不能为零地址");
require(recipient != address(0), "转账接收方不能为零地址");
require(amount > 0, "转账金额必须大于零");
// 交易限额检查
if (sender != owner() && recipient != owner())
require(amount <= _maxTxAmount, "转账金额超过最大限制");
// 自动流动性处理
bool overMinTokenBalance = balanceOf(address(this)) >= numTokensSellToAddToLiquidity;
if (
overMinTokenBalance &&
!inSwapAndLiquify &&
sender != uniswapV2Pair &&
swapAndLiquifyEnabled
) {
swapAndLiquify(numTokensSellToAddToLiquidity);
}
// 转账处理
bool takeFee = true;
if (_isExcludedFromFee[sender] || _isExcludedFromFee[recipient]) {
takeFee = false;
}
_tokenTransfer(sender, recipient, amount, _accountsTier[sender], takeFee);
} function _getCurrentSupply() private view returns (uint256, uint256) {
// 检查总量限制
if (_rTotalExcluded > _rTotal || _tTotalExcluded > _tTotal) {
return (_rTotal, _tTotal);
}
// 计算当前供应量
uint256 rSupply = _rTotal.sub(_rTotalExcluded);
uint256 tSupply = _tTotal.sub(_tTotalExcluded);
// 验证反射率
if (rSupply < _rTotal.div(_tTotal)) return (_rTotal, _tTotal);
return (rSupply, tSupply);
}
function _getRate() private view returns (uint256) {
(uint256 rSupply, uint256 tSupply) = _getCurrentSupply();
return rSupply.div(tSupply);
} function swapAndLiquify(uint256 contractTokenBalance) private lockTheSwap {
// 将代币分成两半
uint256 half = contractTokenBalance.div(2);
uint256 otherHalf = contractTokenBalance.sub(half);
// 获取当前合约BNB余额
uint256 initialBalance = address(this).balance;
// 将一半代币换成BNB
swapTokensForBnb(half);
// 获取实际获得的BNB数量
uint256 newBalance = address(this).balance.sub(initialBalance);
// 添加流动性
addLiquidity(otherHalf, newBalance);
} modifier onlyOwner() {
require(owner() == _msgSender(), "调用者不是所有者");
_;
}
modifier lockTheSwap() {
inSwapAndLiquify = true;
_;
inSwapAndLiquify = false;
} function blacklistAddress(address account) public onlyOwner {
require(!_isBlacklisted[account], "地址已在黑名单中");
_isBlacklisted[account] = true;
}
function unBlacklistAddress(address account) public onlyOwner {
require(_isBlacklisted[account], "地址不在黑名单中");
_isBlacklisted[account] = false;
} function calculateFee(uint256 _amount, uint256 _fee) private pure returns (uint256) {
if (_fee == 0) return 0;
return _amount.mul(_fee).div(10**4);
}
function removeAllFee() private {
_previousFees = feeTiers[0];
feeTiers[0] = _emptyFees;
}
function restoreAllFee() private {
feeTiers[0] = _previousFees;
} modifier lockUpgrade() {
require(!_upgraded, "合约已升级");
_;
_upgraded = true;
}
function migrate(address account, uint256 amount) external override {
require(migration != address(0), "迁移尚未开始");
require(_msgSender() == migration, "无权限执行迁移");
_migrate(account, amount);
}以上是 Safemoon 智能合约的核心代码实现和详细注释。该合约通过创新的代币经济学模型,实现了反射机制、自动流动性生成、多级费用系统等特性,为持有者提供了被动收益和价格稳定性保障。同时,合约还包含了完善的安全机制和升级功能,确保了代币的安全性和可持续发展。
/**
* @title Safemoon V2 智能合约
* @dev 实现了创新的DeFi代币经济学模型,包括:
* 1. 反射机制 - 持有者可以获得交易费用的分红
* 2. 自动流动性生成 - 每笔交易自动向流动性池注入资金
* 3. 多级费用系统 - 支持不同等级的交易费用配置
* 4. 自动销毁 - 部分交易费用会被自动销毁
* @author Safemoon Team
*/
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.11;
/**
* @dev SafeMathUpgradeable 库
* 提供安全的数学运算功能,防止溢出
* 所有的数学运算都会进行溢出检查
*/
library SafeMathUpgradeable {
/**
* @dev 尝试两个无符号整数相加,并返回溢出标志
* @param a 第一个操作数
* @param b 第二个操作数
* @return bool 是否成功(无溢出)
* @return uint256 相加结果
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0); // 溢出检查
return (true, c);
}
/**
* @dev 尝试两个无符号整数相减,并返回溢出标志
* @param a 被减数
* @param b 减数
* @return bool 是否成功(无溢出)
* @return uint256 相减结果
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0); // 溢出检查
return (true, a - b);
}
/**
* @dev 尝试两个无符号整数相乘,并返回溢出标志
* @param a 第一个操作数
* @param b 第二个操作数
* @return bool 是否成功(无溢出)
* @return uint256 相乘结果
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
// Gas优化: 这比要求'a'不为零更便宜,但如果'b'也被测试,这个好处就会失去
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0); // 溢出检查
return (true, c);
}
/**
* @dev 尝试两个无符号整数相除,并返回除零标志
* @param a 被除数
* @param b 除数
* @return bool 是否成功(非零除数)
* @return uint256 相除结果
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0); // 除零检查
return (true, a / b);
}
/**
* @dev 尝试计算两个无符号整数的模,并返回除零标志
* @param a 被除数
* @param b 除数
* @return bool 是否成功(非零除数)
* @return uint256 取模结果
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0); // 除零检查
return (true, a % b);
}
/**
* @dev 返回两个无符号整数的和,溢出时回退
* @param a 第一个操作数
* @param b 第二个操作数
* @return uint256 相加结果
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: 加法溢出");
return c;
}
/**
* @dev 返回两个无符号整数的差,溢出时回退
* @param a 被减数
* @param b 减数
* @return uint256 相减结果
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: 减法溢出");
return a - b;
}
/**
* @dev 返回两个无符号整数的积,溢出时回退
* @param a 第一个操作数
* @param b 第二个操作数
* @return uint256 相乘结果
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: 乘法溢出");
return c;
}
/**
* @dev 返回两个无符号整数的商,除数为零时回退
* @param a 被除数
* @param b 除数
* @return uint256 相除结果
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: 除数为零");
return a / b;
}
/**
* @dev 返回两个无符号整数相除的余数,除数为零时回退
* @param a 被除数
* @param b 除数
* @return uint256 取模结果
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: 模运算除数为零");
return a % b;
}
/**
* @dev 返回两个无符号整数的差,溢出时使用自定义错误消息回退
* @param a 被减数
* @param b 减数
* @param errorMessage 错误消息
* @return uint256 相减结果
* @notice 此函数已弃用,因为它需要为错误消息不必要地分配内存
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
/**
* @dev 返回两个无符号整数的商,除数为零时使用自定义错误消息回退
* @param a 被除数
* @param b 除数
* @param errorMessage 错误消息
* @return uint256 相除结果
* @notice 此函数已弃用,因为它需要为错误消息不必要地分配内存
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
/**
* @dev 返回两个无符号整数相除的余数,除数为零时使用自定义错误消息回退
* @param a 被除数
* @param b 除数
* @param errorMessage 错误消息
* @return uint256 取模结果
* @notice 此函数已弃用,因为它需要为错误消息不必要地分配内存
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
/**
* @dev AddressUpgradeable 库
* 提供地址相关的工具函数
*/
library AddressUpgradeable {
/**
* @dev 检查地址是否是合约
* @param account 要检查的地址
* @return bool 是否是合约地址
* @notice 此函数可能返回false的情况:
* 1. 外部账户(EOA)
* 2. 正在构建中的合约
* 3. 将要创建合约的地址
* 4. 曾经存在但已被销毁的合约地址
*/
function isContract(address account) internal view returns (bool) {
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev 发送ETH到指定地址,转发所有可用gas并在错误时回退
* @param recipient 接收地址
* @param amount 发送数量
* @notice 这是Solidity transfer函数的替代品
* 1. 移除了2300 gas的限制
* 2. 防止重入攻击
* 3. 使用checks-effects-interactions模式
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: 余额不足");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: 无法发送数值,接收方可能已回退");
}
/**
* @dev 使用低级call执行Solidity函数调用
* @param target 目标合约地址
* @param data 调用数据
* @return bytes 返回数据
* @notice 这是安全的函数调用替代品,会传播目标的revert原因
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: 低级调用失败");
}
/**
* @dev 同functionCall,但可以自定义错误消息
* @param target 目标合约地址
* @param data 调用数据
* @param errorMessage 错误消息
* @return bytes 返回数据
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev 同functionCall,但同时转账ETH
* @param target 目标合约地址
* @param data 调用数据
* @param value 转账数量
* @return bytes 返回数据
* @notice 要求:
* 1. 调用合约必须有足够的ETH余额
* 2. 被调用的函数必须是payable
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: 带value的低级调用失败");
}
/**
* @dev 同functionCallWithValue,但可以自定义错误消息
* @param target 目标合约地址
* @param data 调用数据
* @param value 转账数量
* @param errorMessage 错误消息
* @return bytes 返回数据
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: 余额不足");
require(isContract(target), "Address: 调用到非合约地址");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev 同functionCall,但执行staticcall
* @param target 目标合约地址
* @param data 调用数据
* @return bytes 返回数据
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: 低级static调用失败");
}
/**
* @dev 同functionStaticCall,但可以自定义错误消息
* @param target 目标合约地址
* @param data 调用数据
* @param errorMessage 错误消息
* @return bytes 返回数据
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: 对非合约地址进行static调用");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev 验证调用结果
* @param success 是否成功
* @param returndata 返回数据
* @param errorMessage 错误消息
* @return bytes 返回数据
* @notice 如果调用失败,会尝试提取revert原因
*/
function _verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) private pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// 查找revert原因并向上传播
if (returndata.length > 0) {
// 最简单的方法是通过assembly传播revert原因
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
/**
* @dev 可初始化合约的基类
* 提供初始化机制,替代构造函数
* 用于可升级合约
*/
abstract contract Initializable {
/**
* @dev 指示合约是否已经初始化
*/
bool private _initialized;
/**
* @dev 指示合约是否正在初始化
*/
bool private _initializing;
/**
* @dev 修饰符:保护初始化函数不被多次调用
*/
modifier initializer() {
require(_initializing || _isConstructor() || !_initialized, "Initializable: 合约已经初始化");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
/**
* @dev 返回函数是否在构造函数中运行
* @return bool 是否在构造函数中
*/
function _isConstructor() private view returns (bool) {
return !AddressUpgradeable.isContract(address(this));
}
}
/**
* @dev 上下文合约
* 提供有关当前执行上下文的信息
* 包括交易发送者和数据
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {}
/**
* @dev 获取消息发送者
* @return address payable 发送者地址
*/
function _msgSender() internal view virtual returns (address payable) {
return payable(msg.sender);
}
/**
* @dev 获取消息数据
* @return bytes 消息数据
*/
function _msgData() internal view virtual returns (bytes memory) {
this; // 消除状态可变性警告
return msg.data;
}
uint256[50] private __gap;
}
/**
* @dev 所有权合约
* 实现基本的访问控制机制
* 只有合约所有者可以执行某些操作
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev 初始化合约,设置部署者为初始所有者
*/
function __Ownable_init() internal initializer {
__Context_init_unchained();
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal initializer {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev 返回当前所有者地址
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev 修饰符:只允许所有者执行
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: 调用者不是所有者");
_;
}
/**
* @dev 放弃合约所有权
* 将使合约没有所有者
* 只能由当前所有者调用
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev 转移合约所有权
* @param newOwner 新的所有者地址
* 只能由当前所有者调用
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: 新所有者是零地址");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[49] private __gap;
}
/**
* @dev Safemoon代币接口
* 定义了代币必须实现的基本功能
*/
interface ISafemoon {
/**
* @dev 返回代币总供应量
*/
function totalSupply() external view returns (uint256);
/**
* @dev 返回账户持有的代币数量
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev 转移代币
* @param recipient 接收者地址
* @param amount 转移数量
* @return bool 是否成功
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev 返回授权额度
* @param owner 持有者地址
* @param spender 被授权者地址
* @return uint256 授权数量
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev 授权代币
* @param spender 被授权者地址
* @param amount 授权数量
* @return bool 是否成功
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev 通过授权转移代币
* @param sender 发送者地址
* @param recipient 接收者地址
* @param amount 转移数量
* @return bool 是否成功
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev 铸造代币
* @param account 接收者地址
* @param amount 铸造数量
*/
function migrate(address account, uint256 amount) external;
/**
* @dev 检查是否开始迁移
* @return bool 是否开始迁移
*/
function isMigrationStarted() external view returns (bool);
/**
* @dev 转账事件
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev 授权事件
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
/**
* @dev Uniswap V2工厂合约接口
* 用于创建交易对
*/
interface IUniswapV2Factory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint256);
/**
* @dev 创建交易对
* @param tokenA 代币A地址
* @param tokenB 代币B地址
* @param to 接收LP代币的地址
* @return pair 创建的交易对地址
*/
function createPair(
address tokenA,
address tokenB,
address to
) external returns (address pair);
}
/**
* @dev Uniswap V2路由01合约接口
* 提供基本的交易和流动性功能
*/
interface IUniswapV2Router01 {
/**
* @dev 返回工厂合约地址
*/
function factory() external pure returns (address);
/**
* @dev 返回交易路由地址
*/
function routerTrade() external pure returns (address);
/**
* @dev 返回WETH合约地址
*/
function WETH() external pure returns (address);
/**
* @dev 添加ETH流动性
* @param token 代币地址
* @param amountTokenDesired 期望添加的代币数量
* @param amountTokenMin 最小代币数量
* @param amountETHMin 最小ETH数量
* @param to 接收LP代币的地址
* @param deadline 截止时间
*/
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
returns (
uint256 amountToken,
uint256 amountETH,
uint256 liquidity
);
}
/**
* @dev Uniswap V2路由02合约接口
* 继承自路由01,提供更多高级功能
*/
interface IUniswapV2Router02 is IUniswapV2Router01 {}
/**
* @dev SafeSwap交易路由接口
* 提供安全的代币交换功能
*/
interface ISafeSwapTradeRouter {
/**
* @dev 交易结构体
* @param amountIn 输入数量
* @param amountOut 输出数量
* @param path 交易路径
* @param to 接收地址
* @param deadline 截止时间
*/
struct Trade {
uint256 amountIn;
uint256 amountOut;
address[] path;
address payable to;
uint256 deadline;
}
/**
* @dev 设置路由器地址
*/
function setRouter(address _router) external;
/**
* @dev 设置费用百分比
*/
function setFeePercent(uint256 _feePercent) external;
/**
* @dev 设置百分比
*/
function sePercent(uint256 _percent) external;
/**
* @dev 添加费用白名单
*/
function addFfsWhitelist(address _wl) external;
/**
* @dev 移除费用白名单
*/
function removeFfsWhitelist(address _wl) external;
/**
* @dev 设置费用接收地址
*/
function setFeeJar(address _feeJar) external;
/**
* @dev 使用精确代币数量换取ETH
*/
function swapExactTokensForETHAndFeeAmount(Trade calldata trade) external payable;
/**
* @dev 使用代币换取精确ETH数量
*/
function swapTokensForExactETHAndFeeAmount(Trade calldata trade) external payable;
/**
* @dev 使用精确ETH数量换取代币
*/
function swapExactETHForTokensWithFeeAmount(Trade calldata trade, uint256 _feeAmount) external payable;
/**
* @dev 使用ETH换取精确代币数量
*/
function swapETHForExactTokensWithFeeAmount(Trade calldata trade, uint256 _feeAmount) external payable;
/**
* @dev 使用精确代币数量换取代币
*/
function swapExactTokensForTokensWithFeeAmount(Trade calldata trade) external payable;
/**
* @dev 使用代币换取精确代币数量
*/
function swapTokensForExactTokensWithFeeAmount(Trade calldata trade) external payable;
/**
* @dev 获取交换费用
*/
function getSwapFee(
uint256 amountIn,
uint256 _amountOut,
address tokenA,
address tokenB
) external view returns (uint256 _fee);
/**
* @dev 获取费用明细
*/
function getFees(
address[] memory _path,
uint256 _amountIn,
address _address
)
external
view
returns (
uint256 totalBNBFee,
uint256 dexFee,
uint256 tokenAFee,
uint256 tokenBFee
);
/**
* @dev 获取交换总费用
*/
function getSwapFees(uint256 amountIn, address[] memory path) external view returns (uint256 _fees);
}
/**
* @title Safemoon代币合约
* @dev 实现了创新的DeFi代币经济学模型
*/
contract Safemoon is ISafemoon, Initializable, ContextUpgradeable, OwnableUpgradeable {
using SafeMathUpgradeable for uint256;
using AddressUpgradeable for address;
/**
* @dev 费用等级结构体
* @param ecoSystemFee 生态系统费用
* @param liquidityFee 流动性费用
* @param taxFee 税费
* @param ownerFee 所有者费用
* @param burnFee 销毁费用
* @param ecoSystem 生态系统地址
* @param owner 所有者地址
*/
struct FeeTier {
uint256 ecoSystemFee;
uint256 liquidityFee;
uint256 taxFee;
uint256 ownerFee;
uint256 burnFee;
address ecoSystem;
address owner;
}
/**
* @dev 费用值结构体
* 用于存储反射和转账相关的费用数值
*/
struct FeeValues {
uint256 rAmount; // 反射数量
uint256 rTransferAmount;// 反射转账数量
uint256 rFee; // 反射费用
uint256 tTransferAmount;// 代币转账数量
uint256 tEchoSystem; // 生态系统费用
uint256 tLiquidity; // 流动性费用
uint256 tFee; // 税费
uint256 tOwner; // 所有者费用
uint256 tBurn; // 销毁费用
}
/**
* @dev 代币费用值结构体
* 用于存储代币相关的费用数值
*/
struct tFeeValues {
uint256 tTransferAmount;// 转账数量
uint256 tEchoSystem; // 生态系统费用
uint256 tLiquidity; // 流动性费用
uint256 tFee; // 税费
uint256 tOwner; // 所有者费用
uint256 tBurn; // 销毁费用
}
// 外部合约接口
IUniswapV2Router02 public uniswapV2Router; // Uniswap V2路由器
address public uniswapV2Pair; // Uniswap V2交易对
address public WBNB; // WBNB代币地址
address private migration; // 迁移合约地址
address private _initializerAccount; // 初始化账户
address public _burnAddress; // 销毁地址
bool inSwapAndLiquify; // 是否正在交换和注入流动性
bool public swapAndLiquifyEnabled; // 是否启用交换和注入流动性
uint256 public _maxTxAmount; // 最大交易数量
uint256 private numTokensSellToAddToLiquidity; // 触发添加流动性的代币数量
bool private _upgraded; // 是否已升级
event MinTokensBeforeSwapUpdated(uint256 minTokensBeforeSwap);
/**
* @dev 修饰符:锁定交换
* 防止重入攻击
*/
modifier lockTheSwap() {
inSwapAndLiquify = true;
_;
inSwapAndLiquify = false;
}
/**
* @dev 修饰符:锁定升级
* 确保只能升级一次
*/
modifier lockUpgrade() {
require(!_upgraded, "Safemoon: 已经升级");
_;
_upgraded = true;
}
/**
* @dev 修饰符:检查等级索引
* 确保等级索引有效
*/
modifier checkTierIndex(uint256 _index) {
require(feeTiers.length > _index, "Safemoon: 无效的等级索引");
_;
}
/**
* @dev 修饰符:防止黑名单地址
* 检查地址是否在黑名单中
*/
modifier preventBlacklisted(address _account, string memory errorMsg) {
require(!_isBlacklisted[_account], errorMsg);
_;
}
/**
* @dev 修饰符:检查是否是路由器
* 自动识别并标记路由器地址
*/
modifier isRouter(address _sender) {
{
uint32 size;
assembly {
size := extcodesize(_sender)
}
if (size > 0) {
uint256 senderTier = _accountsTier[_sender];
if (senderTier == 0) {
IUniswapV2Router02 _routerCheck = IUniswapV2Router02(_sender);
try _routerCheck.factory() returns (address factory) {
_accountsTier[_sender] = 1;
} catch {}
}
}
}
_;
}
// 状态变量
uint256 public numTokensToCollectBNB; // 触发收集BNB的代币数量
uint256 public numOfBnbToSwapAndEvolve; // 触发交换和进化的BNB数量
bool inSwapAndEvolve; // 是否正在交换和进化
bool public swapAndEvolveEnabled; // 是否启用交换和进化
/**
* @dev 排除的总反射和代币数量
* 用于优化getCurrentSupply函数的性能
* 在合约升级时需要调用updateTotalExcluded来初始化这些值
*/
uint256 private _rTotalExcluded; // 排除的总反射数量
uint256 private _tTotalExcluded; // 排除的总代币数量
// 映射
mapping(address => bool) public listIgnoreCollectBNBAddresses; // 不触发收集BNB的地址列表
address public bridgeBurnAddress; // 桥接销毁地址
mapping(address => bool) public whitelistMint; // 铸造白名单
bool public isPaused; // 是否暂停
mapping(address => bool) public whitelistPause; // 暂停白名单
mapping(address => bool) public isSFMPair; // SFM交易对
// 事件
event SwapAndEvolveEnabledUpdated(bool enabled);
event SwapAndEvolve(uint256 bnbSwapped, uint256 tokenReceived, uint256 bnbIntoLiquidity);
event AddIgnoreCollectBNBAddress(address ignoreAddress);
event RemoveIgnoreCollectBNBAddress(address ignoreAddress);
event WhitelistPause(address user, bool value);
event SetSFMPair(address pair, bool value);
event PauseContract(bool value);
/**
* @dev 修饰符:只允许铸造白名单
*/
modifier onlyWhitelistMint() {
require(whitelistMint[msg.sender], "无效");
_;
}
/**
* @dev 修饰符:合约未暂停时
*/
modifier whenNotPaused() {
require(!isPaused || whitelistPause[msg.sender], "已暂停");
_;
}
// 状态变量
mapping(address => uint256) private _rOwned; // 地址拥有的反射数量
mapping(address => uint256) private _tOwned; // 地址拥有的代币数量
mapping(address => mapping(address => uint256)) private _allowances; // 授权映射
mapping(address => bool) private _isExcludedFromFee; // 免费名单
mapping(address => bool) private _isExcluded; // 排除名单
mapping(address => bool) private _isBlacklisted; // 黑名单
mapping(address => uint256) private _accountsTier; // 账户等级
address[] private _excluded; // 排除地址数组
uint256 private constant MAX = ~uint256(0); // 最大uint256值
uint256 private _tTotal; // 总代币数量
uint256 private _rTotal; // 总反射数量
uint256 private _tFeeTotal; // 总费用数量
uint256 private _maxFee; // 最大费用
string private _name; // 代币名称
string private _symbol; // 代币符号
uint8 private _decimals; // 小数位数
FeeTier public _defaultFees; // 默认费用
FeeTier private _previousFees; // 之前的费用
FeeTier private _emptyFees; // 空费用
FeeTier[] private feeTiers; // 费用等级数组
/**
* @dev 初始化函数
* 替代构造函数
*/
function initialize() public initializer {
__Context_init_unchained();
__Ownable_init_unchained();
__Safemoon_v2_init_unchained();
}
/**
* @dev Safemoon V2初始化函数
* 设置代币基本参数和初始状态
*/
function __Safemoon_v2_init_unchained() internal initializer {
_name = "SafeMoon";
_symbol = "SFM";
_decimals = 9;
_tTotal = 1000000 * 10**6 * 10**9;
_rTotal = (MAX - (MAX % _tTotal));
_maxFee = 1000;
_maxTxAmount = 5000 * 10**6 * 10**9;
numTokensSellToAddToLiquidity = 500 * 10**6 * 10**9;
_burnAddress = 0x000000000000000000000000000000000000dEaD;
_initializerAccount = _msgSender();
_rOwned[_initializerAccount] = _rTotal;
// 排除所有者和合约地址的费用
_isExcludedFromFee[owner()] = true;
_isExcludedFromFee[address(this)] = true;
// 初始化费用等级
__Safemoon_tiers_init();
emit Transfer(address(0), _msgSender(), _tTotal);
}
/**
* @dev 初始化路由器和交易对
* @param _router 路由器地址
*/
function initRouterAndPair(address _router) external onlyOwner {
uniswapV2Router = IUniswapV2Router02(_router);
WBNB = uniswapV2Router.WETH();
// 创建新的交易对
uniswapV2Pair = IUniswapV2Factory(uniswapV2Router.factory()).createPair(address(this), WBNB, address(this));
}
/**
* @dev 初始化费用等级
* 设置默认和其他费用等级
*/
function __Safemoon_tiers_init() internal initializer {
_defaultFees = _addTier(0, 500, 500, 0, 0, address(0), address(0));
_addTier(50, 50, 100, 0, 0, address(0), address(0));
_addTier(50, 50, 100, 100, 0, address(0), address(0));
_addTier(100, 125, 125, 150, 0, address(0), address(0));
}
/**
* @dev 返回代币名称
*/
function name() public view returns (string memory) {
return _name;
}
/**
* @dev 返回代币符号
*/
function symbol() public view returns (string memory) {
return _symbol;
}
/**
* @dev 返回代币小数位数
*/
function decimals() public view returns (uint8) {
return _decimals;
}
/**
* @dev 返回代币总供应量
*/
function totalSupply() public view override returns (uint256) {
return _tTotal;
}
/**
* @dev 返回账户余额
* @param account 查询的账户地址
*/
function balanceOf(address account) public view override returns (uint256) {
if (_isExcluded[account]) return _tOwned[account];
return tokenFromReflection(_rOwned[account]);
}
/**
* @dev 转移代币
* @param recipient 接收者地址
* @param amount 转移数量
*/
function transfer(address recipient, uint256 amount) public override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
/**
* @dev 返回授权额度
* @param owner 持有者地址
* @param spender 被授权者地址
*/
function allowance(address owner, address spender) public view override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev 授权代币
* @param spender 被授权者地址
* @param amount 授权数量
*/
function approve(address spender, uint256 amount) public override whenNotPaused returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
/**
* @dev 通过授权转移代币
* @param sender 发送者地址
* @param recipient 接收者地址
* @param amount 转移数量
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) public override returns (bool) {
_transfer(sender, recipient, amount);
_approve(
sender,
_msgSender(),
_allowances[sender][_msgSender()].sub(amount, "BEP20: 转账金额超过授权额度")
);
return true;
}
/**
* @dev 检查地址是否被排除在奖励之外
* @param account 检查的地址
*/
function isExcludedFromReward(address account) public view returns (bool) {
return _isExcluded[account];
}
/**
* @dev 返回总费用
*/
function totalFees() public view returns (uint256) {
return _tFeeTotal;
}
/**
* @dev 计算特定等级的代币反射值
* @param tAmount 代币数量
* @param _tierIndex 等级索引
* @param deductTransferFee 是否扣除转账费用
*/
function reflectionFromTokenInTiers(
uint256 tAmount,
uint256 _tierIndex,
bool deductTransferFee
) public view returns (uint256) {
require(tAmount <= _tTotal, "金额必须小于总供应量");
if (!deductTransferFee) {
FeeValues memory _values = _getValues(tAmount, _tierIndex);
return _values.rAmount;
} else {
FeeValues memory _values = _getValues(tAmount, _tierIndex);
return _values.rTransferAmount;
}
}
/**
* @dev 计算代币的反射值
* @param tAmount 代币数量
* @param deductTransferFee 是否扣除转账费用
*/
function reflectionFromToken(uint256 tAmount, bool deductTransferFee) public view returns (uint256) {
return reflectionFromTokenInTiers(tAmount, 0, deductTransferFee);
}
/**
* @dev 从反射值计算代币数量
* @param rAmount 反射值
*/
function tokenFromReflection(uint256 rAmount) public view returns (uint256) {
require(rAmount <= _rTotal, "金额必须小于总反射值");
uint256 currentRate = _getRate();
return rAmount.div(currentRate);
}
/**
* @dev 将地址排除在奖励之外
* @param account 要排除的地址
*/
function excludeFromReward(address account) public onlyOwner {
require(!_isExcluded[account], "无效");
if (_rOwned[account] > 0) {
_tOwned[account] = tokenFromReflection(_rOwned[account]);
_tTotalExcluded = _tTotalExcluded.add(_tOwned[account]);
_rTotalExcluded = _rTotalExcluded.add(_rOwned[account]);
}
_isExcluded[account] = true;
_excluded.push(account);
}
/**
* @dev 将地址包含在奖励中
* @param account 要包含的地址
*/
function includeInReward(address account) external onlyOwner {
require(_isExcluded[account], "无效");
for (uint256 i = 0; i < _excluded.length; i++) {
if (_excluded[i] == account) {
_excluded[i] = _excluded[_excluded.length - 1];
_rOwned[account] = _tOwned[account] * _getRate();
_tTotalExcluded = _tTotalExcluded.sub(_tOwned[account]);
_rTotalExcluded = _rTotalExcluded.sub(_rOwned[account]);
_tOwned[account] = 0;
_isExcluded[account] = false;
_excluded.pop();
break;
}
}
}
/**
* @dev 将地址排除在费用之外
* @param account 要排除的地址
*/
function excludeFromFee(address account) public onlyOwner {
_isExcludedFromFee[account] = true;
}
/**
* @dev 将地址包含在费用中
* @param account 要包含的地址
*/
function includeInFee(address account) public onlyOwner {
_isExcludedFromFee[account] = false;
}
/**
* @dev 将地址添加到白名单
* @param _account 要添加的地址
* @param _tierIndex 费用等级索引
*/
function whitelistAddress(address _account, uint256 _tierIndex)
public
onlyOwner
checkTierIndex(_tierIndex)
preventBlacklisted(_account, "Safemoon: 选择的账户在黑名单中")
{
require(_account != address(0), "Safemoon: 无效地址");
_accountsTier[_account] = _tierIndex;
}
/**
* @dev 将地址从白名单中移除
* @param _account 要移除的地址
*/
function excludeWhitelistedAddress(address _account) public onlyOwner {
require(_account != address(0), "Safemoon: 无效地址");
require(_accountsTier[_account] > 0, "Safemoon: 账户不在白名单中");
_accountsTier[_account] = 0;
}
/**
* @dev 获取账户的费用等级
* @param _account 查询的账户地址
*/
function accountTier(address _account) public view returns (FeeTier memory) {
return feeTiers[_accountsTier[_account]];
}
/**
* @dev 检查地址是否在白名单中
* @param _account 检查的地址
*/
function isWhitelisted(address _account) public view returns (bool) {
return _accountsTier[_account] > 0;
}
/**
* @dev 检查费用是否超过限制
* @param _tier 费用等级
*/
function checkFees(FeeTier memory _tier) internal view returns (FeeTier memory) {
uint256 _fees = _tier.ecoSystemFee.add(_tier.liquidityFee).add(_tier.taxFee).add(_tier.ownerFee).add(
_tier.burnFee
);
require(_fees <= _maxFee, "Safemoon: 费用超过最大限制");
return _tier;
}
/**
* @dev 检查费用变化是否合法
* @param _tier 费用等级
* @param _oldFee 旧费用
* @param _newFee 新费用
*/
function checkFeesChanged(
FeeTier memory _tier,
uint256 _oldFee,
uint256 _newFee
) internal view {
uint256 _fees = _tier
.ecoSystemFee
.add(_tier.liquidityFee)
.add(_tier.taxFee)
.add(_tier.ownerFee)
.add(_tier.burnFee)
.sub(_oldFee)
.add(_newFee);
require(_fees <= _maxFee, "Safemoon: 费用超过最大限制");
}
/**
* @dev 设置生态系统费用百分比
* @param _tierIndex 费用等级索引
* @param _ecoSystemFee 新的生态系统费用
*/
function setEcoSystemFeePercent(uint256 _tierIndex, uint256 _ecoSystemFee)
external
onlyOwner
checkTierIndex(_tierIndex)
{
FeeTier memory tier = feeTiers[_tierIndex];
checkFeesChanged(tier, tier.ecoSystemFee, _ecoSystemFee);
feeTiers[_tierIndex].ecoSystemFee = _ecoSystemFee;
if (_tierIndex == 0) {
_defaultFees.ecoSystemFee = _ecoSystemFee;
}
}
/**
* @dev 设置流动性费用百分比
* @param _tierIndex 费用等级索引
* @param _liquidityFee 新的流动性费用
*/
function setLiquidityFeePercent(uint256 _tierIndex, uint256 _liquidityFee)
external
onlyOwner
checkTierIndex(_tierIndex)
{
FeeTier memory tier = feeTiers[_tierIndex];
checkFeesChanged(tier, tier.liquidityFee, _liquidityFee);
feeTiers[_tierIndex].liquidityFee = _liquidityFee;
if (_tierIndex == 0) {
_defaultFees.liquidityFee = _liquidityFee;
}
}
/**
* @dev 设置税费百分比
* @param _tierIndex 费用等级索引
* @param _taxFee 新的税费
*/
function setTaxFeePercent(uint256 _tierIndex, uint256 _taxFee) external onlyOwner checkTierIndex(_tierIndex) {
FeeTier memory tier = feeTiers[_tierIndex];
checkFeesChanged(tier, tier.taxFee, _taxFee);
feeTiers[_tierIndex].taxFee = _taxFee;
if (_tierIndex == 0) {
_defaultFees.taxFee = _taxFee;
}
}
/**
* @dev 设置所有者费用百分比
* @param _tierIndex 费用等级索引
* @param _ownerFee 新的所有者费用
*/
function setOwnerFeePercent(uint256 _tierIndex, uint256 _ownerFee) external onlyOwner checkTierIndex(_tierIndex) {
FeeTier memory tier = feeTiers[_tierIndex];
checkFeesChanged(tier, tier.ownerFee, _ownerFee);
feeTiers[_tierIndex].ownerFee = _ownerFee;
if (_tierIndex == 0) {
_defaultFees.ownerFee = _ownerFee;
}
}
/**
* @dev 设置销毁费用百分比
* @param _tierIndex 费用等级索引
* @param _burnFee 新的销毁费用
*/
function setBurnFeePercent(uint256 _tierIndex, uint256 _burnFee) external onlyOwner checkTierIndex(_tierIndex) {
FeeTier memory tier = feeTiers[_tierIndex];
checkFeesChanged(tier, tier.burnFee, _burnFee);
feeTiers[_tierIndex].burnFee = _burnFee;
if (_tierIndex == 0) {
_defaultFees.burnFee = _burnFee;
}
}
/**
* @dev 设置生态系统费用接收地址
* @param _tierIndex 费用等级索引
* @param _ecoSystem 新的生态系统地址
*/
function setEcoSystemFeeAddress(uint256 _tierIndex, address _ecoSystem)
external
onlyOwner
checkTierIndex(_tierIndex)
{
require(_ecoSystem != address(0), "Safemoon: 不允许零地址");
excludeFromReward(_ecoSystem);
feeTiers[_tierIndex].ecoSystem = _ecoSystem;
if (_tierIndex == 0) {
_defaultFees.ecoSystem = _ecoSystem;
}
}
/**
* @dev 设置所有者费用接收地址
* @param _tierIndex 费用等级索引
* @param _owner 新的所有者地址
*/
function setOwnerFeeAddress(uint256 _tierIndex, address _owner) external onlyOwner checkTierIndex(_tierIndex) {
require(_owner != address(0), "Safemoon: 不允许零地址");
excludeFromReward(_owner);
feeTiers[_tierIndex].owner = _owner;
if (_tierIndex == 0) {
_defaultFees.owner = _owner;
}
}
/**
* @dev 添加新的费用等级
* @param _ecoSystemFee 生态系统费用
* @param _liquidityFee 流动性费用
* @param _taxFee 税费
* @param _ownerFee 所有者费用
* @param _burnFee 销毁费用
* @param _ecoSystem 生态系统地址
* @param _owner 所有者地址
*/
function addTier(
uint256 _ecoSystemFee,
uint256 _liquidityFee,
uint256 _taxFee,
uint256 _ownerFee,
uint256 _burnFee,
address _ecoSystem,
address _owner
) public onlyOwner {
_addTier(_ecoSystemFee, _liquidityFee, _taxFee, _ownerFee, _burnFee, _ecoSystem, _owner);
}
/**
* @dev 内部函数:添加新的费用等级
*/
function _addTier(
uint256 _ecoSystemFee,
uint256 _liquidityFee,
uint256 _taxFee,
uint256 _ownerFee,
uint256 _burnFee,
address _ecoSystem,
address _owner
) internal returns (FeeTier memory) {
FeeTier memory _newTier = checkFees(
FeeTier(_ecoSystemFee, _liquidityFee, _taxFee, _ownerFee, _burnFee, _ecoSystem, _owner)
);
excludeFromReward(_ecoSystem);
excludeFromReward(_owner);
feeTiers.push(_newTier);
return _newTier;
}
/**
* @dev 获取指定索引的费用等级
* @param _tierIndex 费用等级索引
*/
function feeTier(uint256 _tierIndex) public view checkTierIndex(_tierIndex) returns (FeeTier memory) {
return feeTiers[_tierIndex];
}
/**
* @dev 将地址添加到黑名单
* @param account 要添加的地址
*/
function blacklistAddress(address account) public onlyOwner {
_isBlacklisted[account] = true;
_accountsTier[account] = 0;
}
/**
* @dev 将地址从黑名单中移除
* @param account 要移除的地址
*/
function unBlacklistAddress(address account) public onlyOwner {
_isBlacklisted[account] = false;
}
/**
* @dev 更新路由器和交易对地址
* @param _uniswapV2Router 新的路由器地址
* @param _uniswapV2Pair 新的交易对地址
*/
function updateRouterAndPair(address _uniswapV2Router, address _uniswapV2Pair) public onlyOwner {
uniswapV2Router = IUniswapV2Router02(_uniswapV2Router);
uniswapV2Pair = _uniswapV2Pair;
WBNB = uniswapV2Router.WETH();
}
/**
* @dev 设置默认配置
*/
function setDefaultSettings() external onlyOwner {
swapAndLiquifyEnabled = false;
swapAndEvolveEnabled = true;
}
/**
* @dev 设置最大交易数量百分比
* @param maxTxPercent 最大交易百分比
*/
function setMaxTxPercent(uint256 maxTxPercent) external onlyOwner {
_maxTxAmount = _tTotal.mul(maxTxPercent).div(10**4);
}
/**
* @dev 设置是否启用交换和进化
* @param _enabled 是否启用
*/
function setSwapAndEvolveEnabled(bool _enabled) public onlyOwner {
swapAndEvolveEnabled = _enabled;
emit SwapAndEvolveEnabledUpdated(_enabled);
}
/**
* @dev 接收BNB的回退函数
*/
receive() external payable {}
/**
* @dev 反射费用
* @param rFee 反射费用数量
* @param tFee 代币费用数量
*/
function _reflectFee(uint256 rFee, uint256 tFee) private {
_rTotal = _rTotal.sub(rFee);
_tFeeTotal = _tFeeTotal.add(tFee);
}
/**
* @dev 获取转账相关的各种值
* @param tAmount 代币数量
* @param _tierIndex 费用等级索引
*/
function _getValues(uint256 tAmount, uint256 _tierIndex) private view returns (FeeValues memory) {
tFeeValues memory tValues = _getTValues(tAmount, _tierIndex);
uint256 tTransferFee = tValues.tLiquidity.add(tValues.tEchoSystem).add(tValues.tOwner).add(tValues.tBurn);
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee) = _getRValues(
tAmount,
tValues.tFee,
tTransferFee,
_getRate()
);
return
FeeValues(
rAmount,
rTransferAmount,
rFee,
tValues.tTransferAmount,
tValues.tEchoSystem,
tValues.tLiquidity,
tValues.tFee,
tValues.tOwner,
tValues.tBurn
);
}
/**
* @dev 获取代币相关的费用值
* @param tAmount 代币数量
* @param _tierIndex 费用等级索引
*/
function _getTValues(uint256 tAmount, uint256 _tierIndex) private view returns (tFeeValues memory) {
FeeTier memory tier = feeTiers[_tierIndex];
tFeeValues memory tValues = tFeeValues(
0,
calculateFee(tAmount, tier.ecoSystemFee),
calculateFee(tAmount, tier.liquidityFee),
calculateFee(tAmount, tier.taxFee),
calculateFee(tAmount, tier.ownerFee),
calculateFee(tAmount, tier.burnFee)
);
tValues.tTransferAmount = tAmount
.sub(tValues.tEchoSystem)
.sub(tValues.tFee)
.sub(tValues.tLiquidity)
.sub(tValues.tOwner)
.sub(tValues.tBurn);
return tValues;
}
/**
* @dev 获取反射相关的值
* @param tAmount 代币数量
* @param tFee 代币费用
* @param tTransferFee 转账费用
* @param currentRate 当前汇率
*/
function _getRValues(
uint256 tAmount,
uint256 tFee,
uint256 tTransferFee,
uint256 currentRate
)
private
pure
returns (
uint256,
uint256,
uint256
)
{
uint256 rAmount = tAmount.mul(currentRate);
uint256 rFee = tFee.mul(currentRate);
uint256 rTransferFee = tTransferFee.mul(currentRate);
uint256 rTransferAmount = rAmount.sub(rFee).sub(rTransferFee);
return (rAmount, rTransferAmount, rFee);
}
/**
* @dev 获取当前汇率
* @return uint256 当前汇率
*/
function _getRate() private view returns (uint256) {
(uint256 rSupply, uint256 tSupply) = _getCurrentSupply();
return rSupply.div(tSupply);
}
/**
* @dev 获取当前供应量
* @return uint256, uint256 当前反射供应量和代币供应量
*/
function _getCurrentSupply() private view returns (uint256, uint256) {
if (_rTotalExcluded > _rTotal || _tTotalExcluded > _tTotal) {
return (_rTotal, _tTotal);
}
uint256 rSupply = _rTotal.sub(_rTotalExcluded);
uint256 tSupply = _tTotal.sub(_tTotalExcluded);
if (rSupply < _rTotal.div(_tTotal)) return (_rTotal, _tTotal);
return (rSupply, tSupply);
}
/**
* @dev 计算费用
* @param _amount 金额
* @param _fee 费率
* @return uint256 费用金额
*/
function calculateFee(uint256 _amount, uint256 _fee) private pure returns (uint256) {
if (_fee == 0) return 0;
return _amount.mul(_fee).div(10**4);
}
/**
* @dev 移除所有费用
*/
function removeAllFee() private {
_previousFees = feeTiers[0];
feeTiers[0] = _emptyFees;
}
/**
* @dev 恢复所有费用
*/
function restoreAllFee() private {
feeTiers[0] = _previousFees;
}
/**
* @dev 检查地址是否被排除在费用之外
* @param account 检查的地址
*/
function isExcludedFromFee(address account) public view returns (bool) {
return _isExcludedFromFee[account];
}
/**
* @dev 检查地址是否在黑名单中
* @param account 检查的地址
*/
function isBlacklisted(address account) public view returns (bool) {
return _isBlacklisted[account];
}
/**
* @dev 批准代币授权
* @param owner 持有者地址
* @param spender 被授权者地址
* @param amount 授权数量
*/
function _approve(
address owner,
address spender,
uint256 amount
)
private
preventBlacklisted(owner, "Safemoon: 所有者地址在黑名单中")
preventBlacklisted(spender, "Safemoon: 被授权者地址在黑名单中")
{
require(owner != address(0), "BEP20: 从零地址授权");
require(spender != address(0), "BEP20: 授权给零地址");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev 转移代币
* @param from 发送者地址
* @param to 接收者地址
* @param amount 转移数量
*/
function _transfer(
address from,
address to,
uint256 amount
)
private
preventBlacklisted(_msgSender(), "Safemoon: 地址在黑名单中")
preventBlacklisted(from, "Safemoon: 发送者地址在黑名单中")
preventBlacklisted(to, "Safemoon: 接收者地址在黑名单中")
isRouter(_msgSender())
{
require(from != address(0), "BEP20: 从零地址转账");
require(to != address(0), "BEP20: 转账到零地址");
require(amount > 0, "转账金额必须大于零");
require(_canAction(from, to), "已暂停");
if (from != owner() && to != owner())
require(amount <= _maxTxAmount, "转账金额超过最大限制");
// 检查合约代币余额是否超过触发自动流动性的阈值
uint256 contractTokenBalance = balanceOf(address(this));
if (contractTokenBalance >= _maxTxAmount) {
contractTokenBalance = _maxTxAmount;
}
bool overMinTokenBalance = contractTokenBalance >= numTokensToCollectBNB;
if (
overMinTokenBalance &&
!inSwapAndLiquify &&
swapAndEvolveEnabled &&
!_isInCollectBNBWhitelist(from) &&
!_isInCollectBNBWhitelist(to)
) {
contractTokenBalance = numTokensToCollectBNB;
collectBNB(contractTokenBalance);
}
// 是否收取费用
bool takeFee = true;
// 如果地址在免费名单中则不收取费用
if (_isExcludedFromFee[from] || _isExcludedFromFee[to]) {
takeFee = false;
}
uint256 tierIndex = 0;
if (takeFee) {
tierIndex = _accountsTier[from];
if (_msgSender() != from) {
tierIndex = _accountsTier[_msgSender()];
}
}
// 转移代币
_tokenTransfer(from, to, amount, tierIndex, takeFee);
}
/**
* @dev 检查是否可以执行操作
* @param from 发送者地址
* @param to 接收者地址
*/
function _canAction(address from, address to) private view returns (bool) {
if (!isPaused) {
return true;
}
if (whitelistPause[from] && whitelistPause[to]) {
return true;
}
if (whitelistPause[from] && !isSFMPair[from]) {
return true;
}
return false;
}
/**
* @dev 收集BNB
* @param contractTokenBalance 合约代币余额
*/
function collectBNB(uint256 contractTokenBalance) private lockTheSwap {
swapTokensForBnb(contractTokenBalance);
}
/**
* @dev 将代币换成BNB
* @param tokenAmount 代币数量
*/
function swapTokensForBnb(uint256 tokenAmount) private {
// 生成交易路径:token -> wbnb
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = uniswapV2Router.WETH();
ISafeSwapTradeRouter tradeRouter = ISafeSwapTradeRouter(uniswapV2Router.routerTrade());
// 获取费用
uint256 feeAmount = tradeRouter.getSwapFees(tokenAmount, path);
_approve(address(this), address(uniswapV2Router), tokenAmount);
_approve(address(this), address(tradeRouter), tokenAmount);
ISafeSwapTradeRouter.Trade memory trade = ISafeSwapTradeRouter.Trade({
amountIn: tokenAmount,
amountOut: 0,
path: path,
to: payable(address(this)),
deadline: block.timestamp
});
tradeRouter.swapExactTokensForETHAndFeeAmount{ value: feeAmount }(trade);
}
/**
* @dev 交换和进化
* 将合约中的BNB分成两半,一半用于购买代币,另一半用于添加流动性
*/
function swapAndEvolve() public onlyOwner lockTheSwap {
// 将合约余额分成两半
uint256 contractBnbBalance = address(this).balance;
require(contractBnbBalance >= numOfBnbToSwapAndEvolve, "BNB余额未达到交换和进化阈值");
contractBnbBalance = numOfBnbToSwapAndEvolve;
uint256 half = contractBnbBalance.div(2);
uint256 otherHalf = contractBnbBalance.sub(half);
// 记录当前余额
uint256 initialBalance = ISafemoon(address(this)).balanceOf(msg.sender);
// 用BNB换取代币
swapBnbForTokens(half);
// 计算获得的代币数量
uint256 newBalance = ISafemoon(address(this)).balanceOf(msg.sender);
uint256 swapeedToken = newBalance.sub(initialBalance);
// 添加流动性
_approve(msg.sender, address(this), swapeedToken);
ISafemoon(address(this)).transferFrom(msg.sender, address(this), swapeedToken);
addLiquidity(swapeedToken, otherHalf);
emit SwapAndEvolve(half, swapeedToken, otherHalf);
}
/**
* @dev 用BNB换取代币
* @param bnbAmount BNB数量
*/
function swapBnbForTokens(uint256 bnbAmount) private {
// 生成交易路径:wbnb -> token
address[] memory path = new address[](2);
path[0] = uniswapV2Router.WETH();
path[1] = address(this);
ISafeSwapTradeRouter tradeRouter = ISafeSwapTradeRouter(uniswapV2Router.routerTrade());
_approve(owner(), address(uniswapV2Router), bnbAmount);
// 获取费用
uint256 feeAmount = tradeRouter.getSwapFees(bnbAmount, path);
ISafeSwapTradeRouter.Trade memory trade = ISafeSwapTradeRouter.Trade({
amountIn: bnbAmount,
amountOut: 0,
path: path,
to: payable(owner()),
deadline: block.timestamp
});
tradeRouter.swapExactETHForTokensWithFeeAmount{ value: bnbAmount + feeAmount }(trade, feeAmount);
}
/**
* @dev 添加流动性
* @param tokenAmount 代币数量
* @param bnbAmount BNB数量
*/
function addLiquidity(uint256 tokenAmount, uint256 bnbAmount) private {
// 批准代币转账
_approve(address(this), address(uniswapV2Router), tokenAmount);
// 添加流动性
uniswapV2Router.addLiquidityETH{ value: bnbAmount }(
address(this),
tokenAmount,
0, // 滑点不可避免
0, // 滑点不可避免
owner(),
block.timestamp
);
}
/**
* @dev 代币转账
* 处理所有费用的收取
* @param sender 发送者地址
* @param recipient 接收者地址
* @param amount 转账数量
* @param tierIndex 费用等级索引
* @param takeFee 是否收取费用
*/
function _tokenTransfer(
address sender,
address recipient,
uint256 amount,
uint256 tierIndex,
bool takeFee
) private {
if (!takeFee) removeAllFee();
if (!_isExcluded[sender] && !_isExcluded[recipient]) {
_transferStandard(sender, recipient, amount, tierIndex);
} else if (_isExcluded[sender] && !_isExcluded[recipient]) {
_transferFromExcluded(sender, recipient, amount, tierIndex);
} else if (!_isExcluded[sender] && _isExcluded[recipient]) {
_transferToExcluded(sender, recipient, amount, tierIndex);
} else if (_isExcluded[sender] && _isExcluded[recipient]) {
_transferBothExcluded(sender, recipient, amount, tierIndex);
}
if (!takeFee) restoreAllFee();
}
/**
* @dev 在排除列表中的两个地址之间转账
* @param sender 发送者地址
* @param recipient 接收者地址
* @param tAmount 转账数量
* @param tierIndex 费用等级索引
*/
function _transferBothExcluded(
address sender,
address recipient,
uint256 tAmount,
uint256 tierIndex
) private {
FeeValues memory _values = _getValues(tAmount, tierIndex);
_tOwned[sender] = _tOwned[sender].sub(tAmount);
_tOwned[recipient] = _tOwned[recipient].add(_values.tTransferAmount);
if (_values.tTransferAmount > tAmount) {
uint256 tmpValue = _values.tTransferAmount - tAmount;
_tTotalExcluded = _tTotalExcluded.add(tmpValue);
} else {
uint256 tmpValue = tAmount - _values.tTransferAmount;
_tTotalExcluded = _tTotalExcluded.sub(tmpValue);
}
if (_values.rTransferAmount > _values.rAmount) {
uint256 tmpValue = _values.rTransferAmount - _values.rAmount;
_rTotalExcluded = _rTotalExcluded.add(tmpValue);
} else {
uint256 tmpValue = _values.rAmount - _values.rTransferAmount;
_rTotalExcluded = _rTotalExcluded.sub(tmpValue);
}
_takeFees(sender, _values, tierIndex);
_reflectFee(_values.rFee, _values.tFee);
emit Transfer(sender, recipient, _values.tTransferAmount);
}
/**
* @dev 标准转账
* @param sender 发送者地址
* @param recipient 接收者地址
* @param tAmount 转账数量
* @param tierIndex 费用等级索引
*/
function _transferStandard(
address sender,
address recipient,
uint256 tAmount,
uint256 tierIndex
) private {
FeeValues memory _values = _getValues(tAmount, tierIndex);
_rOwned[sender] = _rOwned[sender].sub(_values.rAmount);
_rOwned[recipient] = _rOwned[recipient].add(_values.rTransferAmount);
_takeFees(sender, _values, tierIndex);
_reflectFee(_values.rFee, _values.tFee);
emit Transfer(sender, recipient, _values.tTransferAmount);
}
/**
* @dev 向排除列表中的地址转账
* @param sender 发送者地址
* @param recipient 接收者地址
* @param tAmount 转账数量
* @param tierIndex 费用等级索引
*/
function _transferToExcluded(
address sender,
address recipient,
uint256 tAmount,
uint256 tierIndex
) private {
FeeValues memory _values = _getValues(tAmount, tierIndex);
_rOwned[sender] = _rOwned[sender].sub(_values.rAmount);
_tOwned[recipient] = _tOwned[recipient].add(_values.tTransferAmount);
_tTotalExcluded = _tTotalExcluded.add(_values.tTransferAmount);
_rTotalExcluded = _rTotalExcluded.add(_values.rTransferAmount);
_takeFees(sender, _values, tierIndex);
_reflectFee(_values.rFee, _values.tFee);
emit Transfer(sender, recipient, _values.tTransferAmount);
}
/**
* @dev 从排除列表中的地址转账
* @param sender 发送者地址
* @param recipient 接收者地址
* @param tAmount 转账数量
* @param tierIndex 费用等级索引
*/
function _transferFromExcluded(
address sender,
address recipient,
uint256 tAmount,
uint256 tierIndex
) private {
FeeValues memory _values = _getValues(tAmount, tierIndex);
_tOwned[sender] = _tOwned[sender].sub(tAmount);
_rOwned[recipient] = _rOwned[recipient].add(_values.rTransferAmount);
_tTotalExcluded = _tTotalExcluded.sub(tAmount);
_rTotalExcluded = _rTotalExcluded.sub(_values.rAmount);
_takeFees(sender, _values, tierIndex);
_reflectFee(_values.rFee, _values.tFee);
emit Transfer(sender, recipient, _values.tTransferAmount);
}
/**
* @dev 收取费用
* @param sender 发送者地址
* @param values 费用值
* @param tierIndex 费用等级索引
*/
function _takeFees(
address sender,
FeeValues memory values,
uint256 tierIndex
) private {
_takeFee(sender, values.tLiquidity, address(this));
_takeFee(sender, values.tEchoSystem, feeTiers[tierIndex].ecoSystem);
_takeFee(sender, values.tOwner, feeTiers[tierIndex].owner);
_takeBurn(sender, values.tBurn);
}
/**
* @dev 收取费用
* @param sender 发送者地址
* @param tAmount 代币数量
* @param recipient 接收者地址
*/
function _takeFee(
address sender,
uint256 tAmount,
address recipient
) private {
if (recipient == address(0)) return;
if (tAmount == 0) return;
uint256 currentRate = _getRate();
uint256 rAmount = tAmount.mul(currentRate);
_rOwned[recipient] = _rOwned[recipient].add(rAmount);
if (_isExcluded[recipient]) {
_tOwned[recipient] = _tOwned[recipient].add(tAmount);
_tTotalExcluded = _tTotalExcluded.add(tAmount);
_rTotalExcluded = _rTotalExcluded.add(rAmount);
}
emit Transfer(sender, recipient, tAmount);
}
/**
* @dev 销毁代币
* @param sender 发送者地址
* @param _amount 销毁数量
*/
function _takeBurn(address sender, uint256 _amount) private {
if (_amount == 0) return;
_tOwned[_burnAddress] = _tOwned[_burnAddress].add(_amount);
uint256 _rAmount = _amount * _getRate();
_rOwned[_burnAddress] = _rOwned[_burnAddress].add(_rAmount);
if (_isExcluded[_burnAddress]) {
_rTotalExcluded = _rTotalExcluded.add(_rAmount);
_tTotalExcluded = _tTotalExcluded.add(_amount);
}
emit Transfer(sender, _burnAddress, _amount);
}
/**
* @dev 设置迁移地址
* @param _migration 迁移合约地址
*/
function setMigrationAddress(address _migration) public onlyOwner {
migration = _migration;
}
/**
* @dev 检查是否开始迁移
*/
function isMigrationStarted() external view override returns (bool) {
return migration != address(0);
}
/**
* @dev 迁移代币
* @param account 账户地址
* @param amount 迁移数量
*/
function migrate(address account, uint256 amount)
external
override
preventBlacklisted(account, "Safemoon: 迁移账户在黑名单中")
{
require(migration != address(0), "Safemoon: 迁移未开始");
require(_msgSender() == migration, "Safemoon: 不允许");
_migrate(account, amount);
}
/**
* @dev 内部迁移函数
* @param account 账户地址
* @param amount 迁移数量
*/
function _migrate(address account, uint256 amount) private {
require(account != address(0), "BEP20: 铸造到零地址");
_tokenTransfer(owner(), account, amount, 0, false);
}
/**
* @dev 返回费用等级数量
*/
function feeTiersLength() public view returns (uint256) {
return feeTiers.length;
}
/**
* @dev 更新销毁地址
* @param _newBurnAddress 新的销毁地址
*/
function updateBurnAddress(address _newBurnAddress) external onlyOwner {
_burnAddress = _newBurnAddress;
excludeFromReward(_newBurnAddress);
}
/**
* @dev 提取代币
* @param _token 代币地址
* @param _amount 提取数量
*/
function withdrawToken(address _token, uint256 _amount) public onlyOwner {
ISafemoon(_token).transfer(msg.sender, _amount);
}
/**
* @dev 设置触发收集BNB的代币数量
* @param _numToken 代币数量
*/
function setNumberOfTokenToCollectBNB(uint256 _numToken) public onlyOwner {
numTokensToCollectBNB = _numToken;
}
/**
* @dev 设置触发交换和进化的BNB数量
* @param _numBnb BNB数量
*/
function setNumOfBnbToSwapAndEvolve(uint256 _numBnb) public onlyOwner {
numOfBnbToSwapAndEvolve = _numBnb;
}
/**
* @dev 提取BNB
* @param _amount 提取数量
*/
function withdrawBnb(uint256 _amount) public onlyOwner {
payable(msg.sender).transfer(_amount);
}
/**
* @dev 添加不触发收集BNB的地址列表
* @param _addresses 地址列表
*/
function addListIgnoreCollectBNBOnTransferAddresses(address[] calldata _addresses) external onlyOwner {
uint256 len = _addresses.length;
for (uint256 i = 0; i < len; i++) {
address addr = _addresses[i];
if (listIgnoreCollectBNBAddresses[addr]) continue;
listIgnoreCollectBNBAddresses[addr] = true;
emit AddIgnoreCollectBNBAddress(addr);
}
}
/**
* @dev 移除不触发收集BNB的地址列表
* @param _addresses 地址列表
*/
function removeListIgnoreCollectBNBOnTransferAddresses(address[] calldata _addresses) external onlyOwner {
uint256 len = _addresses.length;
for (uint256 i = 0; i < len; i++) {
address addr = _addresses[i];
if (!listIgnoreCollectBNBAddresses[addr]) continue;
listIgnoreCollectBNBAddresses[addr] = false;
emit RemoveIgnoreCollectBNBAddress(addr);
}
}
/**
* @dev 检查地址是否在不触发收集BNB的白名单中
* @param _addr 检查的地址
*/
function _isInCollectBNBWhitelist(address _addr) private view returns (bool) {
return listIgnoreCollectBNBAddresses[_addr];
}
/**
* @dev 设置桥接销毁地址
* @param _burn 销毁地址
*/
function setBridgeBurnAddress(address _burn) public onlyOwner {
bridgeBurnAddress = _burn;
}
/**
* @dev 设置铸造销毁白名单
* @param _wl 白名单地址
* @param value 是否启用
*/
function setWhitelistMintBurn(address _wl, bool value) public onlyOwner {
whitelistMint[_wl] = value;
}
/**
* @dev 铸造代币
* @param user 接收者地址
* @param amount 铸造数量
*/
function mint(address user, uint256 amount) public whenNotPaused onlyWhitelistMint {
if (msg.sender != owner()) {
require(amount <= _maxTxAmount, "转账金额超过最大限制");
}
_tokenTransfer(bridgeBurnAddress, user, amount, 0, false);
}
/**
* @dev 销毁代币
* @param amount 销毁数量
*/
function burn(uint256 amount) public whenNotPaused onlyWhitelistMint {
if (msg.sender != owner()) {
require(amount <= _maxTxAmount, "转账金额超过最大限制");
}
_tokenTransfer(msg.sender, bridgeBurnAddress, amount, 0, false);
}
/**
* @dev 设置暂停白名单
* @param user 用户地址
* @param value 是否启用
*/
function setWhitelistPause(address user, bool value) public onlyOwner {
whitelistPause[user] = value;
emit WhitelistPause(user, value);
}
}