Description:
Smart contract deployed on Ethereum with Factory features.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"SecurityLib.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./Constants.sol";
library SecurityLib {
error SlippageTooHigh(uint256 expected, uint256 actual);
error FlashLoanDetected();
error RateLimitExceeded(address user, uint256 lastCall);
error InvalidTokenPair(address token0, address token1);
error InsufficientLiquidity(uint256 available, uint256 required);
error PriceManipulationDetected(uint256 oldPrice, uint256 newPrice);
error FakeTokenDetected(address token);
error MEVAttackDetected();
error PoolDrainAttempt(uint256 remainingLiquidity);
struct SlippageParams {
uint256 amountIn;
uint256 amountOutMin;
uint256 amountOutMax;
uint256 maxSlippageBps;
}
struct RateLimit {
uint256 lastCallTime;
uint256 callCount;
uint256 windowStart;
}
struct PriceValidation {
uint256 lastPrice;
uint256 lastUpdateTime;
uint256 maxDeviationBps;
bool isValid;
}
struct FlashLoanGuard {
uint256 balanceBefore;
uint256 balanceAfter;
bool isFlashLoan;
}
function validateSlippage(
SlippageParams memory params,
uint256 actualAmountOut
) internal pure {
if (actualAmountOut < params.amountOutMin) {
revert SlippageTooHigh(params.amountOutMin, actualAmountOut);
}
if (actualAmountOut > params.amountOutMax) {
revert SlippageTooHigh(params.amountOutMax, actualAmountOut);
}
uint256 expectedAmount = (params.amountOutMin + params.amountOutMax) / 2;
if (expectedAmount > 0) {
uint256 slippageBps;
if (actualAmountOut < expectedAmount) {
slippageBps = ((expectedAmount - actualAmountOut) * Constants.BASIS_POINTS) / expectedAmount;
} else {
slippageBps = ((actualAmountOut - expectedAmount) * Constants.BASIS_POINTS) / expectedAmount;
}
if (slippageBps > params.maxSlippageBps) {
revert SlippageTooHigh(expectedAmount, actualAmountOut);
}
}
}
function detectFlashLoan(
address /* token */,
uint256 balanceBefore,
uint256 balanceAfter
) internal pure returns (bool) {
if (balanceAfter > balanceBefore) {
uint256 increase = balanceAfter - balanceBefore;
uint256 increasePercentage = (increase * 100) / balanceBefore;
if (increasePercentage > 1000) {
return true;
}
}
return false;
}
function requireNoFlashLoan(
address token,
uint256 balanceBefore
) internal view {
uint256 currentBalance = getTokenBalance(token, address(this));
if (detectFlashLoan(token, balanceBefore, currentBalance)) {
revert FlashLoanDetected();
}
}
function checkRateLimit(
mapping(address => RateLimit) storage rateLimits,
address user,
uint256 maxCallsPerWindow,
uint256 windowDuration
) internal {
RateLimit storage limit = rateLimits[user];
uint256 currentTime = block.timestamp;
if (currentTime >= limit.windowStart + windowDuration) {
limit.windowStart = currentTime;
limit.callCount = 0;
}
if (limit.callCount >= maxCallsPerWindow) {
revert RateLimitExceeded(user, limit.lastCallTime);
}
limit.callCount++;
limit.lastCallTime = currentTime;
}
function validateSwapParams(
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 amountOutMin,
address to
) internal pure {
require(tokenIn != address(0), "Invalid tokenIn");
require(tokenOut != address(0), "Invalid tokenOut");
require(to != address(0), "Invalid recipient");
require(amountIn > 0, "Invalid amount");
require(amountOutMin > 0, "Invalid min amount");
require(tokenIn != tokenOut, "Identical tokens");
}
function validateToken(address token) internal view returns (bool) {
if (token == address(0)) return false;
uint256 size;
assembly {
size := extcodesize(token)
}
if (size == 0) return false;
try IERC20(token).totalSupply() returns (uint256) {
return true;
} catch {
return false;
}
}
function validatePriceChange(
PriceValidation storage priceData,
uint256 newPrice,
uint256 maxDeviationBps
) internal {
if (priceData.lastPrice > 0 && priceData.isValid) {
uint256 priceChange;
if (newPrice > priceData.lastPrice) {
priceChange = ((newPrice - priceData.lastPrice) * Constants.BASIS_POINTS) / priceData.lastPrice;
} else {
priceChange = ((priceData.lastPrice - newPrice) * Constants.BASIS_POINTS) / priceData.lastPrice;
}
if (priceChange > maxDeviationBps) {
revert PriceManipulationDetected(priceData.lastPrice, newPrice);
}
}
priceData.lastPrice = newPrice;
priceData.lastUpdateTime = block.timestamp;
priceData.isValid = true;
}
function detectSandwichAttack(
address user,
uint256 amountIn,
uint256 /* amountOut */,
mapping(address => uint256) storage lastTxAmounts,
mapping(address => uint256) storage lastTxBlocks
) internal view {
if (lastTxBlocks[user] == block.number - 1) {
uint256 lastAmount = lastTxAmounts[user];
if (amountIn > lastAmount * 10 || lastAmount > amountIn * 10) {
revert MEVAttackDetected();
}
}
}
function validatePoolHealth(
uint256 reserve0,
uint256 reserve1,
uint256 withdrawAmount0,
uint256 withdrawAmount1,
uint256 minLiquidity
) internal pure {
uint256 remainingReserve0 = reserve0 - withdrawAmount0;
uint256 remainingReserve1 = reserve1 - withdrawAmount1;
if (remainingReserve0 < minLiquidity || remainingReserve1 < minLiquidity) {
revert PoolDrainAttempt(remainingReserve0 + remainingReserve1);
}
uint256 kBefore = reserve0 * reserve1;
uint256 kAfter = remainingReserve0 * remainingReserve1;
if (kAfter < (kBefore * 95) / 100) {
revert PoolDrainAttempt(kAfter);
}
}
function getTokenBalance(address token, address account) internal view returns (uint256) {
try IERC20(token).balanceOf(account) returns (uint256 balance) {
return balance;
} catch {
return 0;
}
}
function calculatePercentageChange(
uint256 oldValue,
uint256 newValue
) internal pure returns (uint256) {
if (oldValue == 0) return 0;
if (newValue > oldValue) {
return ((newValue - oldValue) * Constants.BASIS_POINTS) / oldValue;
} else {
return ((oldValue - newValue) * Constants.BASIS_POINTS) / oldValue;
}
}
function validateDeadline(uint256 deadline) internal view {
require(block.timestamp <= deadline, "Transaction expired");
}
function safeTokenTransfer(
address token,
address to,
uint256 amount
) internal {
require(validateToken(token), "Invalid token");
require(to != address(0), "Zero address");
require(amount > 0, "Zero amount");
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(IERC20.transfer.selector, to, amount)
);
require(success && (data.length == 0 || abi.decode(data, (bool))), "Transfer failed");
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}"
},
"Constants.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
library Constants {
string internal constant PROTOCOL_VERSION = "1.0.0";
string internal constant PROTOCOL_NAME = "DEX Protocol";
address internal constant ZERO_ADDRESS = address(0);
uint256 internal constant MAX_UINT256 = type(uint256).max;
uint128 internal constant MAX_UINT128 = type(uint128).max;
uint256 internal constant DECIMAL_BASE = 1e18;
uint256 internal constant MINIMUM_LIQUIDITY = 1000;
uint256 internal constant MAX_POOLS = 10000;
uint256 internal constant MIN_SWAP_AMOUNT = 1000;
uint256 internal constant MAX_SWAP_AMOUNT = 1000000 * DECIMAL_BASE;
uint256 internal constant K_FACTOR = 1e12;
uint256 internal constant DEFAULT_SWAP_FEE = 3000;
uint256 internal constant DEFAULT_WITHDRAW_FEE = 1000;
uint256 internal constant TOKEN_LISTING_FEE = 1e16;
uint256 internal constant MAX_FEE_RATE = 5000;
uint256 internal constant MIN_FEE_RATE = 10;
uint256 internal constant FEE_BASE = 10000;
uint256 internal constant BASIS_POINTS = 10000;
uint256 internal constant PROTOCOL_FEE_SHARE = 2000;
uint256 internal constant LP_FEE_SHARE = 8000;
int24 internal constant MIN_TICK_SPACING = 1;
int24 internal constant MAX_TICK_SPACING = 16384;
int24 internal constant MIN_TICK = -887272;
int24 internal constant MAX_TICK = 887272;
uint256 internal constant PRICE_RATIO_BASE = 1001;
uint256 internal constant Q96 = 0x1000000000000000000000000;
uint256 internal constant Q128 = 0x100000000000000000000000000000000;
uint256 internal constant MIN_VOTING_PERIOD = 3 days;
uint256 internal constant MAX_VOTING_PERIOD = 30 days;
uint256 internal constant MIN_TIMELOCK_DELAY = 1 days;
uint256 internal constant MAX_TIMELOCK_DELAY = 30 days;
uint256 internal constant MIN_QUORUM = 500;
uint256 internal constant MAX_QUORUM = 2000;
uint256 internal constant MIN_PROPOSAL_THRESHOLD = 100;
uint256 internal constant MAX_SLIPPAGE = 1000;
uint256 internal constant MIN_SLIPPAGE = 10;
uint256 internal constant MAX_PRICE_IMPACT = 2000;
uint256 internal constant WITHDRAW_COOLDOWN = 1 hours;
uint256 internal constant MAX_TXS_PER_BLOCK = 100;
uint256 internal constant MAX_GAS_LIMIT = 15000000;
uint256 internal constant MIN_OBSERVATIONS = 2;
uint256 internal constant MAX_OBSERVATIONS = 65535;
uint256 internal constant DEFAULT_CARDINALITY = 100;
uint256 internal constant MIN_UPDATE_INTERVAL = 1;
uint256 internal constant MAX_UPDATE_INTERVAL = 3600;
uint256 internal constant MAX_PRICE_DEVIATION = 500;
uint256 internal constant MIN_TOKEN_SUPPLY = 1000000 * DECIMAL_BASE;
uint256 internal constant MAX_TOKEN_SUPPLY = 1000000000 * DECIMAL_BASE;
uint8 internal constant MAX_DECIMALS = 18;
uint8 internal constant MIN_DECIMALS = 6;
uint256 internal constant MAX_TOKEN_NAME_LENGTH = 50;
uint256 internal constant MAX_TOKEN_SYMBOL_LENGTH = 10;
uint256 internal constant REWARD_LOCK_PERIOD = 30 days;
uint256 internal constant MAX_REWARD_APR = 100000;
uint256 internal constant MIN_REWARD_APR = 100;
uint256 internal constant TEAM_VESTING_PERIOD = 365 days;
uint256 internal constant CIRCUIT_BREAKER_THRESHOLD = 5000;
uint256 internal constant CIRCUIT_BREAKER_COOLDOWN = 2 hours;
uint256 internal constant MAX_CIRCUIT_BREAKER_TRIGGERS = 3;
function percentToBasisPoints(uint256 percentage) internal pure returns (uint256) {
return percentage * 100;
}
function basisPointsToPercent(uint256 basisPoints) internal pure returns (uint256) {
return basisPoints / 100;
}
function calculateFee(uint256 amount, uint256 feeRate) internal pure returns (uint256) {
return (amount * feeRate) / FEE_BASE;
}
function isValidFeeRate(uint256 feeRate) internal pure returns (bool) {
return feeRate >= MIN_FEE_RATE && feeRate <= MAX_FEE_RATE;
}
function isValidTick(int24 tick) internal pure returns (bool) {
return tick >= MIN_TICK && tick <= MAX_TICK;
}
function isValidTickSpacing(int24 tickSpacing) internal pure returns (bool) {
return tickSpacing >= MIN_TICK_SPACING && tickSpacing <= MAX_TICK_SPACING;
}
}"
}
},
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": []
}
}}
Submitted on: 2025-10-07 16:12:53
Comments
Log in to comment.
No comments yet.