Source Code
Overview
S Balance
S Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ThenaAdapterFix
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../interfaces/IAdapter.sol";
import "../interfaces/ISolidly.sol";
import "../interfaces/IERC20.sol";
/**
* @title ThenaAdapterFix
* @notice Adapter for Thena DEX swaps with K-invariant protection for stable pools. When the initial getAmountOut
* result violates the K-invariant check, the adapter performs binary search between 95% of the original result
* and the full result to find the maximum safe amountOut that preserves pool stability.
* @dev This contract implements enhanced safety mechanisms for stable pool swaps by validating the K-invariant
* (K = x³y + y³x) before execution. For volatile pools, it executes direct swaps without additional validation.
* The binary search algorithm ensures optimal amountOut while maintaining mathematical correctness of the AMM.
*/
contract ThenaAdapterFix is IAdapter {
uint256 private constant MAX_ITERATIONS = 50; // Max iteration times
uint256 private constant PRECISION = 1e18; // Precision base
struct PoolInfo {
address token0;
address token1;
uint256 reserve0;
uint256 reserve1;
uint256 reserveIn;
uint256 reserveOut;
}
struct SearchResult {
uint256 amountOut;
uint256 iterations;
}
event AmountOutAdjusted(
address indexed pool,
uint256 originalAmountOut,
uint256 adjustedAmountOut,
uint256 iterations
);
/**
* @notice fromToken = token0, toToken = token1
* @param to receiver address
* @param pool pool address
* @param moreInfo encoded fee and isStable
*/
function sellBase(
address to,
address pool,
bytes memory moreInfo
) external override {
(uint256 fee, bool isStable) = abi.decode(moreInfo, (uint256, bool));
_executeSwap(pool, fee, true, to, isStable);
}
/**
* @notice fromToken = token1, toToken = token0
* @param to receiver address
* @param pool pool address
* @param moreInfo encoded fee and isStable
*/
function sellQuote(
address to,
address pool,
bytes memory moreInfo
) external override {
(uint256 fee, bool isStable) = abi.decode(moreInfo, (uint256, bool));
_executeSwap(pool, fee, false, to, isStable);
}
/**
* @notice execute swap
* @param pool pool address
* @param fee fee
* @param zeroForOne true if fromToken = token0, false if fromToken = token1
* @param to receiver address
* @param isStable true if pool is stable, false if pool is unstable
*/
function _executeSwap(
address pool,
uint256 fee,
bool zeroForOne,
address to,
bool isStable
) internal {
PoolInfo memory poolInfo = PoolInfo({
token0: address(0),
token1: address(0),
reserve0: 0,
reserve1: 0,
reserveIn: 0,
reserveOut: 0
});
poolInfo.token0 = IPair(pool).token0();
poolInfo.token1 = IPair(pool).token1();
(poolInfo.reserve0, poolInfo.reserve1,) = IPair(pool).getReserves();
address tokenIn = zeroForOne ? poolInfo.token0 : poolInfo.token1;
poolInfo.reserveIn = zeroForOne ? poolInfo.reserve0 : poolInfo.reserve1;
poolInfo.reserveOut = zeroForOne ? poolInfo.reserve1 : poolInfo.reserve0;
uint256 amountIn = IERC20(tokenIn).balanceOf(pool) - poolInfo.reserveIn;
uint256 amountOut = IPair(pool).getAmountOut(
amountIn,
tokenIn
);
if (!isStable) {
// unstable pair
_swap(pool, zeroForOne, amountOut, to);
} else {
// stable pair
SearchResult memory searchResult = _binarySearchSafeAmount(
poolInfo.token0,
poolInfo.token1,
poolInfo.reserveIn,
poolInfo.reserveOut,
amountIn,
fee,
amountOut
);
_swap(pool, zeroForOne, searchResult.amountOut, to);
if (searchResult.amountOut != amountOut) {
emit AmountOutAdjusted(pool, amountOut, searchResult.amountOut, searchResult.iterations);
}
}
}
function _swap(
address pool,
bool zeroForOne,
uint256 amountOut,
address to
) internal {
(uint256 amount0Out, uint256 amount1Out) = zeroForOne
? (uint256(0), amountOut)
: (amountOut, uint256(0));
IPair(pool).swap(amount0Out, amount1Out, to, "");
}
function _binarySearchSafeAmount(
address token0,
address token1,
uint256 reserveIn,
uint256 reserveOut,
uint256 amountIn,
uint256 fee,
uint256 originalAmountOut
) internal view returns (SearchResult memory) {
uint256 decimals0 = 10 ** IERC20(token0).decimals();
uint256 decimals1 = 10 ** IERC20(token1).decimals();
uint256 kBefore = _calculateKWithDecimals(
reserveIn,
reserveOut,
decimals0,
decimals1
);
uint256 amountInAfterFee = amountIn - (amountIn * fee) / 10000;
uint256 kAfter = _calculateKWithDecimals(
reserveIn + amountInAfterFee,
reserveOut - originalAmountOut,
decimals0,
decimals1
);
if (kAfter >= kBefore) {
return SearchResult({
amountOut: originalAmountOut,
iterations: 0
});
} else {
return _performBinarySearchWithFee(
reserveIn,
reserveOut,
amountInAfterFee,
originalAmountOut,
kBefore,
decimals0,
decimals1
);
}
}
/**
* @notice Execute binary search logic (with fee handling)
*/
function _performBinarySearchWithFee(
uint256 reserveIn,
uint256 reserveOut,
uint256 amountInAfterFee,
uint256 originalAmountOut,
uint256 kBefore,
uint256 decimals0,
uint256 decimals1
) internal pure returns (SearchResult memory) {
uint256 left = (originalAmountOut * 95) / 100;
uint256 right = originalAmountOut;
uint256 bestAmount = left;
uint256 i;
for (; i < MAX_ITERATIONS; i++) {
uint256 mid = (left + right) / 2;
uint256 kAfter = _calculateKWithDecimals(
reserveIn + amountInAfterFee,
reserveOut - mid,
decimals0,
decimals1
);
if (kAfter >= kBefore) {
bestAmount = mid;
left = mid + 1;
} else {
right = mid - 1;
}
if (left > right) break;
}
return SearchResult({
amountOut: bestAmount,
iterations: i
});
}
/**
* @notice Calculate K value for stable pair, same as Solidly Pair
*/
function _calculateKWithDecimals(
uint256 x,
uint256 y,
uint256 decimals0,
uint256 decimals1
) internal pure returns (uint256) {
// Stable pool: K = x³y + y³x
uint256 _x = (x * 1e18) / decimals0;
uint256 _y = (y * 1e18) / decimals1;
uint256 _a = (_x * _y) / 1e18;
uint256 _b = ((_x * _x) / 1e18 + (_y * _y) / 1e18);
return (_a * _b) / 1e18;
}
}/// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma abicoder v2;
interface IAdapter {
function sellBase(
address to,
address pool,
bytes memory data
) external;
function sellQuote(
address to,
address pool,
bytes memory data
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
event Transfer(address indexed from, address indexed to, uint256 value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view 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);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
interface IPair {
function getReserves()
external
view
returns (
uint256 _reserve0,
uint256 _reserve1,
uint256 _blockTimestampLast
);
function getAmountOut(
uint256 amountIn,
address tokenIn
) external view returns (uint);
function swap(
uint256 amount0Out,
uint256 amount1Out,
address to,
bytes calldata data
) external;
function token0() external view returns (address);
function token1() external view returns (address);
function tokens() external view returns (address, address);
function factory() external view returns (address);
function isStable() external view returns (bool);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"uint256","name":"originalAmountOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"adjustedAmountOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"iterations","type":"uint256"}],"name":"AmountOutAdjusted","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"pool","type":"address"},{"internalType":"bytes","name":"moreInfo","type":"bytes"}],"name":"sellBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"pool","type":"address"},{"internalType":"bytes","name":"moreInfo","type":"bytes"}],"name":"sellQuote","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50610bbc806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806330e6ae311461003b5780636f7929f214610050575b600080fd5b61004e610049366004610866565b610063565b005b61004e61005e366004610866565b610093565b6000808280602001905181019061007a919061093c565b9150915061008c8483600188856100b8565b5050505050565b600080828060200190518101906100aa919061093c565b9150915061008c8483600088855b60006040518060c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152509050856001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101639190610971565b6001600160a01b0390811682526040805163d21220a760e01b815290519188169163d21220a7916004808201926020929091908290030181865afa1580156101af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d39190610971565b81602001906001600160a01b031690816001600160a01b031681525050856001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561022e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102529190610995565b506060830152604082015260008461026e578160200151610271565b81515b905084610282578160600151610288565b81604001515b60808301528461029c5781604001516102a2565b81606001515b60a083015260808201516040516370a0823160e01b81526001600160a01b03898116600483015260009291908416906370a0823190602401602060405180830381865afa1580156102f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061031b91906109c3565b61032591906109f2565b6040516378a051ad60e11b8152600481018290526001600160a01b0384811660248301529192506000918a169063f140a35a90604401602060405180830381865afa158015610378573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039c91906109c3565b9050846103b4576103af8988838961044f565b610444565b60006103d58560000151866020015187608001518860a00151878e886104dd565b90506103e78a8983600001518a61044f565b8051821461044257805160208083015160408051868152928301939093528183015290516001600160a01b038c16917ffd45ceababb14a521e7d2c7e3aa37c2f54a392dcb897f486e90ec8ca10c4f6ea919081900360600190a25b505b505050505050505050565b6000808461045f57836000610463565b6000845b60405163022c0d9f60e01b815260048101839052602481018290526001600160a01b03868116604483015260806064830152600060848301529294509092509087169063022c0d9f9060a401600060405180830381600087803b1580156104c957600080fd5b505af1158015610442573d6000803e3d6000fd5b60408051808201909152600080825260208201526000886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610531573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105559190610a0b565b61056090600a610b12565b90506000886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c69190610a0b565b6105d190600a610b12565b905060006105e189898585610675565b905060006127106105f2888a610b21565b6105fc9190610b38565b61060690896109f2565b90506000610628610617838d610b5a565b610621898d6109f2565b8787610675565b905082811061065357604051806040016040528088815260200160008152509550505050505061066a565b6106628b8b848a878a8a61074b565b955050505050505b979650505050505050565b6000808361068b87670de0b6b3a7640000610b21565b6106959190610b38565b90506000836106ac87670de0b6b3a7640000610b21565b6106b69190610b38565b90506000670de0b6b3a76400006106cd8385610b21565b6106d79190610b38565b90506000670de0b6b3a76400006106ee8480610b21565b6106f89190610b38565b670de0b6b3a764000061070b8680610b21565b6107159190610b38565b61071f9190610b5a565b9050670de0b6b3a76400006107348284610b21565b61073e9190610b38565b9998505050505050505050565b60408051808201909152600080825260208201526000606461076e87605f610b21565b6107789190610b38565b9050858160005b603281101561081857600060026107968587610b5a565b6107a09190610b38565b905060006107c68c8f6107b39190610b5a565b838f6107bf91906109f2565b8b8b610675565b90508981106107e6578193508160016107df9190610b5a565b95506107f4565b6107f16001836109f2565b94505b84861115610803575050610818565b5050808061081090610b6d565b91505061077f565b6040805180820190915291825260208201529a9950505050505050505050565b6001600160a01b038116811461084d57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561087b57600080fd5b833561088681610838565b9250602084013561089681610838565b9150604084013567ffffffffffffffff808211156108b357600080fd5b818601915086601f8301126108c757600080fd5b8135818111156108d9576108d9610850565b604051601f8201601f19908116603f0116810190838211818310171561090157610901610850565b8160405282815289602084870101111561091a57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000806040838503121561094f57600080fd5b825191506020830151801515811461096657600080fd5b809150509250929050565b60006020828403121561098357600080fd5b815161098e81610838565b9392505050565b6000806000606084860312156109aa57600080fd5b8351925060208401519150604084015190509250925092565b6000602082840312156109d557600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610a0557610a056109dc565b92915050565b600060208284031215610a1d57600080fd5b815160ff8116811461098e57600080fd5b600181815b80851115610a69578160001904821115610a4f57610a4f6109dc565b80851615610a5c57918102915b93841c9390800290610a33565b509250929050565b600082610a8057506001610a05565b81610a8d57506000610a05565b8160018114610aa35760028114610aad57610ac9565b6001915050610a05565b60ff841115610abe57610abe6109dc565b50506001821b610a05565b5060208310610133831016604e8410600b8410161715610aec575081810a610a05565b610af68383610a2e565b8060001904821115610b0a57610b0a6109dc565b029392505050565b600061098e60ff841683610a71565b8082028115828204841417610a0557610a056109dc565b600082610b5557634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115610a0557610a056109dc565b600060018201610b7f57610b7f6109dc565b506001019056fea26469706673582212204016fcf7968e26f61f6c65d37ff2e8b94f9cced32bc2fd1f95c0d350cd91e1a164736f6c63430008110033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100365760003560e01c806330e6ae311461003b5780636f7929f214610050575b600080fd5b61004e610049366004610866565b610063565b005b61004e61005e366004610866565b610093565b6000808280602001905181019061007a919061093c565b9150915061008c8483600188856100b8565b5050505050565b600080828060200190518101906100aa919061093c565b9150915061008c8483600088855b60006040518060c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152509050856001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101639190610971565b6001600160a01b0390811682526040805163d21220a760e01b815290519188169163d21220a7916004808201926020929091908290030181865afa1580156101af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101d39190610971565b81602001906001600160a01b031690816001600160a01b031681525050856001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561022e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102529190610995565b506060830152604082015260008461026e578160200151610271565b81515b905084610282578160600151610288565b81604001515b60808301528461029c5781604001516102a2565b81606001515b60a083015260808201516040516370a0823160e01b81526001600160a01b03898116600483015260009291908416906370a0823190602401602060405180830381865afa1580156102f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061031b91906109c3565b61032591906109f2565b6040516378a051ad60e11b8152600481018290526001600160a01b0384811660248301529192506000918a169063f140a35a90604401602060405180830381865afa158015610378573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039c91906109c3565b9050846103b4576103af8988838961044f565b610444565b60006103d58560000151866020015187608001518860a00151878e886104dd565b90506103e78a8983600001518a61044f565b8051821461044257805160208083015160408051868152928301939093528183015290516001600160a01b038c16917ffd45ceababb14a521e7d2c7e3aa37c2f54a392dcb897f486e90ec8ca10c4f6ea919081900360600190a25b505b505050505050505050565b6000808461045f57836000610463565b6000845b60405163022c0d9f60e01b815260048101839052602481018290526001600160a01b03868116604483015260806064830152600060848301529294509092509087169063022c0d9f9060a401600060405180830381600087803b1580156104c957600080fd5b505af1158015610442573d6000803e3d6000fd5b60408051808201909152600080825260208201526000886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610531573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105559190610a0b565b61056090600a610b12565b90506000886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c69190610a0b565b6105d190600a610b12565b905060006105e189898585610675565b905060006127106105f2888a610b21565b6105fc9190610b38565b61060690896109f2565b90506000610628610617838d610b5a565b610621898d6109f2565b8787610675565b905082811061065357604051806040016040528088815260200160008152509550505050505061066a565b6106628b8b848a878a8a61074b565b955050505050505b979650505050505050565b6000808361068b87670de0b6b3a7640000610b21565b6106959190610b38565b90506000836106ac87670de0b6b3a7640000610b21565b6106b69190610b38565b90506000670de0b6b3a76400006106cd8385610b21565b6106d79190610b38565b90506000670de0b6b3a76400006106ee8480610b21565b6106f89190610b38565b670de0b6b3a764000061070b8680610b21565b6107159190610b38565b61071f9190610b5a565b9050670de0b6b3a76400006107348284610b21565b61073e9190610b38565b9998505050505050505050565b60408051808201909152600080825260208201526000606461076e87605f610b21565b6107789190610b38565b9050858160005b603281101561081857600060026107968587610b5a565b6107a09190610b38565b905060006107c68c8f6107b39190610b5a565b838f6107bf91906109f2565b8b8b610675565b90508981106107e6578193508160016107df9190610b5a565b95506107f4565b6107f16001836109f2565b94505b84861115610803575050610818565b5050808061081090610b6d565b91505061077f565b6040805180820190915291825260208201529a9950505050505050505050565b6001600160a01b038116811461084d57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561087b57600080fd5b833561088681610838565b9250602084013561089681610838565b9150604084013567ffffffffffffffff808211156108b357600080fd5b818601915086601f8301126108c757600080fd5b8135818111156108d9576108d9610850565b604051601f8201601f19908116603f0116810190838211818310171561090157610901610850565b8160405282815289602084870101111561091a57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b6000806040838503121561094f57600080fd5b825191506020830151801515811461096657600080fd5b809150509250929050565b60006020828403121561098357600080fd5b815161098e81610838565b9392505050565b6000806000606084860312156109aa57600080fd5b8351925060208401519150604084015190509250925092565b6000602082840312156109d557600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610a0557610a056109dc565b92915050565b600060208284031215610a1d57600080fd5b815160ff8116811461098e57600080fd5b600181815b80851115610a69578160001904821115610a4f57610a4f6109dc565b80851615610a5c57918102915b93841c9390800290610a33565b509250929050565b600082610a8057506001610a05565b81610a8d57506000610a05565b8160018114610aa35760028114610aad57610ac9565b6001915050610a05565b60ff841115610abe57610abe6109dc565b50506001821b610a05565b5060208310610133831016604e8410600b8410161715610aec575081810a610a05565b610af68383610a2e565b8060001904821115610b0a57610b0a6109dc565b029392505050565b600061098e60ff841683610a71565b8082028115828204841417610a0557610a056109dc565b600082610b5557634e487b7160e01b600052601260045260246000fd5b500490565b80820180821115610a0557610a056109dc565b600060018201610b7f57610b7f6109dc565b506001019056fea26469706673582212204016fcf7968e26f61f6c65d37ff2e8b94f9cced32bc2fd1f95c0d350cd91e1a164736f6c63430008110033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$99.87
Net Worth in S
Token Allocations
DAI
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $0.998743 | 100 | $99.87 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.