文件 1 的 1:ZCubed.sol
pragma solidity 0.8.17;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
interface InterfaceLP {
function sync() external;
}
abstract contract ERC20Detailed is IERC20 {
string private _name;
string private _symbol;
uint8 private _decimals;
constructor(
string memory _tokenName,
string memory _tokenSymbol,
uint8 _tokenDecimals
) {
_name = _tokenName;
_symbol = _tokenSymbol;
_decimals = _tokenDecimals;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
}
interface IDEXRouter {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function swapExactTokensForETHSupportingFeeOnTransferTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external;
function swapExactTokensForTokensSupportingFeeOnTransferTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external;
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);
}
interface IDEXFactory {
function createPair(address tokenA, address tokenB)
external
returns (address pair);
}
contract Ownable {
address private _owner;
event OwnershipRenounced(address indexed previousOwner);
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
constructor() {
_owner = msg.sender;
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(msg.sender == _owner, "Not owner");
_;
}
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(_owner);
_owner = address(0);
}
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0));
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
contract TokenHandler is Ownable {
function sendTokenToOwner(address token) external onlyOwner {
if(IERC20(token).balanceOf(address(this)) > 0){
IERC20(token).transfer(owner(), IERC20(token).balanceOf(address(this)));
}
}
}
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
contract ZCubed is ERC20Detailed, Ownable {
bool public tradingActive = false;
bool public swapEnabled = true;
uint256 public rewardYield = 315920639267394;
uint256 public rewardYieldDenominator = 100000000000000000;
uint256 public rebaseFrequency = 1 days / 2;
uint256 public nextRebase;
bool public autoRebase = true;
uint256 public timeBetweenRebaseReduction = 90 days;
uint256 public rebaseReductionAmount = 3;
uint256 public lastReduction;
uint256 public maxTxnAmount;
uint256 public maxWallet;
mapping(address => bool) _isFeeExempt;
address[] public _makerPairs;
mapping (address => bool) public automatedMarketMakerPairs;
uint256 public constant MAX_FEE_RATE = 4;
uint256 public constant MAX_REBASE_FREQUENCY = 43200;
uint256 public constant MIN_REBASE_FREQUENCY = 43200;
uint256 private constant DECIMALS = 18;
uint256 private constant MAX_UINT256 = type(uint256).max;
uint256 private constant INITIAL_FRAGMENTS_SUPPLY = 2_100_000 * 10**DECIMALS;
uint256 private constant TOTAL_GONS = type(uint256).max - (type(uint256).max % INITIAL_FRAGMENTS_SUPPLY);
uint256 private constant MAX_SUPPLY = 21_000_000 * 10**DECIMALS;
event LogRebase(uint256 indexed epoch, uint256 totalSupply);
event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);
event RemovedLimits();
address DEAD = 0x000000000000000000000000000000000000dEaD;
address ZERO = 0x0000000000000000000000000000000000000000;
address public marketingAddress;
address public treasuryAddress;
address public PAIREDTOKEN;
IDEXRouter public immutable router;
address public pair;
TokenHandler public tokenHandler;
mapping(address => uint256) private _holderLastTransferBlock;
bool public transferDelayEnabled = true;
uint256 public liquidityFee = 1;
uint256 public marketingFee = 2;
uint256 public treasuryFee = 1;
uint256 public totalFee = liquidityFee + marketingFee + treasuryFee;
uint256 public feeDenominator = 100;
bool public limitsInEffect = true;
bool inSwap;
modifier swapping() {
inSwap = true;
_;
inSwap = false;
}
uint256 private _totalSupply;
uint256 private _gonsPerFragment;
uint256 private gonSwapThreshold = (TOTAL_GONS / 100000 * 25);
mapping(address => uint256) private _gonBalances;
mapping(address => mapping(address => uint256)) private _allowedFragments;
modifier validRecipient(address to) {
require(to != address(0x0));
_;
}
constructor() ERC20Detailed(block.chainid==1 ? "Z-Cubed" : "ZTEST", block.chainid==1 ? "Z3" : "ZTEST", 18) {
address dexAddress;
address pairedTokenAddress;
if(block.chainid == 1){
dexAddress = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
pairedTokenAddress = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
} else if(block.chainid == 5){
dexAddress = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
pairedTokenAddress = 0x2f3A40A3db8a7e3D09B0adfEfbCe4f6F81927557;
} else if (block.chainid == 97){
dexAddress = 0xD99D1c33F9fC3444f8101754aBC46c52416550D1;
pairedTokenAddress = 0x78867BbEeF44f2326bF8DDd1941a4439382EF2A7;
} else {
revert("Chain not configured");
}
marketingAddress = address(0x77B2aE7647afAa8Eef08572CF7b77803C5aE95d7);
treasuryAddress = address(0x4f013300A0DcE6193388Cd057108eecB9e1054aC);
nextRebase = block.timestamp + rebaseFrequency;
PAIREDTOKEN = pairedTokenAddress;
router = IDEXRouter(dexAddress);
tokenHandler = new TokenHandler();
_allowedFragments[address(this)][address(router)] = ~uint256(0);
_allowedFragments[address(msg.sender)][address(router)] = ~uint256(0);
_allowedFragments[address(this)][address(this)] = ~uint256(0);
_totalSupply = INITIAL_FRAGMENTS_SUPPLY;
_gonBalances[msg.sender] = TOTAL_GONS / 100 * 95;
_gonBalances[treasuryAddress] += TOTAL_GONS - _gonBalances[msg.sender];
_gonsPerFragment = TOTAL_GONS/(_totalSupply);
maxTxnAmount = _totalSupply * 5 / 1000;
maxWallet = _totalSupply * 1 / 100;
_isFeeExempt[address(this)] = true;
_isFeeExempt[address(msg.sender)] = true;
_isFeeExempt[address(dexAddress)] = true;
_isFeeExempt[address(0xdead)] = true;
emit Transfer(address(0x0), msg.sender, balanceOf(msg.sender));
emit Transfer(address(0x0), treasuryAddress, balanceOf(treasuryAddress));
}
function totalSupply() external view override returns (uint256) {
return _totalSupply;
}
function allowance(address owner_, address spender) external view override returns (uint256){
return _allowedFragments[owner_][spender];
}
function balanceOf(address who) public view override returns (uint256) {
return _gonBalances[who]/(_gonsPerFragment);
}
function checkFeeExempt(address _addr) external view returns (bool) {
return _isFeeExempt[_addr];
}
function checkSwapThreshold() external view returns (uint256) {
return gonSwapThreshold/(_gonsPerFragment);
}
function shouldRebase() public view returns (bool) {
return nextRebase <= block.timestamp;
}
function shouldTakeFee(address from, address to) internal view returns (bool) {
if(_isFeeExempt[from] || _isFeeExempt[to]){
return false;
} else {
return (automatedMarketMakerPairs[from] || automatedMarketMakerPairs[to]);
}
}
function shouldSwapBack() internal view returns (bool) {
return
!inSwap &&
swapEnabled &&
totalFee > 0 &&
_gonBalances[address(this)] >= gonSwapThreshold;
}
function manualSync() public {
for(uint i = 0; i < _makerPairs.length; i++){
try InterfaceLP(_makerPairs[i]).sync(){} catch {}
}
}
function transfer(address to, uint256 value) external override validRecipient(to) returns (bool){
_transferFrom(msg.sender, to, value);
return true;
}
function removeLimits() external onlyOwner {
limitsInEffect = false;
emit RemovedLimits();
}
function alterToken(address newToken) external onlyOwner {
require(newToken != address(0), "Zero address");
require(!tradingActive, "trading already active");
pair = IDEXFactory(router.factory()).createPair(address(this), newToken);
_allowedFragments[address(this)][pair] = ~uint256(0);
setAutomatedMarketMakerPair(pair, true);
PAIREDTOKEN = newToken;
}
function _transferFrom(address sender, address recipient, uint256 amount) internal returns (bool) {
if(!tradingActive){
require(_isFeeExempt[sender] || _isFeeExempt[recipient], "Trading is paused");
}
if(limitsInEffect){
if (!_isFeeExempt[sender] && !_isFeeExempt[recipient]){
if (transferDelayEnabled){
if (recipient != address(router) && !automatedMarketMakerPairs[recipient]){
require(_holderLastTransferBlock[tx.origin] + 2 < block.number && _holderLastTransferBlock[recipient] + 2 < block.number, "_transfer:: Transfer Delay enabled. Try again later.");
_holderLastTransferBlock[tx.origin] = block.number;
_holderLastTransferBlock[recipient] = block.number;
}
}
if (automatedMarketMakerPairs[sender]) {
require(amount <= maxTxnAmount, "Buy transfer amount exceeds the max buy.");
}
if (!automatedMarketMakerPairs[recipient]){
require(balanceOf(recipient) + amount <= maxWallet, "Max Wallet Exceeded");
}
}
}
if(!_isFeeExempt[sender] && !_isFeeExempt[recipient] && shouldSwapBack() && !automatedMarketMakerPairs[sender]){
inSwap = true;
swapBack();
inSwap = false;
}
if(autoRebase && !automatedMarketMakerPairs[sender] && !inSwap && shouldRebase() && !_isFeeExempt[recipient] && !_isFeeExempt[sender]){
rebase();
}
uint256 gonAmount = amount*(_gonsPerFragment);
_gonBalances[sender] = _gonBalances[sender]-(gonAmount);
uint256 gonAmountReceived = shouldTakeFee(sender, recipient) ? takeFee(sender, gonAmount) : gonAmount;
_gonBalances[recipient] = _gonBalances[recipient]+(gonAmountReceived);
emit Transfer(sender, recipient, gonAmountReceived/(_gonsPerFragment));
return true;
}
function transferFrom(address from, address to, uint256 value) external override validRecipient(to) returns (bool) {
if (_allowedFragments[from][msg.sender] != MAX_UINT256) {
require(_allowedFragments[from][msg.sender] >= value,"Insufficient Allowance");
_allowedFragments[from][msg.sender] = _allowedFragments[from][msg.sender]-(value);
}
_transferFrom(from, to, value);
return true;
}
function swapBack() public {
uint256 contractBalance = balanceOf(address(this));
if(contractBalance > gonSwapThreshold/(_gonsPerFragment) * 20){
contractBalance = gonSwapThreshold/(_gonsPerFragment) * 20;
}
uint256 tokensForLiquidity = contractBalance * liquidityFee / totalFee;
if(tokensForLiquidity > 0 && contractBalance >= tokensForLiquidity){
_transferFrom(address(this), pair, tokensForLiquidity);
manualSync();
contractBalance -= tokensForLiquidity;
tokensForLiquidity = 0;
}
swapTokensForPAIREDTOKEN(contractBalance);
tokenHandler.sendTokenToOwner(address(PAIREDTOKEN));
uint256 pairedTokenBalance = IERC20(PAIREDTOKEN).balanceOf(address(this));
uint256 pairedTokenForTreasury = pairedTokenBalance * treasuryFee / (treasuryFee + marketingFee);
if(pairedTokenForTreasury > 0){
IERC20(PAIREDTOKEN).transfer(treasuryAddress, pairedTokenForTreasury);
}
if(IERC20(PAIREDTOKEN).balanceOf(address(this)) > 0){
IERC20(PAIREDTOKEN).transfer(marketingAddress, IERC20(PAIREDTOKEN).balanceOf(address(this)));
}
}
function swapTokensForPAIREDTOKEN(uint256 tokenAmount) private {
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = address(PAIREDTOKEN);
router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
tokenAmount,
0,
path,
address(tokenHandler),
block.timestamp
);
}
function takeFee(address sender, uint256 gonAmount) internal returns (uint256){
uint256 feeAmount = gonAmount*(totalFee)/(feeDenominator);
_gonBalances[address(this)] = _gonBalances[address(this)]+(feeAmount);
emit Transfer(sender, address(this), feeAmount/(_gonsPerFragment));
return gonAmount-(feeAmount);
}
function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool){
uint256 oldValue = _allowedFragments[msg.sender][spender];
if (subtractedValue >= oldValue) {
_allowedFragments[msg.sender][spender] = 0;
} else {
_allowedFragments[msg.sender][spender] = oldValue-(
subtractedValue
);
}
emit Approval(
msg.sender,
spender,
_allowedFragments[msg.sender][spender]
);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) external returns (bool){
_allowedFragments[msg.sender][spender] = _allowedFragments[msg.sender][
spender
]+(addedValue);
emit Approval(
msg.sender,
spender,
_allowedFragments[msg.sender][spender]
);
return true;
}
function approve(address spender, uint256 value) public override returns (bool){
_allowedFragments[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
function getSupplyDeltaOnNextRebase() external view returns (uint256){
return (_totalSupply*rewardYield)/rewardYieldDenominator;
}
function rebase() private returns (uint256) {
uint256 epoch = block.timestamp;
if(lastReduction + timeBetweenRebaseReduction <= block.timestamp){
rewardYield -= rewardYield * rebaseReductionAmount / 10;
lastReduction = block.timestamp;
}
uint256 supplyDelta = (_totalSupply*rewardYield)/rewardYieldDenominator;
nextRebase = nextRebase + rebaseFrequency;
if (supplyDelta == 0) {
emit LogRebase(epoch, _totalSupply);
return _totalSupply;
}
_totalSupply = _totalSupply+supplyDelta;
if (_totalSupply > MAX_SUPPLY) {
_totalSupply = MAX_SUPPLY;
}
_gonsPerFragment = TOTAL_GONS/(_totalSupply);
manualSync();
emit LogRebase(epoch, _totalSupply);
return _totalSupply;
}
function manualRebase() external {
require(!inSwap, "Try again");
require(shouldRebase(), "Not in time");
rebase();
}
function setAutomatedMarketMakerPair(address _pair, bool _value) public onlyOwner {
require(automatedMarketMakerPairs[_pair] != _value, "Value already set");
automatedMarketMakerPairs[_pair] = _value;
if(_value){
_makerPairs.push(_pair);
} else {
require(_makerPairs.length > 1, "Required 1 pair");
for (uint256 i = 0; i < _makerPairs.length; i++) {
if (_makerPairs[i] == _pair) {
_makerPairs[i] = _makerPairs[_makerPairs.length - 1];
_makerPairs.pop();
break;
}
}
}
emit SetAutomatedMarketMakerPair(_pair, _value);
}
function enableTrading() external onlyOwner {
require(!tradingActive, "Trading already active");
tradingActive = true;
nextRebase = block.timestamp + rebaseFrequency;
lastReduction = block.timestamp;
}
function disableTransferDelay() external onlyOwner {
transferDelayEnabled = false;
}
function setFeeExempt(address _addr, bool _value) external onlyOwner {
require(_isFeeExempt[_addr] != _value, "Not changed");
_isFeeExempt[_addr] = _value;
}
function setFeeReceivers(address _marketingReceiver, address _treasuryReceiver) external onlyOwner {
require(_marketingReceiver != address(0) && _treasuryReceiver != address(0), "zero address");
treasuryAddress = _treasuryReceiver;
marketingAddress = _marketingReceiver;
}
function setFees(uint256 _liquidityFee, uint256 _marketingFee, uint256 _treasuryFee) external onlyOwner {
liquidityFee = _liquidityFee;
marketingFee = _marketingFee;
treasuryFee = _treasuryFee;
totalFee = liquidityFee + marketingFee + treasuryFee;
require(totalFee <= MAX_FEE_RATE, "Fees set too high");
}
function rescueToken(address tokenAddress, uint256 tokens, address destination) external onlyOwner returns (bool success){
require(tokenAddress != address(this), "Cannot take native tokens");
return ERC20Detailed(tokenAddress).transfer(destination, tokens);
}
function setNextRebase(uint256 _nextRebase) external onlyOwner {
require(_nextRebase > block.timestamp, "Must set rebase in the future");
nextRebase = _nextRebase;
}
}