Files
smom-dbis-138/contracts/bridge/trustless/pilot/Chain138PilotDexVenues.sol
defiQUG 76aa419320 feat: bridges, PMM, flash workflow, token-aggregation, and deployment docs
- CCIP/trustless bridge contracts, GRU tokens, DEX/PMM tests, reserve vault.
- Token-aggregation service routes, planner, chain config, relay env templates.
- Config snapshots and multi-chain deployment markdown updates.
- gitignore services/btc-intake/dist/ (tsc output); do not track dist.

Run forge build && forge test before deploy (large solc graph).

Made-with: Cursor
2026-04-07 23:40:52 -07:00

597 lines
22 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IAggregationRouter.sol";
import "../interfaces/IBalancerVault.sol";
import "../interfaces/ICurvePool.sol";
import "../interfaces/ISwapRouter.sol";
library Chain138PilotVenueMath {
function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
require(tokenA != address(0) && tokenB != address(0) && tokenA != tokenB, "Chain138PilotVenueMath: invalid tokens");
(token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
}
function pairKey(address tokenA, address tokenB, uint24 fee) internal pure returns (bytes32) {
(address token0, address token1) = sortTokens(tokenA, tokenB);
return keccak256(abi.encodePacked(token0, token1, fee));
}
function pairKey(address tokenA, address tokenB) internal pure returns (bytes32) {
(address token0, address token1) = sortTokens(tokenA, tokenB);
return keccak256(abi.encodePacked(token0, token1));
}
function constantProductQuote(
uint256 reserveIn,
uint256 reserveOut,
uint256 amountIn,
uint256 feeBps
) internal pure returns (uint256 amountOut) {
if (reserveIn == 0 || reserveOut == 0 || amountIn == 0 || feeBps >= 10_000) {
return 0;
}
uint256 amountInWithFee = amountIn * (10_000 - feeBps);
return (reserveOut * amountInWithFee) / (reserveIn * 10_000 + amountInWithFee);
}
}
contract Chain138PilotOwned {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
modifier onlyOwner() {
require(msg.sender == owner, "Chain138PilotOwned: not owner");
_;
}
constructor() {
owner = msg.sender;
emit OwnershipTransferred(address(0), msg.sender);
}
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "Chain138PilotOwned: zero owner");
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
contract Chain138PilotUniswapV3Router is Chain138PilotOwned, ISwapRouter {
using SafeERC20 for IERC20;
struct Pool {
address token0;
address token1;
uint24 fee;
uint256 reserve0;
uint256 reserve1;
bool exists;
}
mapping(bytes32 => Pool) private pools;
event PairSeeded(bytes32 indexed poolKey, address indexed token0, address indexed token1, uint24 fee, uint256 amount0, uint256 amount1);
event PairFunded(bytes32 indexed poolKey, uint256 amount0, uint256 amount1);
event Swapped(bytes32 indexed poolKey, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);
function seedPair(
address tokenA,
address tokenB,
uint24 fee,
uint256 amountA,
uint256 amountB
) external onlyOwner returns (bytes32 poolKey) {
require(amountA > 0 && amountB > 0, "Chain138PilotUniswapV3Router: zero seed");
poolKey = Chain138PilotVenueMath.pairKey(tokenA, tokenB, fee);
Pool storage pool = pools[poolKey];
(address token0, address token1) = Chain138PilotVenueMath.sortTokens(tokenA, tokenB);
if (!pool.exists) {
pool.token0 = token0;
pool.token1 = token1;
pool.fee = fee;
pool.exists = true;
emit PairSeeded(
poolKey,
token0,
token1,
fee,
tokenA == token0 ? amountA : amountB,
tokenA == token0 ? amountB : amountA
);
}
_fundPool(poolKey, tokenA, tokenB, amountA, amountB);
}
function fundPair(
address tokenA,
address tokenB,
uint24 fee,
uint256 amountA,
uint256 amountB
) external onlyOwner {
bytes32 poolKey = Chain138PilotVenueMath.pairKey(tokenA, tokenB, fee);
require(pools[poolKey].exists, "Chain138PilotUniswapV3Router: pair missing");
_fundPool(poolKey, tokenA, tokenB, amountA, amountB);
}
function getPairReserves(
address tokenA,
address tokenB,
uint24 fee
) external view returns (uint256 reserveIn, uint256 reserveOut, bool exists) {
bytes32 poolKey = Chain138PilotVenueMath.pairKey(tokenA, tokenB, fee);
Pool storage pool = pools[poolKey];
if (!pool.exists) {
return (0, 0, false);
}
if (tokenA == pool.token0) {
return (pool.reserve0, pool.reserve1, true);
}
return (pool.reserve1, pool.reserve0, true);
}
function quoteExactInputSingle(
address tokenIn,
address tokenOut,
uint24 fee,
uint256 amountIn,
uint160
) external view returns (uint256 amountOut) {
(uint256 reserveIn, uint256 reserveOut, bool exists) = this.getPairReserves(tokenIn, tokenOut, fee);
require(exists, "Chain138PilotUniswapV3Router: pair missing");
return Chain138PilotVenueMath.constantProductQuote(reserveIn, reserveOut, amountIn, fee / 100);
}
function quoteExactInput(bytes calldata path, uint256 amountIn) external view returns (uint256 amountOut) {
(address tokenIn, address tokenOut, uint24 fee) = _decodeSingleHopPath(path);
return this.quoteExactInputSingle(tokenIn, tokenOut, fee, amountIn, 0);
}
function exactInputSingle(
ExactInputSingleParams calldata params
) external payable override returns (uint256 amountOut) {
amountOut = _swap(
params.tokenIn,
params.tokenOut,
params.fee,
params.amountIn,
params.amountOutMinimum,
params.recipient
);
}
function exactInput(
ExactInputParams calldata params
) external payable override returns (uint256 amountOut) {
(address tokenIn, address tokenOut, uint24 fee) = _decodeSingleHopPath(params.path);
amountOut = _swap(
tokenIn,
tokenOut,
fee,
params.amountIn,
params.amountOutMinimum,
params.recipient
);
}
function _fundPool(
bytes32 poolKey,
address tokenA,
address tokenB,
uint256 amountA,
uint256 amountB
) internal {
Pool storage pool = pools[poolKey];
IERC20(tokenA).safeTransferFrom(msg.sender, address(this), amountA);
IERC20(tokenB).safeTransferFrom(msg.sender, address(this), amountB);
if (tokenA == pool.token0) {
pool.reserve0 += amountA;
pool.reserve1 += amountB;
emit PairFunded(poolKey, amountA, amountB);
} else {
pool.reserve0 += amountB;
pool.reserve1 += amountA;
emit PairFunded(poolKey, amountB, amountA);
}
}
function _swap(
address tokenIn,
address tokenOut,
uint24 fee,
uint256 amountIn,
uint256 minAmountOut,
address recipient
) internal returns (uint256 amountOut) {
bytes32 poolKey = Chain138PilotVenueMath.pairKey(tokenIn, tokenOut, fee);
Pool storage pool = pools[poolKey];
require(pool.exists, "Chain138PilotUniswapV3Router: pair missing");
bool inputIsToken0 = tokenIn == pool.token0;
uint256 reserveIn = inputIsToken0 ? pool.reserve0 : pool.reserve1;
uint256 reserveOut = inputIsToken0 ? pool.reserve1 : pool.reserve0;
IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
amountOut = Chain138PilotVenueMath.constantProductQuote(reserveIn, reserveOut, amountIn, fee / 100);
require(amountOut >= minAmountOut, "Chain138PilotUniswapV3Router: insufficient output");
if (inputIsToken0) {
pool.reserve0 += amountIn;
pool.reserve1 -= amountOut;
} else {
pool.reserve1 += amountIn;
pool.reserve0 -= amountOut;
}
IERC20(tokenOut).safeTransfer(recipient, amountOut);
emit Swapped(poolKey, tokenIn, tokenOut, amountIn, amountOut);
}
function _decodeSingleHopPath(bytes memory path) internal pure returns (address tokenIn, address tokenOut, uint24 fee) {
require(path.length == 43, "Chain138PilotUniswapV3Router: single hop only");
assembly {
tokenIn := shr(96, mload(add(path, 32)))
fee := shr(232, mload(add(path, 52)))
tokenOut := shr(96, mload(add(path, 55)))
}
}
}
contract Chain138PilotBalancerVault is Chain138PilotOwned, IBalancerVault {
using SafeERC20 for IERC20;
struct Pool {
address token0;
address token1;
uint256 reserve0;
uint256 reserve1;
uint256 feeBps;
bool exists;
}
mapping(bytes32 => Pool) private pools;
event PoolSeeded(bytes32 indexed poolId, address indexed token0, address indexed token1, uint256 amount0, uint256 amount1, uint256 feeBps);
event PoolFunded(bytes32 indexed poolId, uint256 amount0, uint256 amount1);
event Swapped(bytes32 indexed poolId, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);
function seedPool(
bytes32 poolId,
address token0,
address token1,
uint256 amount0,
uint256 amount1,
uint256 feeBps
) external onlyOwner {
require(poolId != bytes32(0), "Chain138PilotBalancerVault: zero poolId");
require(amount0 > 0 && amount1 > 0, "Chain138PilotBalancerVault: zero seed");
Pool storage pool = pools[poolId];
if (!pool.exists) {
pool.token0 = token0;
pool.token1 = token1;
pool.feeBps = feeBps;
pool.exists = true;
emit PoolSeeded(poolId, token0, token1, amount0, amount1, feeBps);
}
_fund(poolId, amount0, amount1);
}
function fundPool(bytes32 poolId, uint256 amount0, uint256 amount1) external onlyOwner {
require(pools[poolId].exists, "Chain138PilotBalancerVault: pool missing");
_fund(poolId, amount0, amount1);
}
function swap(
SingleSwap memory singleSwap,
FundManagement memory funds,
uint256 limit,
uint256 deadline
) external payable override returns (uint256 amountCalculated) {
require(deadline >= block.timestamp, "Chain138PilotBalancerVault: expired");
Pool storage pool = pools[singleSwap.poolId];
require(pool.exists, "Chain138PilotBalancerVault: pool missing");
require(singleSwap.kind == SwapKind.GIVEN_IN, "Chain138PilotBalancerVault: GIVEN_IN only");
bool inputIsToken0;
if (singleSwap.assetIn == pool.token0 && singleSwap.assetOut == pool.token1) {
inputIsToken0 = true;
} else if (singleSwap.assetIn == pool.token1 && singleSwap.assetOut == pool.token0) {
inputIsToken0 = false;
} else {
revert("Chain138PilotBalancerVault: bad assets");
}
uint256 reserveIn = inputIsToken0 ? pool.reserve0 : pool.reserve1;
uint256 reserveOut = inputIsToken0 ? pool.reserve1 : pool.reserve0;
IERC20(singleSwap.assetIn).safeTransferFrom(funds.sender, address(this), singleSwap.amount);
amountCalculated = Chain138PilotVenueMath.constantProductQuote(reserveIn, reserveOut, singleSwap.amount, pool.feeBps);
require(amountCalculated >= limit, "Chain138PilotBalancerVault: below limit");
if (inputIsToken0) {
pool.reserve0 += singleSwap.amount;
pool.reserve1 -= amountCalculated;
} else {
pool.reserve1 += singleSwap.amount;
pool.reserve0 -= amountCalculated;
}
IERC20(singleSwap.assetOut).safeTransfer(funds.recipient, amountCalculated);
emit Swapped(singleSwap.poolId, singleSwap.assetIn, singleSwap.assetOut, singleSwap.amount, amountCalculated);
}
function getPool(bytes32 poolId) external view override returns (address poolAddress, uint8 specialization) {
require(pools[poolId].exists, "Chain138PilotBalancerVault: pool missing");
return (address(this), 0);
}
function queryBatchSwap(
SwapKind kind,
SingleSwap[] memory swaps,
address[] memory
) external view override returns (int256[] memory assetDeltas) {
require(kind == SwapKind.GIVEN_IN, "Chain138PilotBalancerVault: GIVEN_IN only");
assetDeltas = new int256[](swaps.length > 0 ? 2 : 0);
if (swaps.length == 0) {
return assetDeltas;
}
Pool storage pool = pools[swaps[0].poolId];
bool inputIsToken0 = swaps[0].assetIn == pool.token0;
uint256 reserveIn = inputIsToken0 ? pool.reserve0 : pool.reserve1;
uint256 reserveOut = inputIsToken0 ? pool.reserve1 : pool.reserve0;
uint256 amountOut = Chain138PilotVenueMath.constantProductQuote(reserveIn, reserveOut, swaps[0].amount, pool.feeBps);
assetDeltas[0] = int256(swaps[0].amount);
assetDeltas[1] = -int256(amountOut);
}
function getPoolTokens(
bytes32 poolId
) external view override returns (address[] memory tokens, uint256[] memory balances, uint256 lastChangeBlock) {
Pool storage pool = pools[poolId];
require(pool.exists, "Chain138PilotBalancerVault: pool missing");
tokens = new address[](2);
balances = new uint256[](2);
tokens[0] = pool.token0;
tokens[1] = pool.token1;
balances[0] = pool.reserve0;
balances[1] = pool.reserve1;
return (tokens, balances, block.number);
}
function _fund(bytes32 poolId, uint256 amount0, uint256 amount1) internal {
Pool storage pool = pools[poolId];
IERC20(pool.token0).safeTransferFrom(msg.sender, address(this), amount0);
IERC20(pool.token1).safeTransferFrom(msg.sender, address(this), amount1);
pool.reserve0 += amount0;
pool.reserve1 += amount1;
emit PoolFunded(poolId, amount0, amount1);
}
}
contract Chain138PilotCurve3Pool is Chain138PilotOwned, ICurvePool {
using SafeERC20 for IERC20;
address[3] private _coins;
uint256[3] private _reserves;
uint256 public immutable feeBps;
event Funded(uint256 amount0, uint256 amount1, uint256 amount2);
event Exchanged(int128 indexed i, int128 indexed j, uint256 dx, uint256 dy);
constructor(address token0, address token1, address token2, uint256 feeBps_) {
require(token0 != address(0) && token1 != address(0), "Chain138PilotCurve3Pool: invalid tokens");
_coins[0] = token0;
_coins[1] = token1;
_coins[2] = token2;
feeBps = feeBps_;
}
function fund(uint256 amount0, uint256 amount1, uint256 amount2) external onlyOwner {
if (amount0 > 0) IERC20(_coins[0]).safeTransferFrom(msg.sender, address(this), amount0);
if (amount1 > 0) IERC20(_coins[1]).safeTransferFrom(msg.sender, address(this), amount1);
if (_coins[2] != address(0) && amount2 > 0) IERC20(_coins[2]).safeTransferFrom(msg.sender, address(this), amount2);
_reserves[0] += amount0;
_reserves[1] += amount1;
_reserves[2] += amount2;
emit Funded(amount0, amount1, amount2);
}
function reserves(uint256 index) external view returns (uint256) {
return _reserves[index];
}
function exchange(
int128 i,
int128 j,
uint256 dx,
uint256 min_dy
) external payable override returns (uint256 dy) {
dy = _exchange(i, j, dx, min_dy, false);
}
function exchange_underlying(
int128 i,
int128 j,
uint256 dx,
uint256 min_dy
) external payable override returns (uint256 dy) {
dy = _exchange(i, j, dx, min_dy, true);
}
function get_dy(
int128 i,
int128 j,
uint256 dx
) public view override returns (uint256 dy) {
uint256 ui = uint256(uint128(i));
uint256 uj = uint256(uint128(j));
require(ui < 3 && uj < 3 && ui != uj, "Chain138PilotCurve3Pool: bad indexes");
require(_coins[ui] != address(0) && _coins[uj] != address(0), "Chain138PilotCurve3Pool: token missing");
uint256 reserveIn = _reserves[ui];
uint256 reserveOut = _reserves[uj];
require(reserveIn > 0 && reserveOut > 0, "Chain138PilotCurve3Pool: empty reserves");
uint256 grossOut = (dx * reserveOut) / reserveIn;
dy = (grossOut * (10_000 - feeBps)) / 10_000;
if (dy > reserveOut) {
dy = reserveOut;
}
}
function coins(uint256 i) external view override returns (address) {
return _coins[i];
}
function _exchange(
int128 i,
int128 j,
uint256 dx,
uint256 min_dy,
bool
) internal returns (uint256 dy) {
uint256 ui = uint256(uint128(i));
uint256 uj = uint256(uint128(j));
dy = get_dy(i, j, dx);
require(dy >= min_dy, "Chain138PilotCurve3Pool: insufficient output");
IERC20(_coins[ui]).safeTransferFrom(msg.sender, address(this), dx);
_reserves[ui] += dx;
_reserves[uj] -= dy;
IERC20(_coins[uj]).safeTransfer(msg.sender, dy);
emit Exchanged(i, j, dx, dy);
}
}
contract Chain138PilotOneInchAggregationRouter is Chain138PilotOwned, IAggregationRouter {
using SafeERC20 for IERC20;
struct Route {
address token0;
address token1;
uint256 reserve0;
uint256 reserve1;
uint256 feeBps;
bool exists;
}
mapping(bytes32 => Route) private routes;
event RouteSeeded(address indexed token0, address indexed token1, uint256 amount0, uint256 amount1, uint256 feeBps);
event RouteFunded(address indexed token0, address indexed token1, uint256 amount0, uint256 amount1);
event Swapped(address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut, address indexed recipient);
function seedRoute(
address tokenA,
address tokenB,
uint256 amountA,
uint256 amountB,
uint256 feeBps
) external onlyOwner {
require(amountA > 0 && amountB > 0, "Chain138PilotOneInchAggregationRouter: zero seed");
bytes32 key = Chain138PilotVenueMath.pairKey(tokenA, tokenB);
Route storage route = routes[key];
(address token0, address token1) = Chain138PilotVenueMath.sortTokens(tokenA, tokenB);
if (!route.exists) {
route.token0 = token0;
route.token1 = token1;
route.feeBps = feeBps;
route.exists = true;
emit RouteSeeded(
token0,
token1,
tokenA == token0 ? amountA : amountB,
tokenA == token0 ? amountB : amountA,
feeBps
);
}
_fundRoute(key, tokenA, tokenB, amountA, amountB);
}
function fundRoute(address tokenA, address tokenB, uint256 amountA, uint256 amountB) external onlyOwner {
bytes32 key = Chain138PilotVenueMath.pairKey(tokenA, tokenB);
require(routes[key].exists, "Chain138PilotOneInchAggregationRouter: route missing");
_fundRoute(key, tokenA, tokenB, amountA, amountB);
}
function getRouteReserves(
address tokenA,
address tokenB
) external view returns (uint256 reserveIn, uint256 reserveOut, bool exists) {
bytes32 key = Chain138PilotVenueMath.pairKey(tokenA, tokenB);
Route storage route = routes[key];
if (!route.exists) {
return (0, 0, false);
}
if (tokenA == route.token0) {
return (route.reserve0, route.reserve1, true);
}
return (route.reserve1, route.reserve0, true);
}
function quote(address tokenIn, address tokenOut, uint256 amountIn) external view returns (uint256 amountOut) {
(uint256 reserveIn, uint256 reserveOut, bool exists) = this.getRouteReserves(tokenIn, tokenOut);
require(exists, "Chain138PilotOneInchAggregationRouter: route missing");
return Chain138PilotVenueMath.constantProductQuote(reserveIn, reserveOut, amountIn, routes[Chain138PilotVenueMath.pairKey(tokenIn, tokenOut)].feeBps);
}
function swap(
address,
SwapDescription calldata desc,
bytes calldata,
bytes calldata
) external payable override returns (uint256 returnAmount, uint256 spentAmount) {
bytes32 key = Chain138PilotVenueMath.pairKey(desc.srcToken, desc.dstToken);
Route storage route = routes[key];
require(route.exists, "Chain138PilotOneInchAggregationRouter: route missing");
bool inputIsToken0 = desc.srcToken == route.token0;
uint256 reserveIn = inputIsToken0 ? route.reserve0 : route.reserve1;
uint256 reserveOut = inputIsToken0 ? route.reserve1 : route.reserve0;
IERC20(desc.srcToken).safeTransferFrom(msg.sender, address(this), desc.amount);
returnAmount = Chain138PilotVenueMath.constantProductQuote(reserveIn, reserveOut, desc.amount, route.feeBps);
require(returnAmount >= desc.minReturnAmount, "Chain138PilotOneInchAggregationRouter: insufficient output");
if (inputIsToken0) {
route.reserve0 += desc.amount;
route.reserve1 -= returnAmount;
} else {
route.reserve1 += desc.amount;
route.reserve0 -= returnAmount;
}
IERC20(desc.dstToken).safeTransfer(desc.dstReceiver, returnAmount);
emit Swapped(desc.srcToken, desc.dstToken, desc.amount, returnAmount, desc.dstReceiver);
return (returnAmount, desc.amount);
}
function _fundRoute(
bytes32 key,
address tokenA,
address tokenB,
uint256 amountA,
uint256 amountB
) internal {
Route storage route = routes[key];
IERC20(tokenA).safeTransferFrom(msg.sender, address(this), amountA);
IERC20(tokenB).safeTransferFrom(msg.sender, address(this), amountB);
if (tokenA == route.token0) {
route.reserve0 += amountA;
route.reserve1 += amountB;
emit RouteFunded(route.token0, route.token1, amountA, amountB);
} else {
route.reserve0 += amountB;
route.reserve1 += amountA;
emit RouteFunded(route.token0, route.token1, amountB, amountA);
}
}
}