Qian V2 Contracts
Onchain token launch with permanently locked liquidity and DEX routing (Uniswap v3 + v4). No admin keys, no mint/blacklist. MIT licensed. Deployed addresses in README.
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Qian.ag
|
||||
pragma solidity ^0.8.24;
|
||||
|
||||
interface INonfungiblePositionManager {
|
||||
struct MintParams {
|
||||
address token0;
|
||||
address token1;
|
||||
uint24 fee;
|
||||
int24 tickLower;
|
||||
int24 tickUpper;
|
||||
uint256 amount0Desired;
|
||||
uint256 amount1Desired;
|
||||
uint256 amount0Min;
|
||||
uint256 amount1Min;
|
||||
address recipient;
|
||||
uint256 deadline;
|
||||
}
|
||||
|
||||
struct CollectParams {
|
||||
uint256 tokenId;
|
||||
address recipient;
|
||||
uint128 amount0Max;
|
||||
uint128 amount1Max;
|
||||
}
|
||||
|
||||
function factory() external view returns (address);
|
||||
function WETH9() external view returns (address);
|
||||
|
||||
function positions(uint256 tokenId) external view returns (
|
||||
uint96 nonce,
|
||||
address operator,
|
||||
address token0,
|
||||
address token1,
|
||||
uint24 fee,
|
||||
int24 tickLower,
|
||||
int24 tickUpper,
|
||||
uint128 liquidity,
|
||||
uint256 feeGrowthInside0LastX128,
|
||||
uint256 feeGrowthInside1LastX128,
|
||||
uint128 tokensOwed0,
|
||||
uint128 tokensOwed1
|
||||
);
|
||||
|
||||
function createAndInitializePoolIfNecessary(
|
||||
address token0,
|
||||
address token1,
|
||||
uint24 fee,
|
||||
uint160 sqrtPriceX96
|
||||
) external returns (address pool);
|
||||
|
||||
function mint(MintParams calldata params) external returns (
|
||||
uint256 tokenId,
|
||||
uint128 liquidity,
|
||||
uint256 amount0,
|
||||
uint256 amount1
|
||||
);
|
||||
|
||||
function collect(CollectParams calldata params) external payable returns (
|
||||
uint256 amount0,
|
||||
uint256 amount1
|
||||
);
|
||||
|
||||
function setApprovalForAll(address operator, bool approved) external;
|
||||
function safeTransferFrom(address from, address to, uint256 tokenId) external;
|
||||
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
|
||||
function isApprovedForAll(address owner, address operator) external view returns (bool);
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Qian.ag
|
||||
pragma solidity ^0.8.24;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import "./INonfungiblePositionManager.sol";
|
||||
|
||||
error InvalidTickRange();
|
||||
error PoolPriceHijacked();
|
||||
|
||||
interface IUniswapV3PoolSlot0 {
|
||||
function slot0() external view returns (
|
||||
uint160 sqrtPriceX96, int24 tick, uint16 observationIndex, uint16 observationCardinality,
|
||||
uint16 observationCardinalityNext, uint8 feeProtocol, bool unlocked
|
||||
);
|
||||
}
|
||||
|
||||
library LiquidityProvider {
|
||||
struct Config {
|
||||
uint160 sqrtPriceX96A;
|
||||
uint160 sqrtPriceX96B;
|
||||
int24 tickLower;
|
||||
int24 tickUpper;
|
||||
uint256 amount0Desired;
|
||||
uint256 amount1Desired;
|
||||
}
|
||||
|
||||
function provideLiquidity(
|
||||
address positionManager,
|
||||
address tokenA,
|
||||
address tokenB,
|
||||
Config memory config
|
||||
) internal returns (uint256 tokenId) {
|
||||
bool tokenAIsToken0 = tokenA < tokenB;
|
||||
|
||||
address token0 = tokenAIsToken0 ? tokenA : tokenB;
|
||||
address token1 = tokenAIsToken0 ? tokenB : tokenA;
|
||||
|
||||
IERC20(token0).approve(positionManager, type(uint256).max);
|
||||
IERC20(token1).approve(positionManager, type(uint256).max);
|
||||
|
||||
INonfungiblePositionManager manager = INonfungiblePositionManager(positionManager);
|
||||
|
||||
uint160 sqrtPriceX96 = tokenAIsToken0
|
||||
? config.sqrtPriceX96A
|
||||
: config.sqrtPriceX96B;
|
||||
|
||||
int24 tickLower;
|
||||
int24 tickUpper;
|
||||
if (tokenAIsToken0) {
|
||||
tickLower = -int24(config.tickLower);
|
||||
tickUpper = int24(config.tickUpper);
|
||||
} else {
|
||||
tickLower = -int24(config.tickUpper);
|
||||
tickUpper = int24(config.tickLower);
|
||||
}
|
||||
if (tickLower >= tickUpper) revert InvalidTickRange();
|
||||
|
||||
uint256 amount0Desired = tokenAIsToken0 ? config.amount0Desired : config.amount1Desired;
|
||||
uint256 amount1Desired = tokenAIsToken0 ? config.amount1Desired : config.amount0Desired;
|
||||
|
||||
// "IfNecessary" never reverts on an existing pool, so a front-run init at a WRONG
|
||||
// price would silently skew the mint + dev buy. Assert the live price; a same-price
|
||||
// front-run is harmless (the attacker just created our pool for us).
|
||||
address pool = manager.createAndInitializePoolIfNecessary(token0, token1, 10000, sqrtPriceX96);
|
||||
(uint160 livePrice, , , , , , ) = IUniswapV3PoolSlot0(pool).slot0();
|
||||
if (livePrice != sqrtPriceX96) revert PoolPriceHijacked();
|
||||
|
||||
(tokenId, , , ) = manager.mint(
|
||||
INonfungiblePositionManager.MintParams({
|
||||
token0: token0,
|
||||
token1: token1,
|
||||
fee: 10000,
|
||||
tickLower: tickLower,
|
||||
tickUpper: tickUpper,
|
||||
amount0Desired: amount0Desired,
|
||||
amount1Desired: amount1Desired,
|
||||
amount0Min: 0,
|
||||
amount1Min: 0,
|
||||
recipient: address(this),
|
||||
deadline: block.timestamp
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Qian.ag
|
||||
pragma solidity ^0.8.24;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
||||
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
||||
import "./LiquidityProvider.sol";
|
||||
import "./INonfungiblePositionManager.sol";
|
||||
import "./QianToken.sol";
|
||||
|
||||
interface ISwapRouter02 {
|
||||
struct ExactInputSingleParams {
|
||||
address tokenIn;
|
||||
address tokenOut;
|
||||
uint24 fee;
|
||||
address recipient;
|
||||
uint256 amountIn;
|
||||
uint256 amountOutMinimum;
|
||||
uint160 sqrtPriceLimitX96;
|
||||
}
|
||||
|
||||
function exactInputSingle(ExactInputSingleParams calldata params)
|
||||
external
|
||||
payable
|
||||
returns (uint256 amountOut);
|
||||
}
|
||||
|
||||
error BadRouterConfig();
|
||||
error DeployDisabled();
|
||||
error NewCreatorZero();
|
||||
error NotController();
|
||||
error Unauthorized();
|
||||
error InsufficientDeployFee();
|
||||
error DeployFeeTooHigh();
|
||||
error InvalidConfig();
|
||||
error TransferFailed();
|
||||
|
||||
interface IWETH {
|
||||
function deposit() external payable;
|
||||
function withdraw(uint256 amount) external;
|
||||
}
|
||||
|
||||
interface IBindingLocker {
|
||||
function setCreator(address token, address newCreator) external;
|
||||
function creatorOf(address token) external view returns (address);
|
||||
}
|
||||
|
||||
contract QianFactoryV3 is ReentrancyGuard {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
event ERC20TokenCreated(address tokenAddress);
|
||||
event DeployCoinToggled(bool enabled);
|
||||
event DeployFeeUpdated(uint256 oldFee, uint256 newFee);
|
||||
event CreatorChanged(address indexed token, address indexed oldCreator, address indexed newCreator);
|
||||
event ControllerTransferInitiated(address indexed currentController, address indexed pendingController);
|
||||
event ControllerTransferred(address indexed oldController, address indexed newController);
|
||||
|
||||
struct TokenInfo {
|
||||
address tokenAddress;
|
||||
string name;
|
||||
string symbol;
|
||||
address deployer;
|
||||
uint256 time;
|
||||
string metadata;
|
||||
uint256 nftId;
|
||||
}
|
||||
|
||||
/// @notice Indexer read surface. The by-index list and tokenToNFTId mapping were
|
||||
/// deleted — the token itself and the locker's binding carry the same data.
|
||||
mapping(address => TokenInfo) public tokenInfoByAddress;
|
||||
uint256 public tokenCount = 0;
|
||||
address public platformController;
|
||||
/// @dev platformController is both the admin and the fee sink (there is no
|
||||
/// setFeeVault), so it must be transferable. Two-step, mirroring QianFactoryV4.
|
||||
address public pendingController;
|
||||
bool public deployCoinEnabled = false;
|
||||
uint256 public deployFee = 0.005 ether;
|
||||
|
||||
/// @notice Live receiver of a token's 70% creator fees, read by QianFeeRouter.
|
||||
/// Reassignable via changeTokenFeeReceiver (CTO). The token's own `creator` is an
|
||||
/// immutable record of the original launcher, not this.
|
||||
/// @dev The binding in the locker is the only copy — it is written atomically with the
|
||||
/// lock and is what QianFeeRouter pays. This reads through so callers keep one address.
|
||||
function tokenCreator(address token) public view returns (address) {
|
||||
return IBindingLocker(locker).creatorOf(token);
|
||||
}
|
||||
|
||||
struct LiquidityConfig {
|
||||
uint160 sqrtPriceX96A;
|
||||
uint160 sqrtPriceX96B;
|
||||
int24 tickLower;
|
||||
int24 tickUpper;
|
||||
uint256 amount0Desired;
|
||||
uint256 amount1Desired;
|
||||
}
|
||||
|
||||
mapping(uint256 => LiquidityConfig) public liquidityConfigs;
|
||||
uint256 public liquidityConfigCount = 0;
|
||||
|
||||
address public immutable positionManager;
|
||||
address public immutable weth;
|
||||
address public immutable swapRouter;
|
||||
address public immutable locker;
|
||||
|
||||
// dev buy pays the same 1% QianSwapRouter charges on every other trade
|
||||
uint16 public constant DEV_BUY_FEE_BPS = 100;
|
||||
uint256 private constant FULL_TOKEN_SUPPLY = 1_000_000_000 * 10 ** 18;
|
||||
|
||||
constructor(address _positionManager, address _swapRouter, address _weth, address _locker) {
|
||||
if (_positionManager == address(0) || _swapRouter == address(0) || _weth == address(0) || _locker == address(0)) {
|
||||
revert BadRouterConfig();
|
||||
}
|
||||
platformController = msg.sender;
|
||||
positionManager = _positionManager;
|
||||
swapRouter = _swapRouter;
|
||||
weth = _weth;
|
||||
locker = _locker;
|
||||
|
||||
liquidityConfigs[0] = LiquidityConfig({
|
||||
sqrtPriceX96A: 2_097_222_954_085_974_151_159_020,
|
||||
sqrtPriceX96B: 2_993_054_087_624_369_706_988_840_588_130_593,
|
||||
tickLower: 210800,
|
||||
tickUpper: 310800,
|
||||
amount0Desired: FULL_TOKEN_SUPPLY,
|
||||
amount1Desired: 0
|
||||
});
|
||||
liquidityConfigCount = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @param maxDeployFee caller's ceiling on deployFee, so a controller fee change
|
||||
/// cannot front-run this tx
|
||||
function deployCoin(string memory _name, string memory _symbol, string memory _metadata, bytes32 salt, uint256 configId, uint256 maxDeployFee) public payable nonReentrant returns (uint256 tokensReceived) {
|
||||
if (!deployCoinEnabled) revert DeployDisabled();
|
||||
if (configId >= liquidityConfigCount) revert InvalidConfig();
|
||||
if (deployFee > maxDeployFee) revert DeployFeeTooHigh();
|
||||
if (msg.value < deployFee) revert InsufficientDeployFee();
|
||||
|
||||
// dev buy pays the same 1% the swap router takes on every other trade;
|
||||
// it ships with the deploy fee as a single transfer (no separate hop)
|
||||
uint256 devBuyValue = msg.value - deployFee;
|
||||
uint256 devBuyFee = (devBuyValue * DEV_BUY_FEE_BPS) / 10_000;
|
||||
uint256 remainingValue = devBuyValue - devBuyFee;
|
||||
|
||||
QianToken t = new QianToken{salt: salt}(
|
||||
_name,
|
||||
_symbol,
|
||||
_metadata,
|
||||
msg.sender,
|
||||
address(this)
|
||||
);
|
||||
emit ERC20TokenCreated(address(t));
|
||||
|
||||
address coin_address = address(t);
|
||||
|
||||
uint256 nftId = provideLiquidity(coin_address, weth, configId, msg.sender);
|
||||
|
||||
uint256 platformTake = deployFee + devBuyFee;
|
||||
if (platformTake > 0) {
|
||||
(bool success, ) = platformController.call{value: platformTake}("");
|
||||
if (!success) revert TransferFailed();
|
||||
}
|
||||
|
||||
tokensReceived = 0;
|
||||
|
||||
if (remainingValue > 0) {
|
||||
ISwapRouter02(swapRouter).exactInputSingle{ value: remainingValue }(
|
||||
ISwapRouter02.ExactInputSingleParams({
|
||||
tokenIn: weth,
|
||||
tokenOut: coin_address,
|
||||
fee: 10000,
|
||||
recipient: address(this),
|
||||
amountIn: remainingValue,
|
||||
amountOutMinimum: 0,
|
||||
sqrtPriceLimitX96: 0
|
||||
})
|
||||
);
|
||||
|
||||
IERC20 token = IERC20(coin_address);
|
||||
tokensReceived = token.balanceOf(address(this));
|
||||
token.transfer(msg.sender, tokensReceived);
|
||||
}
|
||||
|
||||
tokenInfoByAddress[coin_address] = TokenInfo({
|
||||
tokenAddress: coin_address,
|
||||
name: _name,
|
||||
symbol: _symbol,
|
||||
deployer: msg.sender,
|
||||
time: block.timestamp,
|
||||
metadata: _metadata,
|
||||
nftId: nftId
|
||||
});
|
||||
tokenCount++;
|
||||
|
||||
return tokensReceived;
|
||||
}
|
||||
|
||||
|
||||
// No withdrawFees and no receive(): nothing accumulates here, so nothing needs a
|
||||
// sweep. deployCoin is payable and takes msg.value directly; the dev buy and the fee
|
||||
// transfer are outbound.
|
||||
|
||||
function toggleDeployCoin() external {
|
||||
if (msg.sender != platformController) revert NotController();
|
||||
deployCoinEnabled = !deployCoinEnabled;
|
||||
emit DeployCoinToggled(deployCoinEnabled);
|
||||
}
|
||||
|
||||
function setDeployFee(uint256 _deployFee) external {
|
||||
if (msg.sender != platformController) revert NotController();
|
||||
uint256 oldFee = deployFee;
|
||||
deployFee = _deployFee;
|
||||
emit DeployFeeUpdated(oldFee, _deployFee);
|
||||
}
|
||||
|
||||
function createLiquidityConfig(
|
||||
uint160 _sqrtPriceX96A,
|
||||
uint160 _sqrtPriceX96B,
|
||||
int24 _tickLower,
|
||||
int24 _tickUpper,
|
||||
uint256 _amount0Desired,
|
||||
uint256 _amount1Desired
|
||||
) external returns (uint256 configId) {
|
||||
if (msg.sender != platformController) revert NotController();
|
||||
if (_tickLower <= 0 || _tickUpper <= 0 || _tickLower >= _tickUpper) revert InvalidTickRange();
|
||||
|
||||
configId = liquidityConfigCount;
|
||||
liquidityConfigs[configId] = LiquidityConfig({
|
||||
sqrtPriceX96A: _sqrtPriceX96A,
|
||||
sqrtPriceX96B: _sqrtPriceX96B,
|
||||
tickLower: _tickLower,
|
||||
tickUpper: _tickUpper,
|
||||
amount0Desired: _amount0Desired,
|
||||
amount1Desired: _amount1Desired
|
||||
});
|
||||
liquidityConfigCount++;
|
||||
|
||||
return configId;
|
||||
}
|
||||
|
||||
function updateLiquidityConfig(
|
||||
uint256 _configId,
|
||||
uint160 _sqrtPriceX96A,
|
||||
uint160 _sqrtPriceX96B,
|
||||
int24 _tickLower,
|
||||
int24 _tickUpper,
|
||||
uint256 _amount0Desired,
|
||||
uint256 _amount1Desired
|
||||
) external {
|
||||
if (msg.sender != platformController) revert NotController();
|
||||
if (_configId >= liquidityConfigCount) revert InvalidConfig();
|
||||
if (_tickLower <= 0 || _tickUpper <= 0 || _tickLower >= _tickUpper) revert InvalidTickRange();
|
||||
|
||||
liquidityConfigs[_configId] = LiquidityConfig({
|
||||
sqrtPriceX96A: _sqrtPriceX96A,
|
||||
sqrtPriceX96B: _sqrtPriceX96B,
|
||||
tickLower: _tickLower,
|
||||
tickUpper: _tickUpper,
|
||||
amount0Desired: _amount0Desired,
|
||||
amount1Desired: _amount1Desired
|
||||
});
|
||||
}
|
||||
|
||||
function provideLiquidity(address tokenA, address tokenB, uint256 configId, address creator) internal returns (uint256 tokenId) {
|
||||
LiquidityConfig memory config = liquidityConfigs[configId];
|
||||
|
||||
LiquidityProvider.Config memory libConfig = LiquidityProvider.Config({
|
||||
sqrtPriceX96A: config.sqrtPriceX96A,
|
||||
sqrtPriceX96B: config.sqrtPriceX96B,
|
||||
tickLower: config.tickLower,
|
||||
tickUpper: config.tickUpper,
|
||||
amount0Desired: config.amount0Desired,
|
||||
amount1Desired: config.amount1Desired
|
||||
});
|
||||
|
||||
tokenId = LiquidityProvider.provideLiquidity(
|
||||
positionManager,
|
||||
tokenA,
|
||||
tokenB,
|
||||
libConfig
|
||||
);
|
||||
|
||||
// Position NFT goes straight into the locker, carrying the (token, creator)
|
||||
// binding in the transfer data — the locker records who this position belongs
|
||||
// to in the same call that permanently locks it.
|
||||
INonfungiblePositionManager(positionManager).safeTransferFrom(
|
||||
address(this), locker, tokenId, abi.encode(tokenA, creator)
|
||||
);
|
||||
}
|
||||
|
||||
// Fee collection now lives in QianFeeRouter.collectFees(token) — permissionless,
|
||||
// fixed 30% treasury / 70% creator split, served by the locker.
|
||||
|
||||
/// @notice Begin handing over the controller role, and with it the fee sink.
|
||||
/// @dev Two-step: the new controller must accept, so a typo cannot strand this
|
||||
/// factory's admin and revenue on an address nobody holds.
|
||||
function transferController(address newController) external {
|
||||
if (msg.sender != platformController) revert NotController();
|
||||
if (newController == address(0)) revert NewCreatorZero();
|
||||
pendingController = newController;
|
||||
emit ControllerTransferInitiated(platformController, newController);
|
||||
}
|
||||
|
||||
/// @notice Complete the handover. Callable only by the pending controller.
|
||||
function acceptController() external {
|
||||
if (msg.sender != pendingController) revert Unauthorized();
|
||||
address oldController = platformController;
|
||||
platformController = pendingController;
|
||||
pendingController = address(0);
|
||||
emit ControllerTransferred(oldController, platformController);
|
||||
}
|
||||
|
||||
/// @notice Controller-only: reassign a token's creator fee rights (approved CTO).
|
||||
/// @dev Fee routing only; cannot touch balances, transfers or supply.
|
||||
/// @dev The locker's binding is the only record; it rejects this call unless the token
|
||||
/// was bound by THIS factory and this factory is still authorized.
|
||||
function changeTokenFeeReceiver(address tokenAddress, address newCreator) external {
|
||||
if (msg.sender != platformController) revert NotController();
|
||||
if (newCreator == address(0)) revert NewCreatorZero();
|
||||
address oldCreator = tokenCreator(tokenAddress);
|
||||
// a token no factory ever launched has no fee rights to reassign
|
||||
if (oldCreator == address(0)) revert InvalidConfig();
|
||||
emit CreatorChanged(tokenAddress, oldCreator, newCreator);
|
||||
IBindingLocker(locker).setCreator(tokenAddress, newCreator);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
// ██████╗ ██╗ █████╗ ███╗ ██╗
|
||||
// ██╔═══██╗██║██╔══██╗████╗ ██║
|
||||
// ██║ ██║██║███████║██╔██╗ ██║
|
||||
// ██║▄▄ ██║██║██╔══██║██║╚██╗██║
|
||||
// ╚██████╔╝██║██║ ██║██║ ╚████║
|
||||
// ╚══▀▀═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝
|
||||
//
|
||||
// 钱 · Qian.ag — Multichain DEX & Launchpad
|
||||
// Fixed supply. No owner, no mint, no games.
|
||||
// — V2.1 —
|
||||
//
|
||||
pragma solidity ^0.8.24;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
|
||||
|
||||
/// @notice Fixed-supply ERC20. Supply is minted once here and there is no mint function.
|
||||
/// No transfer hooks, no owner, no privileged functions.
|
||||
contract QianToken is ERC20, ERC20Burnable {
|
||||
/// @dev Same signature as OpenZeppelin Ownable. Indexers read renouncement from this
|
||||
/// event rather than calling owner().
|
||||
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
|
||||
|
||||
/// @notice The factory that deployed this token.
|
||||
address public immutable platform;
|
||||
/// @notice Original launcher. A record, not the fee receiver — fee rights are
|
||||
/// reassignable, so read `tokenCreator(token)` on `platform` for who is paid today.
|
||||
address public immutable creator;
|
||||
uint256 public constant MAX_SUPPLY = 1_000_000_000 * 10 ** 18;
|
||||
|
||||
/// @notice ipfs://<cid> for the token's image/description, so indexers need no factory.
|
||||
string public metadata;
|
||||
|
||||
constructor(
|
||||
string memory _name,
|
||||
string memory _symbol,
|
||||
string memory _metadata,
|
||||
address _creator,
|
||||
address _platform
|
||||
) ERC20(_name, _symbol) {
|
||||
platform = _platform;
|
||||
creator = _creator;
|
||||
metadata = _metadata;
|
||||
_mint(_platform, MAX_SUPPLY);
|
||||
emit OwnershipTransferred(address(0), _platform);
|
||||
emit OwnershipTransferred(_platform, address(0));
|
||||
}
|
||||
|
||||
/// @notice Common indexer convention — same value as metadata().
|
||||
function tokenURI() external view returns (string memory) {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/// @notice No owner, no mint, no pause, no blacklist.
|
||||
function owner() public pure returns (address) {
|
||||
return address(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
pragma solidity ^0.8.20;
|
||||
// BondingCurveLibrary
|
||||
|
||||
string constant ERR_BONDING_CURVE_LIBRARY_INVALID_AMOUNT_OUT =
|
||||
"BondingCurveLibrary : ERR_BONDING_CURVE_LIBRARY_INVALID_AMOUNT_OUT";
|
||||
string constant ERR_BONDING_CURVE_LIBRARY_INVALID_AMOUNT_IN =
|
||||
"BondingCurveLibrary : ERR_BONDING_CURVE_LIBRARY_INVALID_AMOUNT_IN";
|
||||
string constant ERR_BONDING_CURVE_LIBRARY_INSUFFICIENT_LIQUIDITY =
|
||||
"BondingCurveLibrary : ERR_BONDING_CURVE_LIBRARY_INSUFFICIENT_LIQUIDITY";
|
||||
string constant ERR_BONDING_CURVE_LIBRARY_INVALID_INPUTS =
|
||||
"BondingCurveLibrary : ERR_BONDING_CURVE_LIBRARY_INVALID_INPUTS";
|
||||
//Transfer Helper
|
||||
string constant ERR_TRANSFER_NATIVE_FAILED = "ERR_TRANSFER_NATIVE_FAILED";
|
||||
|
||||
//BondingCurve
|
||||
string constant ERR_BONDING_CURVE_ONLY_OWNER = "BondingCurve : ERR_BONDING_CURVE_ONLY_OWNER";
|
||||
string constant ERR_BONDING_CURVE_ONLY_FACTORY = "BondingCurve : ERR_BONDING_CURVE_ONLY_FACTORY";
|
||||
string constant ERR_BONDING_CURVE_FINISHED = "BondingCurve : ERR_BONDING_CURVE_FINISHED";
|
||||
string constant ERR_BONDING_CURVE_INVALID_AMOUNT_OUT = "BondingCurve : ERR_BONDING_CURVE_INVALID_AMOUNT_OUT";
|
||||
string constant ERR_BONDING_CURVE_INVALID_AMOUNT_IN = "BondingCurve : ERR_BONDING_CURVE_INVALID_AMOUNT_IN";
|
||||
string constant ERR_BONDING_CURVE_OVERFLOW_TARGET = "BondingCurve : ERR_BONDING_CURVE_OVERFLOW_TARGET";
|
||||
string constant ERR_BONDING_CURVE_INVALID_TO = "BondingCurve : ERR_BONDING_CURVE_INVALID_TO";
|
||||
string constant ERR_BONDING_CURVE_INVALID_K = "BondingCurve : ERR_BONDING_CURVE_INVALID_K";
|
||||
string constant ERR_BONDING_CURVE_INSUFFICIENT_RESERVE = "BondingCurve : ERR_BONDING_CURVE_INSUFFICIENT_RESERVE";
|
||||
string constant ERR_BONDING_CURVE_ONLY_LOCK = "BondingCurve : ERR_LISTING_ONLY_LOCK";
|
||||
string constant ERR_BONDING_CURVE_LOCKED = "BondingCurve : ERR_BONDING_CURVE_LOCKED";
|
||||
string constant ERR_BONDING_CURVE_ALREADY_LISTED = "BondingCurve : ERR_BONDING_CURVE_ALREADY_LISTED";
|
||||
string constant ERR_BONDING_CURVE_MUST_LISTING = "BondingCurve : ERR_BONDING_CURVE_MUST_LISTING";
|
||||
//BondingCurveFactory
|
||||
string constant ERR_BONDING_CURVE_FACTORY_ONLY_OWNER = "BondingCurveFactory : ERR_BONDING_CURVE_FACTORY_ONLY_OWNER";
|
||||
string constant ERR_BONDING_CURVE_FACTORY_ONLY_CORE = "BondingCurveFactory : ERR_BONDING_CURVE_FACTORY_ONLY_CORE";
|
||||
|
||||
//CORE
|
||||
string constant ERR_CORE_EXPIRED = "Core : ERR_CORE_EXPIRED";
|
||||
string constant ERR_CORE_INVALID_FEE = "Core : ERR_CORE_INVALID_FEE";
|
||||
string constant ERR_CORE_INVALID_SEND_NATIVE = "Core : ERR_CORE_INVALID_SEND_NATIVE";
|
||||
string constant ERR_CORE_INVALID_AMOUNT_IN = "Core : ERR_CORE_INVALID_AMOUNT_IN";
|
||||
string constant ERR_CORE_INVALID_AMOUNT_OUT = "Core : ERR_CORE_INVALID_AMOUNT_OUT";
|
||||
string constant ERR_CORE_INVALID_ALLOWANCE = "Core : ERR_CORE_INVALID_ALLOWANCE";
|
||||
string constant ERR_CORE_INVALID_AMOUNT_IN_MAX = "Core : ERR_CORE_INVALID_AMOUNT_IN_MAX";
|
||||
string constant ERR_CORE_ALREADY_INITIALIZED = "Core : ERR_CORE_ALREADY_INITIALIZED";
|
||||
|
||||
//LOCK
|
||||
string constant ERR_LOCK_ONLY_OWNER = "Lock : ERR_LOCK_ONLY_OWNER";
|
||||
string constant ERR_LOCK_INVALID_AMOUNT_IN = "Lock : ERR_LOCK_INVALID_AMOUNT_IN";
|
||||
string constant ERR_TOKEN_NOT_LOCKED = "Lock : ERR_TOKEN_NOT_LOCKED";
|
||||
string constant ERR_INVALID_ACCOUNT = "Lock : ERR_INVALID_ACCOUNT";
|
||||
string constant ERR_INVALID_TOKEN_ADDRESS = "Lock : ERR_INVALID_TOKEN_ADDRESS";
|
||||
// MINT PARTY
|
||||
string constant ERR_MINT_PARTY_ONLY_OWNER = "MintParty : ERR_MINT_PARTY_ONLY_OWNER";
|
||||
string constant ERR_MINT_PARTY_ONLY_FACTORY = "MintParty : ERR_MINT_PARTY_ONLY_FACTORY";
|
||||
string constant ERR_MINT_PARTY_FINISHED = "MintParty : ERR_MINT_PARTY_FINISHED";
|
||||
string constant ERR_MINT_PARTY_INVALID_FUNDING_AMOUNT = "MintParty : ERR_MINT_PARTY_INVALID_FUNDING_AMOUNT";
|
||||
string constant ERR_MINT_PARTY_INVALID_WHITE_LIST = "MintParty : ERR_MINT_PARTY_INVALID_WHITE_LIST";
|
||||
string constant ERR_MINT_PARTY_INVALID_WHITELIST = "MintParty : ERR_MINT_PARTY_INVALID_WHITELIST";
|
||||
string constant ERR_MINT_PARTY_WITHDRAW_AMOUNT_IS_ZERO = "MintParty : ERR_MINT_PARTY_WITHDRAW_AMOUNT_IS_ZERO";
|
||||
string constant ERR_MINT_PARTY_ALREADY_DEPOSITED = "MintParty : ERR_MINT_PARTY_ALREADY_DEPOSITED";
|
||||
string constant ERR_MINT_PARTY_BALANCE_ZERO = "MintParty : ERR_MINT_PARTY_BALANCE_ZERO";
|
||||
string constant ERR_MINT_PARTY_WHITELIST_ALREADY_ADDED = "MintParty : ERR_MINT_PARTY_WHITELIST_ALREADY_ADDED";
|
||||
|
||||
//MINT_PARTY Factory
|
||||
string constant ERR_MINT_PARTY_FACTORY_NOT_FINISHED = "MintPartyFactory : ERR_MINT_PARTY_FACTORY_NOT_FINISHED";
|
||||
string constant ERR_MINT_PARTY_FACTORY_INVALID_FUNDING_AMOUNT =
|
||||
"MintPartyFactory : ERR_MINT_PARTY_FACTORY_INVALID_FUNDING_AMOUNT";
|
||||
string constant ERR_MINT_PARTY_FACTORY_INVALID_MAXIMUM_WHITELIST =
|
||||
"MintPartyFactory : ERR_MINT_PARTY_FACTORY_INVALID_MAXIMUM_WHITELIST";
|
||||
string constant ERR_MINT_PARTY_FACTORY_ONLY_OWNER = "MintPartyFactory : ERR_MINT_PARTY_FACTORY_ONLY_OWNER";
|
||||
|
||||
//Token
|
||||
string constant ERR_TOKEN_ONLY_FACTORY = "Token : ERR_TOKEN_ONLY_FACTORY";
|
||||
string constant ERR_TOKEN_ONLY_ONCE_MINT = "Token : ERR_TOKEN_ONLY_ONCE_MINT";
|
||||
string constant ERR_TOKEN_INVALID_EXPIRED = "Token : ERR_TOKEN_INVALID_EXPIRED";
|
||||
string constant ERR_TOKEN_INVALID_SIGNATURE = "Token : ERR_TOKEN_INVALID_SIGNATURE";
|
||||
|
||||
//FeeVault
|
||||
string constant ERR_FEE_VAULT_INVALID_WNATIVE_ADDRESS = "FeeVault : ERR_FEE_VAULT_INVALID_WNATIVE_ADDRESS";
|
||||
string constant ERR_FEE_VAULT_INVALID_OWNER = "FeeVault : ERR_FEE_VAULT_INVALID_OWNER";
|
||||
string constant ERR_FEE_VAULT_NOT_OWNER = "FeeVault : ERR_FEE_VAULT_NOT_OWNER";
|
||||
string constant ERR_FEE_VAULT_INVALID_RECEIVER = "FeeVault : ERR_FEE_VAULT_INVALID_RECEIVER";
|
||||
string constant ERR_FEE_VAULT_INVALID_AMOUNT = "FeeVault : ERR_FEE_VAULT_INVALID_AMOUNT";
|
||||
string constant ERR_FEE_VAULT_INSUFFICIENT_BALANCE = "FeeVault : ERR_FEE_VAULT_INSUFFICIENT_BALANCE";
|
||||
string constant ERR_FEE_VAULT_TRANSFER_FAILED = "FeeVault : ERR_FEE_VAULT_TRANSFER_FAILED";
|
||||
string constant ERR_FEE_VAULT_REENTRANT = "FeeVault : ERR_FEE_VAULT_REENTRANT";
|
||||
|
||||
//DexRouter
|
||||
|
||||
string constant ERR_DEX_ROUTER_EXPIRED = "DexRouter : ERR_DEX_ROUTER_EXPIRED";
|
||||
string constant ERR_DEX_ROUTER_INVALID_SEND_NATIVE = "DexRouter : ERR_DEX_ROUTER_INVALID_SEND_NATIVE";
|
||||
string constant ERR_DEX_ROUTER_INVALID_AMOUNT_IN = "DexRouter : ERR_DEX_ROUTER_INVALID_AMOUNT_IN";
|
||||
string constant ERR_DEX_ROUTER_INVALID_FEE = "DexRouter : ERR_DEX_ROUTER_INVALID_FEE";
|
||||
string constant ERR_DEX_ROUTER_INVALID_ALLOWANCE = "DexRouter : ERR_DEX_ROUTER_INVALID_ALLOWANCE";
|
||||
string constant ERR_DEX_ROUTER_INVALID_AMOUNT_OUT_MIN = "DexRouter : ERR_DEX_ROUTER_INVALID_AMOUNT_OUT_MIN";
|
||||
string constant ERR_DEX_ROUTER_INVALID_AMOUNT_IN_MAX = "DexRouter : ERR_DEX_ROUTER_INVALID_AMOUNT_IN_MAX";
|
||||
Reference in New Issue
Block a user