Files
smom-dbis-138/contracts/bridge/trustless/adapters/CurveRouteExecutorAdapter.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

54 lines
2.0 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/ICurvePool.sol";
import "../RouteTypesV2.sol";
import "../interfaces/IRouteExecutorAdapter.sol";
contract CurveRouteExecutorAdapter is IRouteExecutorAdapter {
using SafeERC20 for IERC20;
function validate(
RouteTypesV2.RouteLeg calldata leg
) external pure override returns (bool ok, string memory reason) {
if (leg.provider != RouteTypesV2.Provider.Curve) {
return (false, "CurveRouteExecutorAdapter: invalid provider");
}
if (leg.target == address(0)) {
return (false, "CurveRouteExecutorAdapter: zero target");
}
if (leg.providerData.length == 0) {
return (false, "CurveRouteExecutorAdapter: missing providerData");
}
return (true, "");
}
function quote(
RouteTypesV2.RouteLeg calldata leg,
uint256 amountIn
) external view override returns (uint256 amountOut, uint256 gasEstimate) {
(int128 i, int128 j,) = abi.decode(leg.providerData, (int128, int128, bool));
amountOut = ICurvePool(leg.target).get_dy(i, j, amountIn);
gasEstimate = 190000;
}
function execute(
RouteTypesV2.RouteLeg calldata leg,
uint256 amountIn
) external override returns (uint256 amountOut) {
(int128 i, int128 j, bool useUnderlying) = abi.decode(leg.providerData, (int128, int128, bool));
IERC20(leg.tokenIn).forceApprove(leg.target, 0);
IERC20(leg.tokenIn).forceApprove(leg.target, amountIn);
if (useUnderlying) {
amountOut = ICurvePool(leg.target).exchange_underlying(i, j, amountIn, leg.minAmountOut);
} else {
amountOut = ICurvePool(leg.target).exchange(i, j, amountIn, leg.minAmountOut);
}
IERC20(leg.tokenOut).safeTransfer(msg.sender, amountOut);
}
}