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

127 lines
4.8 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "./RouteTypesV2.sol";
import "./interfaces/IEnhancedSwapRouterV2.sol";
import "./interfaces/IBridgeIntentExecutor.sol";
contract IntentBridgeCoordinatorV2 is AccessControl, ReentrancyGuard {
using SafeERC20 for IERC20;
bytes32 public constant EXECUTOR_MANAGER_ROLE = keccak256("EXECUTOR_MANAGER_ROLE");
IEnhancedSwapRouterV2 public immutable swapRouter;
mapping(bytes32 => address) public bridgeExecutors;
event BridgeExecutorSet(bytes32 indexed bridgeType, address indexed executor);
event IntentExecuted(
bytes32 indexed intentHash,
bytes32 indexed bridgeReference,
bytes32 indexed destinationPlanHash,
address inputToken,
address bridgeToken,
uint256 amountIn,
uint256 bridgedAmount,
address recipient
);
error ZeroAddress();
error InvalidIntent();
error BridgeExecutorNotConfigured();
error BridgeValidationFailed(string reason);
constructor(address _swapRouter) {
if (_swapRouter == address(0)) revert ZeroAddress();
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(EXECUTOR_MANAGER_ROLE, msg.sender);
swapRouter = IEnhancedSwapRouterV2(_swapRouter);
}
function setBridgeExecutor(
bytes32 bridgeType,
address executor
) external onlyRole(EXECUTOR_MANAGER_ROLE) {
if (executor == address(0)) revert ZeroAddress();
bridgeExecutors[bridgeType] = executor;
emit BridgeExecutorSet(bridgeType, executor);
}
function executeIntent(
RouteTypesV2.BridgeIntentPlan calldata intent
) external payable nonReentrant returns (bytes32 bridgeReference, bytes32 destinationPlanHash) {
if (intent.deadline < block.timestamp) revert InvalidIntent();
if (intent.recipient == address(0)) revert InvalidIntent();
if (intent.sourcePlan.deadline < block.timestamp) revert InvalidIntent();
if (intent.sourcePlan.recipient != address(this)) revert InvalidIntent();
address bridgeExecutor = bridgeExecutors[intent.bridgeType];
if (bridgeExecutor == address(0)) revert BridgeExecutorNotConfigured();
uint256 bridgedAmount;
address bridgeToken;
if (intent.sourcePlan.inputToken == address(0)) {
bridgedAmount = swapRouter.executeRoute{value: intent.sourcePlan.amountIn}(intent.sourcePlan);
bridgeToken = intent.sourcePlan.outputToken;
} else {
IERC20(intent.sourcePlan.inputToken).safeTransferFrom(
msg.sender,
address(this),
intent.sourcePlan.amountIn
);
IERC20(intent.sourcePlan.inputToken).forceApprove(address(swapRouter), 0);
IERC20(intent.sourcePlan.inputToken).forceApprove(address(swapRouter), intent.sourcePlan.amountIn);
bridgedAmount = swapRouter.executeRoute(intent.sourcePlan);
bridgeToken = intent.sourcePlan.outputToken;
}
(bool ok, string memory reason) = IBridgeIntentExecutor(bridgeExecutor).validateBridge(
intent.bridgeType,
intent.bridgeData,
bridgeToken,
bridgedAmount,
intent.recipient
);
if (!ok) revert BridgeValidationFailed(reason);
IERC20(bridgeToken).forceApprove(bridgeExecutor, 0);
IERC20(bridgeToken).forceApprove(bridgeExecutor, bridgedAmount);
bridgeReference = IBridgeIntentExecutor(bridgeExecutor).executeBridge(
intent.bridgeType,
intent.bridgeData,
bridgeToken,
bridgedAmount,
intent.recipient
);
destinationPlanHash = keccak256(
abi.encode(
intent.destinationPlan.chainId,
intent.destinationPlan.inputToken,
intent.destinationPlan.outputToken,
intent.destinationPlan.amountIn,
intent.destinationPlan.minAmountOut,
intent.destinationPlan.recipient,
intent.destinationPlan.deadline,
intent.destinationPlan.legs
)
);
emit IntentExecuted(
keccak256(abi.encode(intent.bridgeType, intent.recipient, intent.deadline)),
bridgeReference,
destinationPlanHash,
intent.sourcePlan.inputToken == address(0) ? address(0) : intent.sourcePlan.inputToken,
bridgeToken,
intent.sourcePlan.amountIn,
bridgedAmount,
intent.recipient
);
}
receive() external payable {}
}