// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/access/AccessControl.sol"; import "../interop/BridgeRegistry.sol"; import "../../iso4217w/TokenFactory.sol"; import "../../iso4217w/registry/TokenRegistry.sol"; /** * @title WTokenBridgeIntegration * @notice Automatically registers ISO-4217 W tokens with BridgeRegistry * @dev Extends TokenFactory to auto-register W tokens on creation */ contract WTokenBridgeIntegration is AccessControl { bytes32 public constant INTEGRATOR_ROLE = keccak256("INTEGRATOR_ROLE"); TokenFactory public tokenFactory; BridgeRegistry public bridgeRegistry; ITokenRegistry public wTokenRegistry; // Default bridge configuration for W tokens (more conservative due to compliance) uint256 public defaultMinBridgeAmount = 100e2; // 100 USD minimum uint256 public defaultMaxBridgeAmount = 10_000_000e2; // 10M USD maximum uint8 public defaultRiskLevel = 20; // Low risk (fiat-backed) uint256 public defaultBridgeFeeBps = 5; // 0.05% default fee (lower due to compliance) // Destination chain IDs (includes XRPL and Fabric in addition to EVM) uint256[] public defaultEvmDestinations; uint256[] public defaultNonEvmDestinations; // 0 for XRPL, 1 for Fabric (example) event WTokenRegistered( address indexed token, string indexed currencyCode, uint256[] destinationChainIds ); constructor( address admin, address tokenFactory_, address bridgeRegistry_, address wTokenRegistry_ ) { _grantRole(DEFAULT_ADMIN_ROLE, admin); _grantRole(INTEGRATOR_ROLE, admin); require(tokenFactory_ != address(0), "WTokenBridgeIntegration: zero token factory"); require(bridgeRegistry_ != address(0), "WTokenBridgeIntegration: zero bridge registry"); require(wTokenRegistry_ != address(0), "WTokenBridgeIntegration: zero W token registry"); tokenFactory = TokenFactory(tokenFactory_); bridgeRegistry = BridgeRegistry(bridgeRegistry_); wTokenRegistry = ITokenRegistry(wTokenRegistry_); // Set default EVM destinations defaultEvmDestinations.push(137); // Polygon defaultEvmDestinations.push(10); // Optimism defaultEvmDestinations.push(8453); // Base defaultEvmDestinations.push(42161); // Arbitrum defaultEvmDestinations.push(43114); // Avalanche defaultEvmDestinations.push(56); // BNB Chain defaultEvmDestinations.push(10143); // Monad defaultEvmDestinations.push(42793); // Etherlink (Tezos EVM L2) // Set default non-EVM destinations defaultNonEvmDestinations.push(0); // XRPL (0 = non-EVM identifier) defaultNonEvmDestinations.push(1); // Fabric (1 = non-EVM identifier) } /** * @notice Register a W token with bridge registry * @param currencyCode ISO-4217 currency code (e.g., "USD") * @param destinationChainIds Array of allowed destination chain IDs * @param minAmount Minimum bridge amount (in token decimals) * @param maxAmount Maximum bridge amount (in token decimals) * @param riskLevel Risk level (0-255) * @param bridgeFeeBps Bridge fee in basis points */ function registerWToken( string memory currencyCode, uint256[] memory destinationChainIds, uint256 minAmount, uint256 maxAmount, uint8 riskLevel, uint256 bridgeFeeBps ) public onlyRole(INTEGRATOR_ROLE) { address token = wTokenRegistry.getTokenAddress(currencyCode); require(token != address(0), "WTokenBridgeIntegration: token not found"); require(destinationChainIds.length > 0, "WTokenBridgeIntegration: no destinations"); require(minAmount > 0, "WTokenBridgeIntegration: zero min amount"); require(maxAmount >= minAmount, "WTokenBridgeIntegration: max < min"); require(bridgeFeeBps <= 10000, "WTokenBridgeIntegration: fee > 100%"); bridgeRegistry.registerToken( token, minAmount, maxAmount, destinationChainIds, riskLevel, bridgeFeeBps ); emit WTokenRegistered(token, currencyCode, destinationChainIds); } /** * @notice Register a W token with default configuration * @param currencyCode ISO-4217 currency code */ function registerWTokenDefault(string memory currencyCode) public onlyRole(INTEGRATOR_ROLE) { // Combine EVM and non-EVM destinations uint256[] memory allDestinations = new uint256[]( defaultEvmDestinations.length + defaultNonEvmDestinations.length ); uint256 i = 0; for (uint256 j = 0; j < defaultEvmDestinations.length; j++) { allDestinations[i++] = defaultEvmDestinations[j]; } for (uint256 j = 0; j < defaultNonEvmDestinations.length; j++) { allDestinations[i++] = defaultNonEvmDestinations[j]; } registerWToken( currencyCode, allDestinations, defaultMinBridgeAmount, defaultMaxBridgeAmount, defaultRiskLevel, defaultBridgeFeeBps ); } /** * @notice Register multiple W tokens with default configuration * @param currencyCodes Array of ISO-4217 currency codes */ function registerMultipleWTokensDefault(string[] memory currencyCodes) external onlyRole(INTEGRATOR_ROLE) { for (uint256 i = 0; i < currencyCodes.length; i++) { registerWTokenDefault(currencyCodes[i]); } } /** * @notice Set default bridge configuration */ function setDefaultMinBridgeAmount(uint256 minAmount) external onlyRole(DEFAULT_ADMIN_ROLE) { require(minAmount > 0, "WTokenBridgeIntegration: zero min amount"); defaultMinBridgeAmount = minAmount; } function setDefaultMaxBridgeAmount(uint256 maxAmount) external onlyRole(DEFAULT_ADMIN_ROLE) { require(maxAmount >= defaultMinBridgeAmount, "WTokenBridgeIntegration: max < min"); defaultMaxBridgeAmount = maxAmount; } function setDefaultRiskLevel(uint8 riskLevel) external onlyRole(DEFAULT_ADMIN_ROLE) { require(riskLevel <= 255, "WTokenBridgeIntegration: invalid risk level"); defaultRiskLevel = riskLevel; } function setDefaultBridgeFeeBps(uint256 feeBps) external onlyRole(DEFAULT_ADMIN_ROLE) { require(feeBps <= 10000, "WTokenBridgeIntegration: fee > 100%"); defaultBridgeFeeBps = feeBps; } function setDefaultEvmDestinations(uint256[] memory chainIds) external onlyRole(DEFAULT_ADMIN_ROLE) { require(chainIds.length > 0, "WTokenBridgeIntegration: no destinations"); defaultEvmDestinations = chainIds; } function setDefaultNonEvmDestinations(uint256[] memory chainIds) external onlyRole(DEFAULT_ADMIN_ROLE) { defaultNonEvmDestinations = chainIds; } }