编译器
0.8.19+commit.7dd6d404
文件 1 的 8:AerodromeInterfaces.sol
pragma solidity ^0.8.0;
interface IFactoryRegistry {
error FallbackFactory();
error InvalidFactoriesToPoolFactory();
error PathAlreadyApproved();
error PathNotApproved();
error SameAddress();
error ZeroAddress();
event Approve(
address indexed poolFactory,
address indexed votingRewardsFactory,
address indexed gaugeFactory
);
event Unapprove(
address indexed poolFactory,
address indexed votingRewardsFactory,
address indexed gaugeFactory
);
event SetManagedRewardsFactory(address indexed _newRewardsFactory);
function approve(
address poolFactory,
address votingRewardsFactory,
address gaugeFactory
) external;
function unapprove(address poolFactory) external;
function managedRewardsFactory() external view returns (address);
function setManagedRewardsFactory(
address _newManagedRewardsFactory
) external;
function factoriesToPoolFactory(
address poolFactory
)
external
view
returns (address votingRewardsFactory, address gaugeFactory);
function poolFactories() external view returns (address[] memory);
function isPoolFactoryApproved(
address poolFactory
) external view returns (bool);
function poolFactoriesLength() external view returns (uint256);
}
interface IPoolFactory {
event SetFeeManager(address feeManager);
event SetPauser(address pauser);
event SetPauseState(bool state);
event SetVoter(address voter);
event PoolCreated(
address indexed token0,
address indexed token1,
bool indexed stable,
address pool,
uint256
);
event SetCustomFee(address indexed pool, uint256 fee);
error FeeInvalid();
error FeeTooHigh();
error InvalidPool();
error NotFeeManager();
error NotPauser();
error NotVoter();
error PoolAlreadyExists();
error SameAddress();
error ZeroFee();
error ZeroAddress();
function allPoolsLength() external view returns (uint256);
function isPool(address pool) external view returns (bool);
function getPool(
address tokenA,
address tokenB,
bool stable
) external view returns (address);
function getPool(
address tokenA,
address tokenB,
uint24 fee
) external view returns (address);
function setVoter(address _voter) external;
function setPauser(address _pauser) external;
function setPauseState(bool _state) external;
function setFeeManager(address _feeManager) external;
function setFee(bool _stable, uint256 _fee) external;
function setCustomFee(address _pool, uint256 _fee) external;
function getFee(
address _pool,
bool _stable
) external view returns (uint256);
function createPool(
address tokenA,
address tokenB,
bool stable
) external returns (address pool);
function createPool(
address tokenA,
address tokenB,
uint24 fee
) external returns (address pool);
function isPaused() external view returns (bool);
function voter() external view returns (address);
function implementation() external view returns (address);
}
interface IPool {
error DepositsNotEqual();
error BelowMinimumK();
error FactoryAlreadySet();
error InsufficientLiquidity();
error InsufficientLiquidityMinted();
error InsufficientLiquidityBurned();
error InsufficientOutputAmount();
error InsufficientInputAmount();
error IsPaused();
error InvalidTo();
error K();
error NotEmergencyCouncil();
event Fees(address indexed sender, uint256 amount0, uint256 amount1);
event Mint(address indexed sender, uint256 amount0, uint256 amount1);
event Burn(
address indexed sender,
address indexed to,
uint256 amount0,
uint256 amount1
);
event Swap(
address indexed sender,
address indexed to,
uint256 amount0In,
uint256 amount1In,
uint256 amount0Out,
uint256 amount1Out
);
event Sync(uint256 reserve0, uint256 reserve1);
event Claim(
address indexed sender,
address indexed recipient,
uint256 amount0,
uint256 amount1
);
struct Observation {
uint256 timestamp;
uint256 reserve0Cumulative;
uint256 reserve1Cumulative;
}
function metadata()
external
view
returns (
uint256 dec0,
uint256 dec1,
uint256 r0,
uint256 r1,
bool st,
address t0,
address t1
);
function claimFees() external returns (uint256, uint256);
function tokens() external view returns (address, address);
function token0() external view returns (address);
function token1() external view returns (address);
function poolFees() external view returns (address);
function factory() external view returns (address);
function periodSize() external view returns (uint256);
function reserve0() external view returns (uint256);
function reserve1() external view returns (uint256);
function blockTimestampLast() external view returns (uint256);
function reserve0CumulativeLast() external view returns (uint256);
function reserve1CumulativeLast() external view returns (uint256);
function index0() external view returns (uint256);
function index1() external view returns (uint256);
function supplyIndex0(address) external view returns (uint256);
function supplyIndex1(address) external view returns (uint256);
function claimable0(address) external view returns (uint256);
function claimable1(address) external view returns (uint256);
function getK() external returns (uint256);
function setName(string calldata __name) external;
function setSymbol(string calldata __symbol) external;
function observationLength() external view returns (uint256);
function lastObservation() external view returns (Observation memory);
function stable() external view returns (bool);
function currentCumulativePrices()
external
view
returns (
uint256 reserve0Cumulative,
uint256 reserve1Cumulative,
uint256 blockTimestamp
);
function quote(
address tokenIn,
uint256 amountIn,
uint256 granularity
) external view returns (uint256 amountOut);
function prices(
address tokenIn,
uint256 amountIn,
uint256 points
) external view returns (uint256[] memory);
function sample(
address tokenIn,
uint256 amountIn,
uint256 points,
uint256 window
) external view returns (uint256[] memory);
function swap(
uint256 amount0Out,
uint256 amount1Out,
address to,
bytes calldata data
) external;
function burn(
address to
) external returns (uint256 amount0, uint256 amount1);
function mint(address to) external returns (uint256 liquidity);
function getReserves()
external
view
returns (
uint256 _reserve0,
uint256 _reserve1,
uint256 _blockTimestampLast
);
function getAmountOut(
uint256 amountIn,
address tokenIn
) external view returns (uint256);
function skim(address to) external;
function sync() external;
function initialize(
address _token0,
address _token1,
bool _stable
) external;
}
文件 2 的 8:BMXInterfaces.sol
pragma solidity 0.8.19;
interface IERC20 {
function totalSupply() external view returns (uint256);
function transfer(address recipient, uint amount) external returns (bool);
function decimals() external view returns (uint8);
function symbol() external view returns (string memory);
function balanceOf(address) external view returns (uint);
function transferFrom(
address sender,
address recipient,
uint amount
) external returns (bool);
function allowance(
address owner,
address spender
) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
}
interface VaultAPI is IERC20 {
function deposit() external returns (uint256);
function deposit(uint256 amount) external returns (uint256);
function deposit(
uint256 amount,
address recipient
) external returns (uint256);
function withdraw() external returns (uint256);
function withdraw(uint256 maxShares) external returns (uint256);
function withdraw(
uint256 maxShares,
address recipient
) external returns (uint256);
function pricePerShare() external view returns (uint256);
}
interface IBMX is IERC20 {
function glp() external view returns (address);
function usdg() external view returns (address);
function cooldownDuration() external returns (uint256);
function getAumInUsdg(bool maximise) external view returns (uint256);
function underlyingToken() external view returns (address);
function lastAddedAt(address _account) external returns (uint256);
function getPaymentTokenAmountForExerciseLp(
uint256,
uint256
) external view returns (uint256, uint256);
function addLiquidity(
address _token,
uint256 _amount,
uint256 _minUsdg,
uint256 _minGlp
) external returns (uint256);
function unstakeAndRedeemGlp(
address _tokenOut,
uint256 _glpAmount,
uint256 _minOut,
address _receiver
) external returns (uint256);
function addLiquidityForAccount(
address _fundingAccount,
address _account,
address _token,
uint256 _amount,
uint256 _minUsdg,
uint256 _minGlp
) external returns (uint256);
function removeLiquidity(
address _tokenOut,
uint256 _glpAmount,
uint256 _minOut,
address _receiver
) external returns (uint256);
function removeLiquidityForAccount(
address _account,
address _tokenOut,
uint256 _glpAmount,
uint256 _minOut,
address _receiver
) external returns (uint256);
function setShortsTrackerAveragePriceWeight(
uint256 _shortsTrackerAveragePriceWeight
) external;
function setCooldownDuration(uint256 _cooldownDuration) external;
function exerciseLp(
uint256 _amount,
uint256 _maxPaymentAmount,
address _recipient,
uint256 _discount,
uint256 _deadline
) external returns (uint256, uint256);
function claimable(address) external view returns (uint256);
function pairAmounts(address) external view returns (uint256);
function depositBalances(address, address) external view returns (uint256);
function handleRewards(bool, bool, bool) external;
function withdraw() external;
function deposit(uint256) external;
function signalTransfer(address) external;
function acceptTransfer(address) external;
function getPairAmount(address, uint256) external view returns (uint256);
function mintAndStakeGlp(
address,
uint256,
uint256,
uint256
) external returns (uint256);
function updateCumulativeFundingRate(
address _collateralToken,
address _indexToken
) external returns (bool);
function validateIncreasePosition(
address _account,
address _collateralToken,
address _indexToken,
uint256 _sizeDelta,
bool _isLong
) external view;
function validateDecreasePosition(
address _account,
address _collateralToken,
address _indexToken,
uint256 _collateralDelta,
uint256 _sizeDelta,
bool _isLong,
address _receiver
) external view;
function getEntryFundingRate(
address _collateralToken,
address _indexToken,
bool _isLong
) external view returns (uint256);
function getPositionFee(
address _account,
address _collateralToken,
address _indexToken,
bool _isLong,
uint256 _sizeDelta
) external view returns (uint256);
function getFundingFee(
address _account,
address _collateralToken,
address _indexToken,
bool _isLong,
uint256 _size,
uint256 _entryFundingRate
) external view returns (uint256);
function getBuyUsdgFeeBasisPoints(
address _token,
uint256 _usdgAmount
) external view returns (uint256);
function getSellUsdgFeeBasisPoints(
address _token,
uint256 _usdgAmount
) external view returns (uint256);
function getSwapFeeBasisPoints(
address _tokenIn,
address _tokenOut,
uint256 _usdgAmount
) external view returns (uint256);
function isInitialized() external view returns (bool);
function adjustForDecimals(
uint256 _amount,
address _tokenDiv,
address _tokenMul
) external view returns (uint256);
function PRICE_PRECISION() external view returns (uint256);
function BASIS_POINTS_DIVISOR() external view returns (uint256);
function isSwapEnabled() external view returns (bool);
function isLeverageEnabled() external view returns (bool);
function setError(uint256 _errorCode, string calldata _error) external;
function router() external view returns (address);
function gov() external view returns (address);
function whitelistedTokenCount() external view returns (uint256);
function maxLeverage() external view returns (uint256);
function minProfitTime() external view returns (uint256);
function hasDynamicFees() external view returns (bool);
function fundingInterval() external view returns (uint256);
function totalTokenWeights() external view returns (uint256);
function getTargetUsdgAmount(
address _token
) external view returns (uint256);
function inManagerMode() external view returns (bool);
function inPrivateLiquidationMode() external view returns (bool);
function maxGasPrice() external view returns (uint256);
function approvedRouters(
address _account,
address _router
) external view returns (bool);
function isLiquidator(address _account) external view returns (bool);
function isManager(address _account) external view returns (bool);
function minProfitBasisPoints(
address _token
) external view returns (uint256);
function tokenBalances(address _token) external view returns (uint256);
function lastFundingTimes(address _token) external view returns (uint256);
function setMaxLeverage(uint256 _maxLeverage) external;
function setInManagerMode(bool _inManagerMode) external;
function setManager(address _manager, bool _isManager) external;
function setIsSwapEnabled(bool _isSwapEnabled) external;
function setIsLeverageEnabled(bool _isLeverageEnabled) external;
function setMaxGasPrice(uint256 _maxGasPrice) external;
function setUsdgAmount(address _token, uint256 _amount) external;
function setBufferAmount(address _token, uint256 _amount) external;
function setMaxGlobalShortSize(address _token, uint256 _amount) external;
function setInPrivateLiquidationMode(
bool _inPrivateLiquidationMode
) external;
function setLiquidator(address _liquidator, bool _isActive) external;
function setFundingRate(
uint256 _fundingInterval,
uint256 _fundingRateFactor,
uint256 _stableFundingRateFactor
) external;
function setFees(
uint256 _taxBasisPoints,
uint256 _stableTaxBasisPoints,
uint256 _mintBurnFeeBasisPoints,
uint256 _swapFeeBasisPoints,
uint256 _stableSwapFeeBasisPoints,
uint256 _marginFeeBasisPoints,
uint256 _liquidationFeeUsd,
uint256 _minProfitTime,
bool _hasDynamicFees
) external;
function setTokenConfig(
address _token,
uint256 _tokenDecimals,
uint256 _redemptionBps,
uint256 _minProfitBps,
uint256 _maxUsdgAmount,
bool _isStable,
bool _isShortable
) external;
function setPriceFeed(address _priceFeed) external;
function withdrawFees(
address _token,
address _receiver
) external returns (uint256);
function directPoolDeposit(address _token) external;
function buyUSDG(
address _token,
address _receiver
) external returns (uint256);
function sellUSDG(
address _token,
address _receiver
) external returns (uint256);
function swap(
address _tokenIn,
address _tokenOut,
address _receiver
) external returns (uint256);
function increasePosition(
address _account,
address _collateralToken,
address _indexToken,
uint256 _sizeDelta,
bool _isLong
) external;
function decreasePosition(
address _account,
address _collateralToken,
address _indexToken,
uint256 _collateralDelta,
uint256 _sizeDelta,
bool _isLong,
address _receiver
) external returns (uint256);
function validateLiquidation(
address _account,
address _collateralToken,
address _indexToken,
bool _isLong,
bool _raise
) external view returns (uint256, uint256);
function liquidatePosition(
address _account,
address _collateralToken,
address _indexToken,
bool _isLong,
address _feeReceiver
) external;
function tokenToUsdMin(
address _token,
uint256 _tokenAmount
) external view returns (uint256);
function priceFeed() external view returns (address);
function fundingRateFactor() external view returns (uint256);
function stableFundingRateFactor() external view returns (uint256);
function cumulativeFundingRates(
address _token
) external view returns (uint256);
function getNextFundingRate(address _token) external view returns (uint256);
function getFeeBasisPoints(
address _token,
uint256 _usdgDelta,
uint256 _feeBasisPoints,
uint256 _taxBasisPoints,
bool _increment
) external view returns (uint256);
function liquidationFeeUsd() external view returns (uint256);
function taxBasisPoints() external view returns (uint256);
function stableTaxBasisPoints() external view returns (uint256);
function mintBurnFeeBasisPoints() external view returns (uint256);
function swapFeeBasisPoints() external view returns (uint256);
function stableSwapFeeBasisPoints() external view returns (uint256);
function marginFeeBasisPoints() external view returns (uint256);
function allWhitelistedTokensLength() external view returns (uint256);
function allWhitelistedTokens(uint256) external view returns (address);
function whitelistedTokens(address _token) external view returns (bool);
function stableTokens(address _token) external view returns (bool);
function shortableTokens(address _token) external view returns (bool);
function feeReserves(address _token) external view returns (uint256);
function globalShortSizes(address _token) external view returns (uint256);
function globalShortAveragePrices(
address _token
) external view returns (uint256);
function maxGlobalShortSizes(
address _token
) external view returns (uint256);
function tokenDecimals(address _token) external view returns (uint256);
function tokenWeights(address _token) external view returns (uint256);
function guaranteedUsd(address _token) external view returns (uint256);
function poolAmounts(address _token) external view returns (uint256);
function bufferAmounts(address _token) external view returns (uint256);
function reservedAmounts(address _token) external view returns (uint256);
function usdgAmounts(address _token) external view returns (uint256);
function maxUsdgAmounts(address _token) external view returns (uint256);
function getLivePrice() external view returns (uint256);
function getRedemptionAmount(
address _token,
uint256 _usdgAmount
) external view returns (uint256);
function getMaxPrice(address _token) external view returns (uint256);
function getMinPrice(address _token) external view returns (uint256);
function getDelta(
address _indexToken,
uint256 _size,
uint256 _averagePrice,
bool _isLong,
uint256 _lastIncreasedTime
) external view returns (bool, uint256);
function getPosition(
address _account,
address _collateralToken,
address _indexToken,
bool _isLong
)
external
view
returns (
uint256,
uint256,
uint256,
uint256,
uint256,
uint256,
bool,
uint256
);
}
interface IWETH is IERC20 {
function deposit() external payable;
function transfer(address to, uint256 value) external returns (bool);
function withdraw(uint256) external;
}
interface IShareHelper {
function sharesToAmount(
address vault,
uint shares,
bool useCeiling
) external view returns (uint);
function amountToShares(
address vault,
uint amount,
bool useCeiling
) external view returns (uint);
}
文件 3 的 8:Clones.sol
pragma solidity ^0.8.0;
library Clones {
function clone(address implementation) internal returns (address instance) {
assembly {
mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
instance := create(0, 0x09, 0x37)
}
require(instance != address(0), "ERC1167: create failed");
}
function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
assembly {
mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
instance := create2(0, 0x09, 0x37, salt)
}
require(instance != address(0), "ERC1167: create2 failed");
}
function predictDeterministicAddress(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
assembly {
let ptr := mload(0x40)
mstore(add(ptr, 0x38), deployer)
mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)
mstore(add(ptr, 0x14), implementation)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)
mstore(add(ptr, 0x58), salt)
mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))
predicted := keccak256(add(ptr, 0x43), 0x55)
}
}
function predictDeterministicAddress(
address implementation,
bytes32 salt
) internal view returns (address predicted) {
return predictDeterministicAddress(implementation, salt, address(this));
}
}
文件 4 的 8:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 5 的 8:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1, "Math: mulDiv overflow");
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
文件 6 的 8:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 7 的 8:Ownable2Step.sol
pragma solidity ^0.8.0;
import "./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();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
}
文件 8 的 8:wBLTRouterV2.sol
pragma solidity 0.8.19;
import {Math} from "@openzeppelin/contracts@4.9.3/utils/math/Math.sol";
import {Ownable2Step} from "@openzeppelin/contracts@4.9.3/access/Ownable2Step.sol";
import {Clones} from "@openzeppelin/contracts@4.9.3/proxy/Clones.sol";
import {IFactoryRegistry, IPoolFactory, IPool} from "./interfaces/AerodromeInterfaces.sol";
import {IERC20, IWETH, IBMX, VaultAPI, IShareHelper} from "./interfaces/BMXInterfaces.sol";
contract wBLTRouterV2 is Ownable2Step {
struct Route {
address from;
address to;
bool stable;
}
address public constant defaultFactory =
0x420DD381b31aEf6683db6B902084cB0FFECe40Da;
IWETH public constant weth =
IWETH(0x4200000000000000000000000000000000000006);
uint256 internal immutable PRICE_PRECISION;
uint256 internal immutable BASIS_POINTS_DIVISOR;
address[] public bltTokens;
VaultAPI internal constant wBLT =
VaultAPI(0x4E74D4Db6c0726ccded4656d0BCE448876BB4C7A);
IBMX internal constant sBLT =
IBMX(0x64755939a80BC89E1D2d0f93A312908D348bC8dE);
IBMX internal constant rewardRouter =
IBMX(0x49A97680938B4F1f73816d1B70C3Ab801FAd124B);
IBMX internal constant morphexVault =
IBMX(0xec8d8D4b215727f3476FF0ab41c406FA99b4272C);
IBMX internal constant bltManager =
IBMX(0x9fAc7b75f367d5B35a6D6D0a09572eFcC3D406C5);
IBMX internal constant vaultUtils =
IBMX(0xec31c83C5689C66cb77DdB5378852F3707022039);
IShareHelper internal constant shareValueHelper =
IShareHelper(0x4d2ED72285206D2b4b59CDA21ED0a979ad1F497f);
constructor() {
sBLT.approve(address(wBLT), type(uint256).max);
updateAllowances();
PRICE_PRECISION = morphexVault.PRICE_PRECISION();
BASIS_POINTS_DIVISOR = morphexVault.BASIS_POINTS_DIVISOR();
}
modifier ensure(uint256 _deadline) {
require(_deadline >= block.timestamp, "Router: EXPIRED");
_;
}
receive() external payable {
assert(msg.sender == address(weth));
}
function updateAllowances() public onlyOwner {
for (uint256 i = 0; i < bltTokens.length; ++i) {
IERC20 token = IERC20(bltTokens[i]);
token.approve(address(bltManager), 0);
}
delete bltTokens;
uint256 tokensCount = morphexVault.whitelistedTokenCount();
for (uint256 i = 0; i < tokensCount; ++i) {
IERC20 token = IERC20(morphexVault.allWhitelistedTokens(i));
token.approve(address(bltManager), type(uint256).max);
bltTokens.push(address(token));
}
}
function getAmountsOut(
uint256 _amountIn,
Route[] memory _routes
) public view returns (uint256[] memory amounts) {
require(_routes.length >= 1, "Router: INVALID_PATH");
amounts = new uint256[](_routes.length + 1);
amounts[0] = _amountIn;
for (uint256 i = 0; i < _routes.length; i++) {
if (_routes[i].from == address(wBLT)) {
if (_isBLTToken(_routes[i].to)) {
amounts[i + 1] = getRedeemAmountWrappedBLT(
_routes[i].to,
amounts[i],
false
);
continue;
}
} else if (_routes[i].to == address(wBLT)) {
if (_isBLTToken(_routes[i].from)) {
amounts[i + 1] = getMintAmountWrappedBLT(
_routes[i].from,
amounts[i]
);
continue;
}
}
address pool = poolFor(
_routes[i].from,
_routes[i].to,
_routes[i].stable
);
if (IPoolFactory(defaultFactory).isPool(pool)) {
amounts[i + 1] = IPool(pool).getAmountOut(
amounts[i],
_routes[i].from
);
}
}
}
function swapExactTokensForETH(
uint256 _amountIn,
uint256 _amountOutMin,
Route[] calldata _routes,
address _to,
uint256 _deadline
) external ensure(_deadline) returns (uint256[] memory amounts) {
amounts = getAmountsOut(_amountIn, _routes);
require(
amounts[amounts.length - 1] >= _amountOutMin,
"Router: INSUFFICIENT_OUTPUT_AMOUNT"
);
require(
_routes[_routes.length - 1].to == address(weth),
"Router: END_ROUTE_IN_ETH_BOZO"
);
if (
_routes[0].from == address(wBLT) || _routes[0].to == address(wBLT)
) {
if (_isBLTToken(_routes[0].from) || _isBLTToken(_routes[0].to)) {
_safeTransferFrom(
_routes[0].from,
msg.sender,
address(this),
amounts[0]
);
} else {
_safeTransferFrom(
_routes[0].from,
msg.sender,
poolFor(_routes[0].from, _routes[0].to, _routes[0].stable),
amounts[0]
);
}
} else {
_safeTransferFrom(
_routes[0].from,
msg.sender,
poolFor(_routes[0].from, _routes[0].to, _routes[0].stable),
amounts[0]
);
}
_swap(amounts, _routes, address(this));
uint256 amountUnderlying = weth.balanceOf(address(this));
weth.withdraw(amountUnderlying);
_safeTransferETH(_to, amountUnderlying);
}
function swapExactETHForTokens(
uint256 _amountIn,
uint256 _amountOutMin,
Route[] calldata _routes,
address _to,
uint256 _deadline
) public payable ensure(_deadline) returns (uint256[] memory amounts) {
amounts = getAmountsOut(_amountIn, _routes);
require(
amounts[amounts.length - 1] >= _amountOutMin,
"Router: INSUFFICIENT_OUTPUT_AMOUNT"
);
weth.deposit{value: _amountIn}();
if (weth.balanceOf(address(this)) != _amountIn) {
revert("WETH not sent");
}
if (
_routes[0].from != address(weth) || _routes[0].to != address(wBLT)
) {
revert("Route must start WETH -> wBLT");
}
_swap(amounts, _routes, _to);
}
function swapExactTokensForTokens(
uint256 _amountIn,
uint256 _amountOutMin,
Route[] calldata _routes,
address _to,
uint256 _deadline
) external ensure(_deadline) returns (uint256[] memory amounts) {
amounts = getAmountsOut(_amountIn, _routes);
require(
amounts[amounts.length - 1] >= _amountOutMin,
"Router: INSUFFICIENT_OUTPUT_AMOUNT"
);
if (
_routes[0].from == address(wBLT) || _routes[0].to == address(wBLT)
) {
if (_isBLTToken(_routes[0].from) || _isBLTToken(_routes[0].to)) {
_safeTransferFrom(
_routes[0].from,
msg.sender,
address(this),
amounts[0]
);
} else {
_safeTransferFrom(
_routes[0].from,
msg.sender,
poolFor(_routes[0].from, _routes[0].to, _routes[0].stable),
amounts[0]
);
}
} else {
_safeTransferFrom(
_routes[0].from,
msg.sender,
poolFor(_routes[0].from, _routes[0].to, _routes[0].stable),
amounts[0]
);
}
_swap(amounts, _routes, _to);
}
function _swap(
uint256[] memory _amounts,
Route[] memory _routes,
address _to
) internal virtual {
for (uint256 i = 0; i < _routes.length; i++) {
(address token0, ) = sortTokens(_routes[i].from, _routes[i].to);
uint256 amountOut = _amounts[i + 1];
(uint256 amount0Out, uint256 amount1Out) = _routes[i].from == token0
? (uint256(0), amountOut)
: (amountOut, uint256(0));
bool directSend;
uint256 received;
address to;
if (_routes[i].from == address(wBLT)) {
if (_isBLTToken(_routes[i].to)) {
received = _withdrawFromWrappedBLT(_routes[i].to);
if (i < (_routes.length - 1)) {
directSend = true;
} else {
_safeTransfer(_routes[i].to, _to, received);
return;
}
}
} else if (_routes[i].to == address(wBLT)) {
if (_isBLTToken(_routes[i].from)) {
received = _depositToWrappedBLT(_routes[i].from);
if (i < (_routes.length - 1)) {
directSend = true;
} else {
_safeTransfer(_routes[i].to, _to, received);
return;
}
}
}
if (i == _routes.length - 1) {
to = _to;
} else if (
(_isBLTToken(_routes[i + 1].from) &&
_routes[i + 1].to == address(wBLT)) ||
(_isBLTToken(_routes[i + 1].to) &&
_routes[i + 1].from == address(wBLT))
) {
to = address(this);
} else {
to = poolFor(
_routes[i + 1].from,
_routes[i + 1].to,
_routes[i + 1].stable
);
}
if (directSend) {
_safeTransfer(_routes[i].to, to, received);
} else {
IPool(
poolFor(_routes[i].from, _routes[i].to, _routes[i].stable)
).swap(amount0Out, amount1Out, to, new bytes(0));
}
}
}
function getMintAmountWrappedBLT(
address _token,
uint256 _amount
) public view returns (uint256 wrappedBLTMintAmount) {
require(_amount > 0, "invalid _amount");
(uint256 aumInUsdg, uint256 bltSupply) = _getBltInfo(true);
uint256 price = morphexVault.getMinPrice(_token);
uint256 _precision = PRICE_PRECISION;
uint256 _divisor = BASIS_POINTS_DIVISOR;
uint256 usdgAmount = (_amount * price) / _precision;
usdgAmount = morphexVault.adjustForDecimals(
usdgAmount,
_token,
morphexVault.usdg()
);
uint256 feeBasisPoints = vaultUtils.getBuyUsdgFeeBasisPoints(
_token,
usdgAmount
);
uint256 afterFeeAmount = (_amount * (_divisor - feeBasisPoints)) /
_divisor;
uint256 usdgMintAmount = (afterFeeAmount * price) / _precision;
usdgMintAmount = morphexVault.adjustForDecimals(
usdgMintAmount,
_token,
morphexVault.usdg()
);
uint256 BLTMintAmount = aumInUsdg == 0
? usdgMintAmount
: (usdgMintAmount * bltSupply) / aumInUsdg;
wrappedBLTMintAmount = shareValueHelper.amountToShares(
address(wBLT),
BLTMintAmount,
false
);
}
function getRedeemAmountWrappedBLT(
address _tokenOut,
uint256 _amount,
bool _roundUp
) public view returns (uint256 underlyingReceived) {
require(_amount > 0, "invalid _amount");
_amount = shareValueHelper.sharesToAmount(
address(wBLT),
_amount,
_roundUp
);
(uint256 aumInUsdg, uint256 bltSupply) = _getBltInfo(false);
uint256 usdgAmount;
if (_roundUp) {
usdgAmount = Math.ceilDiv((_amount * aumInUsdg), bltSupply);
} else {
usdgAmount = (_amount * aumInUsdg) / bltSupply;
}
uint256 price;
if (_roundUp) {
price = morphexVault.getMinPrice(_tokenOut);
} else {
price = morphexVault.getMaxPrice(_tokenOut);
}
uint256 redeemAmount = (usdgAmount * PRICE_PRECISION) / price;
redeemAmount = morphexVault.adjustForDecimals(
redeemAmount,
morphexVault.usdg(),
_tokenOut
);
if (_roundUp) {
redeemAmount += 1;
}
uint256 feeBasisPoints = vaultUtils.getSellUsdgFeeBasisPoints(
_tokenOut,
usdgAmount
);
uint256 _divisor = BASIS_POINTS_DIVISOR;
if (_roundUp) {
underlyingReceived = Math.ceilDiv(
(redeemAmount * (_divisor - feeBasisPoints)),
_divisor
);
} else {
underlyingReceived = ((redeemAmount * (_divisor - feeBasisPoints)) /
_divisor);
}
}
function quoteRedeemAmountBLT(
address _underlyingToken,
uint256 _amount
) external view returns (uint256 wBLTAmount) {
require(_amount > 0, "invalid _amount");
_amount += 1;
(uint256 aumInUsdg, uint256 bltSupply) = _getBltInfo(false);
uint256 underlyingPrice = morphexVault.getMaxPrice(_underlyingToken);
uint256 usdgNeeded = Math.ceilDiv(
(_amount * underlyingPrice),
PRICE_PRECISION
);
uint256 bltAmount = (usdgNeeded * bltSupply) / aumInUsdg;
bltAmount = morphexVault.adjustForDecimals(
bltAmount,
morphexVault.usdg(),
_underlyingToken
);
bltAmount += 1;
uint256 _divisor = BASIS_POINTS_DIVISOR;
uint256 feeBasisPoints = vaultUtils.getSellUsdgFeeBasisPoints(
_underlyingToken,
usdgNeeded
);
bltAmount = Math.ceilDiv(
(bltAmount * _divisor),
(_divisor - feeBasisPoints)
);
wBLTAmount = shareValueHelper.amountToShares(
address(wBLT),
bltAmount,
true
);
}
function quoteMintAmountBLT(
address _underlyingToken,
uint256 _amount
) public view returns (uint256 startingTokenAmount) {
require(_amount > 0, "invalid _amount");
_amount = shareValueHelper.sharesToAmount(address(wBLT), _amount, true);
(uint256 aumInUsdg, uint256 bltSupply) = _getBltInfo(true);
uint256 usdgAmount = Math.ceilDiv((_amount * aumInUsdg), bltSupply);
uint256 tokenPrice = morphexVault.getMinPrice(_underlyingToken);
startingTokenAmount = Math.ceilDiv(
usdgAmount * PRICE_PRECISION,
tokenPrice
);
startingTokenAmount = morphexVault.adjustForDecimals(
startingTokenAmount,
morphexVault.usdg(),
_underlyingToken
);
startingTokenAmount += 1;
uint256 feeBasisPoints = vaultUtils.getBuyUsdgFeeBasisPoints(
_underlyingToken,
usdgAmount
);
uint256 _divisor = BASIS_POINTS_DIVISOR;
startingTokenAmount = Math.ceilDiv(
startingTokenAmount * _divisor,
(_divisor - feeBasisPoints)
);
}
function _getBltInfo(
bool _maximize
) internal view returns (uint256 aumInUsdg, uint256 bltSupply) {
bltSupply = sBLT.totalSupply();
aumInUsdg = bltManager.getAumInUsdg(_maximize);
}
function _isBLTToken(address _tokenToCheck) internal view returns (bool) {
for (uint256 i = 0; i < bltTokens.length; ++i) {
if (bltTokens[i] == _tokenToCheck) {
return true;
}
}
return false;
}
function _withdrawFromWrappedBLT(
address _targetToken
) internal returns (uint256) {
if (!_isBLTToken(_targetToken)) {
revert("Token not in wBLT");
}
uint256 toWithdraw = wBLT.withdraw(type(uint256).max, address(this));
return
rewardRouter.unstakeAndRedeemGlp(
_targetToken,
toWithdraw,
0,
address(this)
);
}
function _depositToWrappedBLT(
address _fromToken
) internal returns (uint256 tokens) {
if (!_isBLTToken(_fromToken)) {
revert("Token not in wBLT");
}
IERC20 token = IERC20(_fromToken);
uint256 newMlp = rewardRouter.mintAndStakeGlp(
address(_fromToken),
token.balanceOf(address(this)),
0,
0
);
tokens = wBLT.deposit(newMlp, address(this));
}
function poolFor(
address _tokenA,
address _tokenB,
bool _stable
) public view returns (address pool) {
(address token0, address token1) = sortTokens(_tokenA, _tokenB);
bytes32 salt = keccak256(abi.encodePacked(token0, token1, _stable));
pool = Clones.predictDeterministicAddress(
IPoolFactory(defaultFactory).implementation(),
salt,
defaultFactory
);
}
function sortTokens(
address _tokenA,
address _tokenB
) public pure returns (address token0, address token1) {
require(_tokenA != _tokenB, "Router: IDENTICAL_ADDRESSES");
(token0, token1) = _tokenA < _tokenB
? (_tokenA, _tokenB)
: (_tokenB, _tokenA);
require(token0 != address(0), "Router: ZERO_ADDRESS");
}
function getReserves(
address _tokenA,
address _tokenB,
bool _stable
) public view returns (uint256 reserveA, uint256 reserveB) {
(address token0, ) = sortTokens(_tokenA, _tokenB);
(uint256 reserve0, uint256 reserve1, ) = IPool(
poolFor(_tokenA, _tokenB, _stable)
).getReserves();
(reserveA, reserveB) = _tokenA == token0
? (reserve0, reserve1)
: (reserve1, reserve0);
}
function getAmountOut(
uint256 _amountIn,
address _tokenIn,
address _tokenOut
) public view returns (uint256 amount, bool stable) {
address pool = poolFor(_tokenIn, _tokenOut, true);
uint256 amountStable;
uint256 amountVolatile;
if (IPoolFactory(defaultFactory).isPool(pool)) {
amountStable = IPool(pool).getAmountOut(_amountIn, _tokenIn);
}
pool = poolFor(_tokenIn, _tokenOut, false);
if (IPoolFactory(defaultFactory).isPool(pool)) {
amountVolatile = IPool(pool).getAmountOut(_amountIn, _tokenIn);
}
return
amountStable > amountVolatile
? (amountStable, true)
: (amountVolatile, false);
}
function getAmountOut(
uint256 _amountIn,
address _tokenIn,
address _tokenOut,
bool _stable
) public view returns (uint256 amount) {
address pool = poolFor(_tokenIn, _tokenOut, _stable);
if (IPoolFactory(defaultFactory).isPool(pool)) {
amount = IPool(pool).getAmountOut(_amountIn, _tokenIn);
}
}
function _quoteLiquidity(
uint256 _amountA,
uint256 _reserveA,
uint256 _reserveB
) internal pure returns (uint256 amountB) {
require(_amountA > 0, "Router: INSUFFICIENT_AMOUNT");
require(
_reserveA > 0 && _reserveB > 0,
"Router: INSUFFICIENT_LIQUIDITY"
);
amountB = (_amountA * _reserveB) / _reserveA;
}
function _safeTransferETH(address _to, uint256 _value) internal {
(bool success, ) = _to.call{value: _value}(new bytes(0));
require(success, "TransferHelper: ETH_TRANSFER_FAILED");
}
function _safeTransfer(
address _token,
address _to,
uint256 _value
) internal {
require(_token.code.length > 0);
(bool success, bytes memory data) = _token.call(
abi.encodeWithSelector(IERC20.transfer.selector, _to, _value)
);
require(success && (data.length == 0 || abi.decode(data, (bool))));
}
function _safeTransferFrom(
address _token,
address _from,
address _to,
uint256 _value
) internal {
require(_token.code.length > 0);
(bool success, bytes memory data) = _token.call(
abi.encodeWithSelector(
IERC20.transferFrom.selector,
_from,
_to,
_value
)
);
require(success && (data.length == 0 || abi.decode(data, (bool))));
}
}
{
"compilationTarget": {
"contracts/wBLTRouterV2.sol": "wBLTRouterV2"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"bltTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"stable","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"bool","name":"_stable","type":"bool"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"internalType":"struct wBLTRouterV2.Route[]","name":"_routes","type":"tuple[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getMintAmountWrappedBLT","outputs":[{"internalType":"uint256","name":"wrappedBLTMintAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bool","name":"_roundUp","type":"bool"}],"name":"getRedeemAmountWrappedBLT","outputs":[{"internalType":"uint256","name":"underlyingReceived","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenA","type":"address"},{"internalType":"address","name":"_tokenB","type":"address"},{"internalType":"bool","name":"_stable","type":"bool"}],"name":"getReserves","outputs":[{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenA","type":"address"},{"internalType":"address","name":"_tokenB","type":"address"},{"internalType":"bool","name":"_stable","type":"bool"}],"name":"poolFor","outputs":[{"internalType":"address","name":"pool","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_underlyingToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"quoteMintAmountBLT","outputs":[{"internalType":"uint256","name":"startingTokenAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_underlyingToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"quoteRedeemAmountBLT","outputs":[{"internalType":"uint256","name":"wBLTAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenA","type":"address"},{"internalType":"address","name":"_tokenB","type":"address"}],"name":"sortTokens","outputs":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"uint256","name":"_amountOutMin","type":"uint256"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"internalType":"struct wBLTRouterV2.Route[]","name":"_routes","type":"tuple[]"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"uint256","name":"_amountOutMin","type":"uint256"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"internalType":"struct wBLTRouterV2.Route[]","name":"_routes","type":"tuple[]"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"uint256","name":"_amountOutMin","type":"uint256"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"stable","type":"bool"}],"internalType":"struct wBLTRouterV2.Route[]","name":"_routes","type":"tuple[]"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateAllowances","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]