编译器
0.8.26+commit.8a97fa7a
文件 1 的 13:Address.sol
pragma solidity ^0.8.20;
library Address {
error AddressInsufficientBalance(address account);
error AddressEmptyCode(address target);
error FailedInnerCall();
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success,) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function verifyCallResultFromTarget(address target, bool success, bytes memory returndata)
internal
view
returns (bytes memory)
{
if (!success) {
_revert(returndata);
} else {
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
function _revert(bytes memory returndata) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}
文件 2 的 13:Context.sol
pragma solidity ^0.8.20;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
文件 3 的 13:IERC20.sol
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";
文件 4 的 13:IERC20Burnable.sol
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/interfaces/IERC20.sol";
interface IERC20Burnable is IERC20 {
function burn(uint256 value) external;
}
文件 5 的 13:IERC20Permit.sol
pragma solidity ^0.8.20;
interface IERC20Permit {
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 6 的 13:IHelios.sol
pragma solidity ^0.8.26;
import "@openzeppelin/contracts/interfaces/IERC20.sol";
interface IHelios is IERC20 {
function userBurnTokens(uint256 amount) external;
}
文件 7 的 13:IUniswapV2Router01.sol
pragma solidity >=0.6.2;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB, uint256 liquidity);
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external payable returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETH(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountToken, uint256 amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETHWithPermit(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountToken, uint256 amountETH);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactETHForTokens(uint256 amountOutMin, address[] calldata path, address to, uint256 deadline)
external
payable
returns (uint256[] memory amounts);
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapETHForExactTokens(uint256 amountOut, address[] calldata path, address to, uint256 deadline)
external
payable
returns (uint256[] memory amounts);
function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) external pure returns (uint256 amountB);
function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut)
external
pure
returns (uint256 amountOut);
function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut)
external
pure
returns (uint256 amountIn);
function getAmountsOut(uint256 amountIn, address[] calldata path)
external
view
returns (uint256[] memory amounts);
function getAmountsIn(uint256 amountOut, address[] calldata path)
external
view
returns (uint256[] memory amounts);
}
文件 8 的 13:IUniswapV2Router02.sol
pragma solidity >=0.6.2;
import "./IUniswapV2Router01.sol";
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
}
文件 9 的 13:Ownable.sol
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 10 的 13:Ownable2Step.sol
pragma solidity ^0.8.20;
import {Ownable} from "./Ownable.sol";
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
function acceptOwnership() public virtual {
address sender = _msgSender();
if (pendingOwner() != sender) {
revert OwnableUnauthorizedAccount(sender);
}
_transferOwnership(sender);
}
}
文件 11 的 13:SafeERC20.sol
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
error SafeERC20FailedOperation(address token);
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}
文件 12 的 13:ScaleBuyBurn.sol
pragma solidity ^0.8.26;
import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable2Step.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "./interfaces/IERC20Burnable.sol";
import "./interfaces/IHelios.sol";
import "./lib/constants.sol";
contract ScaleBuyBurn is Ownable2Step {
using SafeERC20 for *;
uint16 public incentiveFeeBps = 420;
uint256 public capPerSwapE280 = 888_888_888 ether;
uint256 public capPerSwapDragonX = 8_888_888 ether;
uint32 public buyBurnInterval = 15 minutes;
uint256 public lastBuyBurn;
mapping(address account => bool) public whitelisted;
event BuyBurn();
event ContractActivated();
error Prohibited();
error Cooldown();
error NoAllocation();
constructor(address _owner) Ownable(_owner) {
whitelisted[_owner] = true;
}
function buyAndBurn(uint256 minScaleAmount, uint256 minHeliosAmount, uint256 minE280Amount, uint256 deadline) external {
if (!whitelisted[msg.sender]) revert Prohibited();
if (block.timestamp < lastBuyBurn + buyBurnInterval) revert Cooldown();
uint256 _capPerSwapE280 = capPerSwapE280;
lastBuyBurn = block.timestamp;
uint256 e280Balance = IERC20(E280).balanceOf(address(this));
if (e280Balance < _capPerSwapE280) {
e280Balance = _handleDragonXBalanceCheck(e280Balance, minE280Amount, deadline);
}
if (e280Balance == 0) revert NoAllocation();
uint256 amountToSwap = e280Balance > _capPerSwapE280 ? _capPerSwapE280 : e280Balance;
amountToSwap = _processIncentiveFee(amountToSwap);
uint256 heliosAmount = amountToSwap / 10;
uint256 scaleAmount = amountToSwap - heliosAmount;
_swapELMNT(SCALE, scaleAmount, minScaleAmount, deadline);
_swapELMNT(HELIOS, heliosAmount, minHeliosAmount, deadline);
burnTokens();
emit BuyBurn();
}
function burnTokens() public {
IERC20Burnable scale = IERC20Burnable(SCALE);
IHelios helios = IHelios(HELIOS);
uint256 scaleBurnAmount = scale.balanceOf(address(this));
uint256 heliosBurnAmount = helios.balanceOf(address(this));
scale.burn(scaleBurnAmount);
helios.userBurnTokens(heliosBurnAmount);
}
function setIncentiveFee(uint16 bps) external onlyOwner {
if (bps < 30 || bps > 500) revert Prohibited();
incentiveFeeBps = bps;
}
function setBuyBurnInterval(uint32 limit) external onlyOwner {
if (limit == 0) revert Prohibited();
buyBurnInterval = limit;
}
function setCapPerSwapE280(uint256 limit) external onlyOwner {
capPerSwapE280 = limit;
}
function setCapPerSwapDragonX(uint256 limit) external onlyOwner {
capPerSwapDragonX = limit;
}
function setWhitelisted(address[] calldata accounts, bool isWhitelisted) external onlyOwner {
for (uint256 i = 0; i < accounts.length; i++) {
whitelisted[accounts[i]] = isWhitelisted;
}
}
function getBuyBurnParams()
external
view
returns (bool additionalSwap, uint256 e280Amount, uint256 dragonXAmount, uint256 nextAvailable)
{
uint256 e280Balance = IERC20(E280).balanceOf(address(this));
uint256 dragonxBalance = IERC20(DRAGONX).balanceOf(address(this));
additionalSwap = e280Balance < capPerSwapE280 && dragonxBalance > 0;
e280Amount = e280Balance > capPerSwapE280 ? capPerSwapE280 : e280Balance;
if (additionalSwap) dragonXAmount = dragonxBalance > capPerSwapDragonX ? capPerSwapDragonX : dragonxBalance;
nextAvailable = lastBuyBurn + buyBurnInterval;
}
function _handleDragonXBalanceCheck(uint256 currentE280Balance, uint256 minE280Amount, uint256 deadline)
internal
returns (uint256)
{
uint256 dragonxBalance = IERC20(DRAGONX).balanceOf(address(this));
if (dragonxBalance == 0) return currentE280Balance;
uint256 amountToSwap = dragonxBalance > capPerSwapDragonX ? capPerSwapDragonX : dragonxBalance;
uint256 swappedAmount = _swapDragonXforELMNT(amountToSwap, minE280Amount, deadline);
unchecked {
return currentE280Balance + swappedAmount;
}
}
function _processIncentiveFee(uint256 e280Amount) internal returns (uint256) {
uint256 incentiveFee = e280Amount * incentiveFeeBps / BPS_BASE;
IERC20(E280).safeTransfer(msg.sender, incentiveFee);
unchecked {
return e280Amount - incentiveFee;
}
}
function _swapELMNT(address tokenOut, uint256 amountIn, uint256 minAmountOut, uint256 deadline) internal {
IERC20(E280).safeIncreaseAllowance(UNISWAP_V2_ROUTER, amountIn);
address[] memory path = new address[](2);
path[0] = E280;
path[1] = tokenOut;
IUniswapV2Router02(UNISWAP_V2_ROUTER).swapExactTokensForTokensSupportingFeeOnTransferTokens(
amountIn, minAmountOut, path, address(this), deadline
);
}
function _swapDragonXforELMNT(uint256 amountIn, uint256 minAmountOut, uint256 deadline)
internal
returns (uint256)
{
IERC20(DRAGONX).safeIncreaseAllowance(UNISWAP_V2_ROUTER, amountIn);
address[] memory path = new address[](2);
path[0] = DRAGONX;
path[1] = E280;
uint256[] memory amounts = IUniswapV2Router02(UNISWAP_V2_ROUTER).swapExactTokensForTokens(
amountIn, minAmountOut, path, address(this), deadline
);
return amounts[1];
}
}
文件 13 的 13:constants.sol
pragma solidity ^0.8.26;
address constant E280 = 0xe9A53C43a0B58706e67341C4055de861e29Ee943;
address constant DRAGONX = 0x96a5399D07896f757Bd4c6eF56461F58DB951862;
address constant HELIOS = 0x2614f29C39dE46468A921Fd0b41fdd99A01f2EDf;
address constant SCALE = 0xEADeB14bea62B136Ff0D486937aEf9BEe4759c6A;
address constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
uint32 constant BPS_BASE = 100_00;
{
"compilationTarget": {
"contracts/ScaleBuyBurn.sol": "ScaleBuyBurn"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [],
"viaIR": true
}
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"Cooldown","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"NoAllocation","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"Prohibited","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[],"name":"BuyBurn","type":"event"},{"anonymous":false,"inputs":[],"name":"ContractActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burnTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minScaleAmount","type":"uint256"},{"internalType":"uint256","name":"minHeliosAmount","type":"uint256"},{"internalType":"uint256","name":"minE280Amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"buyAndBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buyBurnInterval","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"capPerSwapDragonX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"capPerSwapE280","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBuyBurnParams","outputs":[{"internalType":"bool","name":"additionalSwap","type":"bool"},{"internalType":"uint256","name":"e280Amount","type":"uint256"},{"internalType":"uint256","name":"dragonXAmount","type":"uint256"},{"internalType":"uint256","name":"nextAvailable","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"incentiveFeeBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastBuyBurn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"limit","type":"uint32"}],"name":"setBuyBurnInterval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setCapPerSwapDragonX","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setCapPerSwapE280","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"bps","type":"uint16"}],"name":"setIncentiveFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"bool","name":"isWhitelisted","type":"bool"}],"name":"setWhitelisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"whitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]