编译器
0.8.24+commit.e11b9ed9
文件 1 的 23: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 的 23: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 的 23:ERC20.sol
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
mapping(address account => uint256) private _balances;
mapping(address account => mapping(address spender => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual returns (string memory) {
return _name;
}
function symbol() public view virtual returns (string memory) {
return _symbol;
}
function decimals() public view virtual returns (uint8) {
return 18;
}
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
function allowance(address owner, address spender) public view virtual returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, value);
return true;
}
function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, value);
_transfer(from, to, value);
return true;
}
function _transfer(address from, address to, uint256 value) internal {
if (from == address(0)) {
revert ERC20InvalidSender(address(0));
}
if (to == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(from, to, value);
}
function _update(address from, address to, uint256 value) internal virtual {
if (from == address(0)) {
_totalSupply += value;
} else {
uint256 fromBalance = _balances[from];
if (fromBalance < value) {
revert ERC20InsufficientBalance(from, fromBalance, value);
}
unchecked {
_balances[from] = fromBalance - value;
}
}
if (to == address(0)) {
unchecked {
_totalSupply -= value;
}
} else {
unchecked {
_balances[to] += value;
}
}
emit Transfer(from, to, value);
}
function _mint(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(address(0), account, value);
}
function _burn(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
_update(account, address(0), value);
}
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}
function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
if (owner == address(0)) {
revert ERC20InvalidApprover(address(0));
}
if (spender == address(0)) {
revert ERC20InvalidSpender(address(0));
}
_allowances[owner][spender] = value;
if (emitEvent) {
emit Approval(owner, spender, value);
}
}
function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
if (currentAllowance < value) {
revert ERC20InsufficientAllowance(spender, currentAllowance, value);
}
unchecked {
_approve(owner, spender, currentAllowance - value, false);
}
}
}
}
文件 4 的 23:FullMath.sol
pragma solidity ^0.8.0;
library FullMath {
function mulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(a, b, not(0))
prod0 := mul(a, b)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
require(denominator > 0);
assembly {
result := div(prod0, denominator)
}
return result;
}
require(denominator > prod1);
uint256 remainder;
assembly {
remainder := mulmod(a, b, denominator)
}
assembly {
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = (0 - denominator) & denominator;
assembly {
denominator := div(denominator, twos)
}
assembly {
prod0 := div(prod0, twos)
}
assembly {
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inv = (3 * denominator) ^ 2;
inv *= 2 - denominator * inv;
inv *= 2 - denominator * inv;
inv *= 2 - denominator * inv;
inv *= 2 - denominator * inv;
inv *= 2 - denominator * inv;
inv *= 2 - denominator * inv;
result = prod0 * inv;
return result;
}
}
function mulDivRoundingUp(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
result = mulDiv(a, b, denominator);
if (mulmod(a, b, denominator) > 0) {
require(result < type(uint256).max);
result++;
}
}
}
}
文件 5 的 23:IDragonX.sol
pragma solidity ^0.8.24;
interface IDragonX {
function updateVault() external;
}
文件 6 的 23:IERC165.sol
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";
文件 7 的 23:IERC20.sol
pragma solidity ^0.8.20;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
文件 8 的 23:IERC20Metadata.sol
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 9 的 23: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);
}
文件 10 的 23:ISwapRouter.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
import "@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol";
interface ISwapRouter is IUniswapV3SwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}
文件 11 的 23:IUniswapV2Factory.sol
pragma solidity >=0.5.0;
interface IUniswapV2Factory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint256);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint256) external view returns (address pair);
function allPairsLength() external view returns (uint256);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
}
文件 12 的 23:IUniswapV2Pair.sol
pragma solidity >=0.5.0;
interface IUniswapV2Pair {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint256);
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
external;
event Mint(address indexed sender, uint256 amount0, uint256 amount1);
event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to);
event Swap(
address indexed sender,
uint256 amount0In,
uint256 amount1In,
uint256 amount0Out,
uint256 amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint256);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint256);
function price1CumulativeLast() external view returns (uint256);
function kLast() external view returns (uint256);
function mint(address to) external returns (uint256 liquidity);
function burn(address to) external returns (uint256 amount0, uint256 amount1);
function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
文件 13 的 23: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);
}
文件 14 的 23: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;
}
文件 15 的 23:IUniswapV3SwapCallback.sol
pragma solidity >=0.5.0;
interface IUniswapV3SwapCallback {
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external;
}
文件 16 的 23:IWETH9.sol
pragma solidity ^0.8.10;
import "@openzeppelin/contracts/interfaces/IERC20.sol";
interface IWETH9 is IERC20 {
function deposit() external payable;
function withdraw(uint256) external;
}
文件 17 的 23:MerkleProof.sol
pragma solidity ^0.8.20;
library MerkleProof {
error MerkleProofInvalidMultiproof();
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
return processProofCalldata(proof, leaf) == root;
}
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
function multiProofVerify(bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves)
internal
pure
returns (bool)
{
return processMultiProof(proof, proofFlags, leaves) == root;
}
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves) == root;
}
function processMultiProof(bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves)
internal
pure
returns (bytes32 merkleRoot)
{
uint256 leavesLen = leaves.length;
uint256 proofLen = proof.length;
uint256 totalHashes = proofFlags.length;
if (leavesLen + proofLen != totalHashes + 1) {
revert MerkleProofInvalidMultiproof();
}
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b =
proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
if (proofPos != proofLen) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
function processMultiProofCalldata(bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves)
internal
pure
returns (bytes32 merkleRoot)
{
uint256 leavesLen = leaves.length;
uint256 proofLen = proof.length;
uint256 totalHashes = proofFlags.length;
if (leavesLen + proofLen != totalHashes + 1) {
revert MerkleProofInvalidMultiproof();
}
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b =
proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
if (proofPos != proofLen) {
revert MerkleProofInvalidMultiproof();
}
unchecked {
return hashes[totalHashes - 1];
}
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
}
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}
文件 18 的 23: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);
}
}
文件 19 的 23: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);
}
}
文件 20 的 23:SCALE.sol
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC165.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable2Step.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol";
import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import "./interfaces/IWETH9.sol";
import "./interfaces/IDragonX.sol";
import "./lib/FullMath.sol";
import "./lib/constants.sol";
contract SCALE is ERC20, Ownable2Step, IERC165 {
using SafeERC20 for IERC20;
address public heliosVault;
address public dragonXVault;
address public devWallet;
address public marketingWallet;
address public shedContract;
address public bdxBuyBurnAddress;
uint16 public incentiveFee = 30;
uint16 public reflectionFee = 150;
uint256 public totalBurned;
uint256 public minReserveDistribution = 1_000_000 * 10 ** 9;
uint256 public maxReserveDistribution = 500_000_000 * 10 ** 9;
uint256 public titanLpPool;
uint256 public totalLpPoolUsed;
uint256 public scaleLpPool;
uint256 public bdxBuyBurnPool;
uint256 public buyBurnDragonXAllocation;
uint8 public totalLPsCreated;
uint8 public buyBurnPurchases;
uint8 public purchasesRequired = 10;
uint256 public presaleEnd;
bool public presaleFinalized;
bool public lpPurchaseFinished;
bool public tradingEnabled;
mapping(address token => uint256) public tokenPool;
mapping(address token => uint8) public lpPurchases;
mapping(address token => uint8) public tokenLpPercent;
uint256 private _totalMinted;
bytes32 private _merkleRoot;
mapping(address => uint256) private _tOwned;
mapping(address => uint256) private _rOwned;
mapping(address => bool) private _isExcludedFromReflections;
address[] private _excluded;
uint256 private _tTotal = 100 * 10 ** 12 * 10 ** 9;
uint256 private _rTotal = (MAX_VALUE - (MAX_VALUE % _tTotal));
error ZeroInput();
error ZeroAddress();
error PresaleInactive();
error PresaleActive();
error MaxSupply();
error TradingDisabled();
error Prohibited();
error DuplicateToken();
error IncorrectPercentage();
error IncorrectTokenNumber();
error IncorrectBonus();
error InsuffucientBalance();
error ExcludedAddress();
event PresaleStarted();
event TradingEnabled();
event ReserveDistributed();
modifier onlyPresale() {
if (!isPresaleActive()) revert PresaleInactive();
_;
}
constructor(
address _owner,
address _devWallet,
address _marketingWallet,
address _heliosVault,
address _dragonxVault,
address _bdxBuyBurnAddress,
address[] memory _ecosystemTokens,
uint8[] memory _lpPercentages
) ERC20("SCALE", "SCALE") Ownable(_owner) {
if (_ecosystemTokens.length != NUM_ECOSYSTEM_TOKENS) revert IncorrectTokenNumber();
if (_lpPercentages.length != NUM_ECOSYSTEM_TOKENS) revert IncorrectTokenNumber();
if (_owner == address(0)) revert ZeroAddress();
if (_devWallet == address(0)) revert ZeroAddress();
if (_marketingWallet == address(0)) revert ZeroAddress();
if (_heliosVault == address(0)) revert ZeroAddress();
if (_dragonxVault == address(0)) revert ZeroAddress();
if (_bdxBuyBurnAddress == address(0)) revert ZeroAddress();
_rOwned[address(this)] = _rTotal;
devWallet = _devWallet;
marketingWallet = _marketingWallet;
heliosVault = _heliosVault;
dragonXVault = _dragonxVault;
bdxBuyBurnAddress = _bdxBuyBurnAddress;
uint8 totalPercentage;
for (uint256 i = 0; i < _ecosystemTokens.length; i++) {
address token = _ecosystemTokens[i];
uint8 allocation = _lpPercentages[i];
if (token == address(0)) revert ZeroAddress();
if (allocation == 0) revert ZeroInput();
if (tokenLpPercent[token] != 0) revert DuplicateToken();
tokenLpPercent[token] = allocation;
totalPercentage += allocation;
}
if (totalPercentage != 100) revert IncorrectPercentage();
}
function mintWithTitanX(uint256 amount, uint16 bonus, bytes32[] memory merkleProof) external onlyPresale {
if (amount == 0) revert ZeroInput();
IERC20(TITANX).safeTransferFrom(msg.sender, address(this), amount * 10 ** 9);
amount = _processBonus(amount, bonus, merkleProof);
if ((_totalMinted + amount) * 135 / 100 > _tTotal) revert MaxSupply();
_rMint(msg.sender, amount);
}
function mintWithETH(uint256 amount, uint16 bonus, bytes32[] memory merkleProof, uint256 deadline)
external
payable
onlyPresale
{
if (amount == 0) revert ZeroInput();
uint256 titanXAmount = amount * 10 ** 9;
uint256 swappedAmount = _swapETHForTitanX(titanXAmount, deadline);
if (swappedAmount > titanXAmount) IERC20(TITANX).safeTransfer(msg.sender, swappedAmount - titanXAmount);
amount = _processBonus(amount, bonus, merkleProof);
if ((_totalMinted + amount) * 135 / 100 > _tTotal) revert MaxSupply();
_rMint(msg.sender, amount);
}
function burn(uint256 amount) public {
if (!tradingEnabled) revert TradingDisabled();
_rBurn(msg.sender, amount);
}
function reflect(uint256 amount) public {
if (!tradingEnabled) revert TradingDisabled();
address sender = msg.sender;
if (_isExcludedFromReflections[sender]) revert ExcludedAddress();
uint256 rAmount = amount * _getRate();
_balanceCheck(sender, rAmount, amount);
_rOwned[sender] -= rAmount;
_rTotal -= rAmount;
}
function distributeReserve(uint256 minDragonXAmount, uint256 deadline) external {
if (!tradingEnabled) revert TradingDisabled();
uint256 balance = balanceOf(address(this));
if (balance < minReserveDistribution) revert InsuffucientBalance();
uint256 distribution = balance > maxReserveDistribution ? maxReserveDistribution : balance;
distribution = _processIncentiveFee(msg.sender, distribution);
uint256 buyBurnShare = distribution / 2;
_swapScaleToDragonX(buyBurnShare, minDragonXAmount, deadline);
uint256 quarter = distribution / 4;
uint256 rTransferAmount = reflectionFromToken(quarter);
_rOwned[address(this)] -= rTransferAmount;
_rOwned[marketingWallet] += rTransferAmount;
if (_isExcludedFromReflections[marketingWallet]) _tOwned[marketingWallet] += quarter;
_rBurn(address(this), quarter);
emit ReserveDistributed();
}
function startPresale() external onlyOwner {
if (presaleEnd != 0) revert Prohibited();
if (_merkleRoot == bytes32(0)) revert IncorrectBonus();
unchecked {
presaleEnd = block.timestamp + PRESALE_LENGTH;
}
emit PresaleStarted();
}
function finalizePresale() external onlyOwner {
if (presaleEnd == 0) revert PresaleInactive();
if (isPresaleActive()) revert PresaleActive();
if (shedContract == address(0)) revert ZeroAddress();
if (presaleFinalized) revert Prohibited();
_distributeTokens();
uint256 tBurn = _tTotal - _totalMinted - scaleLpPool;
uint256 rBurn = tBurn * _getRate();
_rOwned[address(this)] -= rBurn;
_rTotal -= rBurn;
_tTotal = _totalMinted + scaleLpPool;
presaleFinalized = true;
emit Transfer(address(0), address(this), scaleLpPool);
}
function purchaseTokenForLP(address token, uint256 minAmountOut, uint256 deadline) external onlyOwner {
if (!presaleFinalized) revert PresaleActive();
if (lpPurchaseFinished) revert Prohibited();
uint256 requiredAmount = token == BDX_ADDRESS ? purchasesRequired : 1;
if (lpPurchases[token] == requiredAmount) revert Prohibited();
uint256 allocation = tokenLpPercent[token];
if (allocation == 0) revert Prohibited();
uint256 amountToSwap = FullMath.mulDiv(titanLpPool, allocation, 100 * requiredAmount);
totalLpPoolUsed += amountToSwap;
uint256 swappedAmount = _swapTitanXToToken(token, amountToSwap, minAmountOut, deadline);
unchecked {
tokenPool[token] += swappedAmount;
lpPurchases[token]++;
if (totalLpPoolUsed >= titanLpPool - NUM_ECOSYSTEM_TOKENS - purchasesRequired) lpPurchaseFinished = true;
}
}
function purchaseDragonXForBuyBurn(uint256 minAmountOut, uint256 deadline) external onlyOwner {
if (!presaleFinalized) revert PresaleActive();
if (buyBurnPurchases == purchasesRequired) revert Prohibited();
uint256 amountToSwap = bdxBuyBurnPool / purchasesRequired;
uint256 swappedAmount = _swapTitanXToToken(DRAGONX_ADDRESS, amountToSwap, minAmountOut, deadline);
unchecked {
buyBurnDragonXAllocation += swappedAmount;
buyBurnPurchases++;
}
if (buyBurnPurchases == purchasesRequired) {
IERC20(DRAGONX_ADDRESS).safeTransfer(bdxBuyBurnAddress, buyBurnDragonXAllocation);
}
}
function deployLiquidityPool(address tokenAddress) external onlyOwner {
if (!lpPurchaseFinished) revert Prohibited();
uint256 tokenAmount = tokenPool[tokenAddress];
if (tokenAmount == 0) revert Prohibited();
uint256 scaleAllocation = FullMath.mulDiv(scaleLpPool, tokenLpPercent[tokenAddress], 100);
_addLiquidity(tokenAddress, tokenAmount, scaleAllocation);
tokenPool[tokenAddress] = 0;
unchecked {
totalLPsCreated++;
}
if (totalLPsCreated == NUM_ECOSYSTEM_TOKENS) _enableTrading();
}
function claimDust() external onlyOwner {
if (!tradingEnabled || buyBurnPurchases != purchasesRequired) revert Prohibited();
IERC20 titanX = IERC20(TITANX);
titanX.safeTransfer(msg.sender, titanX.balanceOf(address(this)));
}
function excludeAccountFromReflections(address account) public onlyOwner {
if (_isExcludedFromReflections[account]) revert ExcludedAddress();
if (_excluded.length == 22) revert Prohibited();
if (account == address(this)) revert Prohibited();
if (_rOwned[account] > 0) {
_tOwned[account] = tokenFromReflection(_rOwned[account]);
}
_isExcludedFromReflections[account] = true;
_excluded.push(account);
}
function includeAccountToReflections(address account) public onlyOwner {
if (!_isExcludedFromReflections[account]) revert ExcludedAddress();
uint256 difference = _rOwned[account] - (_getRate() * _tOwned[account]);
for (uint256 i = 0; i < _excluded.length; i++) {
if (_excluded[i] == account) {
_excluded[i] = _excluded[_excluded.length - 1];
_tOwned[account] = 0;
_rOwned[account] -= difference;
_rTotal -= difference;
_isExcludedFromReflections[account] = false;
_excluded.pop();
break;
}
}
}
function setPurchasesRequired(uint8 amount) external onlyOwner {
if (amount == 0) revert ZeroInput();
if (amount > 50) revert Prohibited();
if (presaleFinalized) revert Prohibited();
purchasesRequired = amount;
}
function setDragonXVault(address _address) external onlyOwner {
if (_address == address(0)) revert ZeroAddress();
dragonXVault = _address;
}
function setHeliosVault(address _address) external onlyOwner {
if (_address == address(0)) revert ZeroAddress();
heliosVault = _address;
}
function setDevWallet(address _address) external onlyOwner {
if (_address == address(0)) revert ZeroAddress();
devWallet = _address;
}
function setMarketingWallet(address _address) external onlyOwner {
if (_address == address(0)) revert ZeroAddress();
marketingWallet = _address;
}
function setSHED(address _address) external onlyOwner {
if (_address == address(0)) revert ZeroAddress();
shedContract = _address;
}
function setBDXBuyBurn(address _address) external onlyOwner {
if (_address == address(0)) revert ZeroAddress();
bdxBuyBurnAddress = _address;
}
function setMerkleRoot(bytes32 root) external onlyOwner {
if (root == bytes32(0)) revert ZeroInput();
_merkleRoot = root;
}
function setReflectionFee(uint16 bps) external onlyOwner {
if (bps != 150 && bps != 300 && bps != 450 && bps != 600) revert Prohibited();
reflectionFee = bps;
}
function setIncentiveFee(uint16 bps) external onlyOwner {
if (bps < 30 || bps > 500) revert Prohibited();
incentiveFee = bps;
}
function setMinReserveDistribution(uint256 limit) external onlyOwner {
if (limit < 100 || limit > maxReserveDistribution) revert Prohibited();
minReserveDistribution = limit;
}
function setMaxReserveDistribution(uint256 limit) external onlyOwner {
if (limit < minReserveDistribution || limit > _tTotal) revert Prohibited();
maxReserveDistribution = limit;
}
function isPresaleActive() public view returns (bool) {
return presaleEnd > block.timestamp;
}
function decimals() public pure override returns (uint8) {
return 9;
}
function totalSupply() public view override returns (uint256) {
if (!presaleFinalized) return _totalMinted;
return _tTotal;
}
function balanceOf(address account) public view override returns (uint256) {
if (!presaleFinalized && account == address(this)) return 0;
if (_isExcludedFromReflections[account]) return _tOwned[account];
return tokenFromReflection(_rOwned[account]);
}
function isExcluded(address account) public view returns (bool) {
return _isExcludedFromReflections[account];
}
function reflectionFromToken(uint256 tAmount) public view returns (uint256) {
if (tAmount > _tTotal) revert MaxSupply();
uint256 rAmount = tAmount * _getRate();
return rAmount;
}
function tokenFromReflection(uint256 rAmount) public view returns (uint256) {
if (rAmount > _rTotal) revert MaxSupply();
return rAmount / _getRate();
}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC20).interfaceId || interfaceId == type(IERC165).interfaceId;
}
function _processBonus(uint256 amount, uint16 bonus, bytes32[] memory merkleProof)
internal
view
returns (uint256)
{
if (bonus > 0) {
bytes32 leaf = keccak256(abi.encodePacked(msg.sender, bonus));
if (!MerkleProof.verify(merkleProof, _merkleRoot, leaf)) revert IncorrectBonus();
uint256 bonusAmount = amount * bonus / 10000;
amount += bonusAmount;
}
return amount;
}
function _processIncentiveFee(address receiver, uint256 amount) internal returns (uint256) {
uint256 rValue = reflectionFromToken(amount);
uint256 rIncentive = FullMath.mulDiv(rValue, incentiveFee, 10000);
uint256 tIncentive = FullMath.mulDiv(amount, incentiveFee, 10000);
_rOwned[address(this)] -= rIncentive;
_rOwned[receiver] += rIncentive;
if (_isExcludedFromReflections[receiver]) _tOwned[receiver] += tIncentive;
return amount - tIncentive;
}
function _distributeTokens() internal {
IERC20 titanX = IERC20(TITANX);
uint256 availableTitanX = titanX.balanceOf(address(this));
titanLpPool = availableTitanX * LP_POOL_PERCENT / 100;
scaleLpPool = titanLpPool / 10 ** 9;
bdxBuyBurnPool = availableTitanX * BDX_BUY_BURN_PERCENT / 100;
uint256 dragonVaultAmount = availableTitanX * DRAGONX_VAULT_PERCENT / 100;
uint256 heliosVaultAmount = availableTitanX * HELIOS_VAULT_PERCENT / 100;
uint256 devAmount = availableTitanX * DEV_PERCENT / 100;
uint256 genesisAmount = availableTitanX * GENESIS_PERCENT / 100;
uint256 shedAmount = availableTitanX - titanLpPool - bdxBuyBurnPool - dragonVaultAmount - heliosVaultAmount
- devAmount - genesisAmount;
titanX.safeTransfer(dragonXVault, dragonVaultAmount);
titanX.safeTransfer(heliosVault, heliosVaultAmount);
titanX.safeTransfer(devWallet, devAmount);
titanX.safeTransfer(owner(), genesisAmount);
titanX.safeTransfer(shedContract, shedAmount);
IDragonX(dragonXVault).updateVault();
}
function _addLiquidity(address tokenAddress, uint256 tokenAmount, uint256 scaleAmount) internal {
(uint256 pairBalance, address pairAddress) = _checkPoolValidity(tokenAddress);
if (pairBalance > 0) _fixPool(pairAddress, tokenAmount, scaleAmount, pairBalance);
if (tokenAddress == BDX_ADDRESS) {
if (pairAddress == address(0)) {
pairAddress = IUniswapV2Factory(UNISWAP_V2_FACTORY).createPair(address(this), tokenAddress);
}
excludeAccountFromReflections(pairAddress);
}
if (pairBalance > 0) {
_update(address(this), pairAddress, scaleAmount);
IERC20(tokenAddress).transfer(pairAddress, tokenAmount);
IUniswapV2Pair(pairAddress).mint(address(0));
} else {
IERC20(address(this)).safeIncreaseAllowance(UNISWAP_V2_ROUTER, scaleAmount);
IERC20(tokenAddress).safeIncreaseAllowance(UNISWAP_V2_ROUTER, tokenAmount);
IUniswapV2Router02(UNISWAP_V2_ROUTER).addLiquidity(
address(this),
tokenAddress,
scaleAmount,
tokenAmount,
scaleAmount,
tokenAmount,
address(0),
block.timestamp
);
}
}
function _checkPoolValidity(address target) internal returns (uint256, address) {
address pairAddress = IUniswapV2Factory(UNISWAP_V2_FACTORY).getPair(address(this), target);
if (pairAddress == address(0)) return (0, pairAddress);
IUniswapV2Pair pair = IUniswapV2Pair(pairAddress);
pair.skim(owner());
(uint112 reserve0, uint112 reserve1,) = pair.getReserves();
if (reserve0 != 0) return (reserve0, pairAddress);
if (reserve1 != 0) return (reserve1, pairAddress);
return (0, pairAddress);
}
function _fixPool(address pairAddress, uint256 tokenAmount, uint256 scaleAmount, uint256 currentBalance) internal {
uint256 requiredScale = currentBalance * scaleAmount / tokenAmount;
if (requiredScale == 0) requiredScale = 1;
uint256 rAmount = requiredScale * _getRate();
_rOwned[pairAddress] += rAmount;
if (_isExcludedFromReflections[pairAddress]) _tOwned[pairAddress] += requiredScale;
_rTotal += rAmount;
_tTotal += requiredScale;
emit Transfer(address(0), pairAddress, requiredScale);
IUniswapV2Pair(pairAddress).sync();
}
function _enableTrading() internal {
tradingEnabled = true;
emit TradingEnabled();
}
function _swapETHForTitanX(uint256 minAmountOut, uint256 deadline) internal returns (uint256) {
IWETH9(WETH9).deposit{value: msg.value}();
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: WETH9,
tokenOut: TITANX,
fee: POOL_FEE_1PERCENT,
recipient: address(this),
deadline: deadline,
amountIn: msg.value,
amountOutMinimum: minAmountOut,
sqrtPriceLimitX96: 0
});
IERC20(WETH9).safeIncreaseAllowance(UNISWAP_V3_ROUTER, msg.value);
uint256 amountOut = ISwapRouter(UNISWAP_V3_ROUTER).exactInputSingle(params);
return amountOut;
}
function _swapScaleToDragonX(uint256 amountIn, uint256 minAmountOut, uint256 deadline) internal {
IERC20(address(this)).safeIncreaseAllowance(UNISWAP_V2_ROUTER, amountIn);
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = DRAGONX_ADDRESS;
IUniswapV2Router02(UNISWAP_V2_ROUTER).swapExactTokensForTokensSupportingFeeOnTransferTokens(
amountIn, minAmountOut, path, bdxBuyBurnAddress, deadline
);
}
function _swapTitanXToToken(address outputToken, uint256 amount, uint256 minAmountOut, uint256 deadline)
internal
returns (uint256)
{
if (outputToken == DRAGONX_ADDRESS) return _swapUniswapV3Pool(outputToken, amount, minAmountOut, deadline);
if (outputToken == E280_ADDRESS) return _swapUniswapV2Pool(outputToken, amount, minAmountOut, deadline);
return _swapMultihop(outputToken, DRAGONX_ADDRESS, amount, minAmountOut, deadline);
}
function _swapUniswapV3Pool(address outputToken, uint256 amountIn, uint256 minAmountOut, uint256 deadline)
internal
returns (uint256)
{
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: TITANX,
tokenOut: outputToken,
fee: POOL_FEE_1PERCENT,
recipient: address(this),
deadline: deadline,
amountIn: amountIn,
amountOutMinimum: minAmountOut,
sqrtPriceLimitX96: 0
});
IERC20(TITANX).safeIncreaseAllowance(UNISWAP_V3_ROUTER, amountIn);
uint256 amountOut = ISwapRouter(UNISWAP_V3_ROUTER).exactInputSingle(params);
return amountOut;
}
function _swapUniswapV2Pool(address outputToken, uint256 amountIn, uint256 minAmountOut, uint256 deadline)
internal
returns (uint256)
{
IERC20(TITANX).safeIncreaseAllowance(UNISWAP_V2_ROUTER, amountIn);
uint256 previous = IERC20(outputToken).balanceOf(address(this));
address[] memory path = new address[](2);
path[0] = TITANX;
path[1] = outputToken;
IUniswapV2Router02(UNISWAP_V2_ROUTER).swapExactTokensForTokensSupportingFeeOnTransferTokens(
amountIn, minAmountOut, path, address(this), deadline
);
return IERC20(outputToken).balanceOf(address(this)) - previous;
}
function _swapMultihop(
address outputToken,
address midToken,
uint256 amountIn,
uint256 minAmountOut,
uint256 deadline
) internal returns (uint256) {
bytes memory path = abi.encodePacked(TITANX, POOL_FEE_1PERCENT, midToken, POOL_FEE_1PERCENT, outputToken);
ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({
path: path,
recipient: address(this),
deadline: deadline,
amountIn: amountIn,
amountOutMinimum: minAmountOut
});
IERC20(TITANX).safeIncreaseAllowance(UNISWAP_V3_ROUTER, amountIn);
uint256 amoutOut = ISwapRouter(UNISWAP_V3_ROUTER).exactInput(params);
return amoutOut;
}
function _rMint(address account, uint256 tAmount) internal {
uint256 rAmount = tAmount * _getRate();
_rOwned[address(this)] -= rAmount;
_rOwned[msg.sender] += rAmount;
if (_isExcludedFromReflections[account]) _tOwned[msg.sender] += tAmount;
_totalMinted += tAmount;
emit Transfer(address(0), account, tAmount);
}
function _rBurn(address account, uint256 tAmount) internal {
uint256 rBurn = tAmount * _getRate();
_balanceCheck(account, rBurn, tAmount);
_rOwned[account] -= rBurn;
if (_isExcludedFromReflections[account]) _tOwned[account] -= tAmount;
_rTotal -= rBurn;
_tTotal -= tAmount;
totalBurned += tAmount;
emit Transfer(account, address(0), tAmount);
}
function _update(address from, address to, uint256 value) internal override {
if (tradingEnabled) {
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 rReserve, uint256 tTransferAmount) =
_getValues(value);
_balanceCheck(from, rAmount, value);
_rOwned[from] -= rAmount;
if (_isExcludedFromReflections[from]) _tOwned[from] -= value;
_rOwned[to] += rTransferAmount;
if (_isExcludedFromReflections[to]) _tOwned[to] += tTransferAmount;
_rOwned[address(this)] += rReserve;
_reflectFee(rFee);
emit Transfer(from, to, tTransferAmount);
} else {
if (from != address(this)) revert TradingDisabled();
uint256 rValue = value * _getRate();
_rOwned[from] -= rValue;
_rOwned[to] += rValue;
if (_isExcludedFromReflections[to]) _tOwned[to] += value;
emit Transfer(from, to, value);
}
}
function _balanceCheck(address from, uint256 rAmount, uint256 value) internal view {
uint256 fromBalance = _rOwned[from];
if (fromBalance < rAmount) {
revert ERC20InsufficientBalance(from, tokenFromReflection(fromBalance), value);
}
}
function _reflectFee(uint256 rFee) private {
_rTotal -= rFee;
}
function _getValues(uint256 tAmount) private view returns (uint256, uint256, uint256, uint256, uint256) {
(uint256 tTransferAmount, uint256 tFee, uint256 tReserve) = _getTValues(tAmount);
uint256 currentRate = _getRate();
(uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 rReserve) =
_getRValues(tAmount, tFee, tReserve, currentRate);
return (rAmount, rTransferAmount, rFee, rReserve, tTransferAmount);
}
function _getTValues(uint256 tAmount) private view returns (uint256, uint256, uint256) {
uint256 tFee = FullMath.mulDivRoundingUp(tAmount, reflectionFee, 10000);
uint256 tReserve = tAmount / 100;
uint256 tTransferAmount = tAmount - tFee - tReserve;
return (tTransferAmount, tFee, tReserve);
}
function _getRValues(uint256 tAmount, uint256 tFee, uint256 tReserve, uint256 currentRate)
private
pure
returns (uint256, uint256, uint256, uint256)
{
uint256 rAmount = tAmount * currentRate;
uint256 rFee = tFee * currentRate;
uint256 rReserve = tReserve * currentRate;
uint256 rTransferAmount = rAmount - rFee - rReserve;
return (rAmount, rTransferAmount, rFee, rReserve);
}
function _getRate() private view returns (uint256) {
(uint256 rSupply, uint256 tSupply) = _getCurrentSupply();
return rSupply / tSupply;
}
function _getCurrentSupply() private view returns (uint256, uint256) {
uint256 rSupply = _rTotal;
uint256 tSupply = _tTotal;
for (uint256 i = 0; i < _excluded.length; i++) {
address account = _excluded[i];
uint256 rValue = _rOwned[account];
uint256 tValue = _tOwned[account];
if (rValue > rSupply || tValue > tSupply) return (_rTotal, _tTotal);
rSupply -= rValue;
tSupply -= tValue;
}
if (rSupply < _rTotal / _tTotal) return (_rTotal, _tTotal);
return (rSupply, tSupply);
}
}
文件 21 的 23: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;
}
}
文件 22 的 23:constants.sol
pragma solidity ^0.8.24;
uint8 constant NUM_ECOSYSTEM_TOKENS = 5;
address constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address constant TITANX = 0xF19308F923582A6f7c465e5CE7a9Dc1BEC6665B1;
address constant DRAGONX_ADDRESS = 0x96a5399D07896f757Bd4c6eF56461F58DB951862;
address constant BDX_ADDRESS = 0x9f278Dc799BbC61ecB8e5Fb8035cbfA29803623B;
address constant HYDRA_ADDRESS = 0xCC7ed2ab6c3396DdBc4316D2d7C1b59ff9d2091F;
address constant E280_ADDRESS = 0xe9A53C43a0B58706e67341C4055de861e29Ee943;
address constant DRAGONX_HYDRA_POOL = 0xF8F0Ef9f6A12336A1e035adDDbD634F3B0962F54;
address constant TITANX_DRAGONX_POOL = 0x25215d9ba4403b3DA77ce50606b54577a71b7895;
uint256 constant MAX_VALUE = ~uint256(0);
uint256 constant PRESALE_LENGTH = 14 days;
uint256 constant LP_POOL_PERCENT = 35;
uint256 constant BDX_BUY_BURN_PERCENT = 35;
uint256 constant DRAGONX_VAULT_PERCENT = 5;
uint256 constant HELIOS_VAULT_PERCENT = 5;
uint256 constant SHED_PERCENT = 11;
uint256 constant DEV_PERCENT = 8;
uint256 constant GENESIS_PERCENT = 1;
uint256 constant START_MAX_MINT_COST = 1e11 ether;
uint256 constant MAX_MINT_POWER_CAP = 10_000;
uint256 constant MAX_MINT_LENGTH = 88;
uint256 constant MAX_MINT_PER_WALLET = 1000;
uint8 constant MAX_AVAILABLE_MINERS = 20;
uint8 constant MIN_AVAILABLE_MINERS = 4;
address constant UNISWAP_V2_FACTORY = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
address constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
address constant UNISWAP_V3_ROUTER = 0xE592427A0AEce92De3Edee1F18E0157C05861564;
uint24 constant POOL_FEE_1PERCENT = 10000;
文件 23 的 23:draft-IERC6093.sol
pragma solidity ^0.8.20;
interface IERC20Errors {
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
error ERC20InvalidSender(address sender);
error ERC20InvalidReceiver(address receiver);
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
error ERC20InvalidApprover(address approver);
error ERC20InvalidSpender(address spender);
}
interface IERC721Errors {
error ERC721InvalidOwner(address owner);
error ERC721NonexistentToken(uint256 tokenId);
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
error ERC721InvalidSender(address sender);
error ERC721InvalidReceiver(address receiver);
error ERC721InsufficientApproval(address operator, uint256 tokenId);
error ERC721InvalidApprover(address approver);
error ERC721InvalidOperator(address operator);
}
interface IERC1155Errors {
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
error ERC1155InvalidSender(address sender);
error ERC1155InvalidReceiver(address receiver);
error ERC1155MissingApprovalForAll(address operator, address owner);
error ERC1155InvalidApprover(address approver);
error ERC1155InvalidOperator(address operator);
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
{
"compilationTarget": {
"contracts/SCALE.sol": "SCALE"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_devWallet","type":"address"},{"internalType":"address","name":"_marketingWallet","type":"address"},{"internalType":"address","name":"_heliosVault","type":"address"},{"internalType":"address","name":"_dragonxVault","type":"address"},{"internalType":"address","name":"_bdxBuyBurnAddress","type":"address"},{"internalType":"address[]","name":"_ecosystemTokens","type":"address[]"},{"internalType":"uint8[]","name":"_lpPercentages","type":"uint8[]"}],"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":"DuplicateToken","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"ExcludedAddress","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"IncorrectBonus","type":"error"},{"inputs":[],"name":"IncorrectPercentage","type":"error"},{"inputs":[],"name":"IncorrectTokenNumber","type":"error"},{"inputs":[],"name":"InsuffucientBalance","type":"error"},{"inputs":[],"name":"MaxSupply","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":"PresaleActive","type":"error"},{"inputs":[],"name":"PresaleInactive","type":"error"},{"inputs":[],"name":"Prohibited","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"TradingDisabled","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroInput","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","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"},{"anonymous":false,"inputs":[],"name":"PresaleStarted","type":"event"},{"anonymous":false,"inputs":[],"name":"ReserveDistributed","type":"event"},{"anonymous":false,"inputs":[],"name":"TradingEnabled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bdxBuyBurnAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bdxBuyBurnPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buyBurnDragonXAllocation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyBurnPurchases","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimDust","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"deployLiquidityPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"devWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minDragonXAmount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"distributeReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dragonXVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"excludeAccountFromReflections","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"finalizePresale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"heliosVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"incentiveFee","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"includeAccountToReflections","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isExcluded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPresaleActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpPurchaseFinished","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"lpPurchases","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketingWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxReserveDistribution","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minReserveDistribution","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint16","name":"bonus","type":"uint16"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"mintWithETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint16","name":"bonus","type":"uint16"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"mintWithTitanX","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"presaleEnd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presaleFinalized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"purchaseDragonXForBuyBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"purchaseTokenForLP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"purchasesRequired","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"reflect","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reflectionFee","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tAmount","type":"uint256"}],"name":"reflectionFromToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"scaleLpPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setBDXBuyBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setDevWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setDragonXVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setHeliosVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"bps","type":"uint16"}],"name":"setIncentiveFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setMarketingWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setMaxReserveDistribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setMinReserveDistribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"amount","type":"uint8"}],"name":"setPurchasesRequired","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"bps","type":"uint16"}],"name":"setReflectionFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setSHED","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shedContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startPresale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"titanLpPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rAmount","type":"uint256"}],"name":"tokenFromReflection","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"tokenLpPercent","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"tokenPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBurned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLPsCreated","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalLpPoolUsed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradingEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]