// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {Script, console} from "forge-std/Script.sol"; import {CWReserveVerifier} from "../contracts/bridge/integration/CWReserveVerifier.sol"; interface ICWMultiTokenBridgeL1Admin { function setReserveVerifier(address newVerifier) external; } /** * @title DeployCWReserveVerifier * @notice Deploy and optionally attach/configure the cW canonical reserve verifier. * * Env: * PRIVATE_KEY (required) * CW_L1_BRIDGE (required) * CW_STABLECOIN_RESERVE_VAULT (optional) * CW_RESERVE_SYSTEM (optional) * CW_ATTACH_VERIFIER_TO_L1=1 (optional, default 1) * CW_CANONICAL_USDT / CW_CANONICAL_USDC (optional) * CW_USDT_RESERVE_ASSET / CW_USDC_RESERVE_ASSET (optional, used for reserve-system balance checks) * CW_REQUIRE_VAULT_BACKING=1 (optional, defaults to 1 when vault address is set) * CW_REQUIRE_RESERVE_SYSTEM_BALANCE=1 (optional, defaults to 1 when reserve system address is set) * CW_REQUIRE_TOKEN_OWNER_MATCH_VAULT=1 (optional, defaults to 1 when vault address is set) */ contract DeployCWReserveVerifier is Script { function run() external { uint256 privateKey = vm.envUint("PRIVATE_KEY"); address admin = vm.addr(privateKey); address l1Bridge = vm.envAddress("CW_L1_BRIDGE"); address stablecoinReserveVault = vm.envOr("CW_STABLECOIN_RESERVE_VAULT", address(0)); address reserveSystem = vm.envOr("CW_RESERVE_SYSTEM", address(0)); bool attachVerifierToBridge = vm.envOr("CW_ATTACH_VERIFIER_TO_L1", uint256(1)) == 1; bool defaultRequireVaultBacking = stablecoinReserveVault != address(0); bool defaultRequireReserveSystemBalance = reserveSystem != address(0); bool defaultRequireTokenOwnerMatchVault = stablecoinReserveVault != address(0); bool requireVaultBacking = vm.envOr("CW_REQUIRE_VAULT_BACKING", defaultRequireVaultBacking ? uint256(1) : uint256(0)) == 1; bool requireReserveSystemBalance = vm.envOr("CW_REQUIRE_RESERVE_SYSTEM_BALANCE", defaultRequireReserveSystemBalance ? uint256(1) : uint256(0)) == 1; bool requireTokenOwnerMatchVault = vm.envOr("CW_REQUIRE_TOKEN_OWNER_MATCH_VAULT", defaultRequireTokenOwnerMatchVault ? uint256(1) : uint256(0)) == 1; address canonicalUSDT = vm.envOr("CW_CANONICAL_USDT", address(0)); address canonicalUSDC = vm.envOr("CW_CANONICAL_USDC", address(0)); address usdtReserveAsset = vm.envOr("CW_USDT_RESERVE_ASSET", address(0)); address usdcReserveAsset = vm.envOr("CW_USDC_RESERVE_ASSET", address(0)); vm.startBroadcast(privateKey); CWReserveVerifier verifier = new CWReserveVerifier( admin, l1Bridge, stablecoinReserveVault, reserveSystem ); if (attachVerifierToBridge) { ICWMultiTokenBridgeL1Admin(l1Bridge).setReserveVerifier(address(verifier)); } if (canonicalUSDT != address(0)) { verifier.configureToken( canonicalUSDT, usdtReserveAsset, requireVaultBacking, requireReserveSystemBalance && usdtReserveAsset != address(0), requireTokenOwnerMatchVault ); } if (canonicalUSDC != address(0)) { verifier.configureToken( canonicalUSDC, usdcReserveAsset, requireVaultBacking, requireReserveSystemBalance && usdcReserveAsset != address(0), requireTokenOwnerMatchVault ); } vm.stopBroadcast(); console.log("CWReserveVerifier:", address(verifier)); console.log(" L1 bridge:", l1Bridge); console.log(" attached to bridge:", attachVerifierToBridge); console.log(" stablecoin reserve vault:", stablecoinReserveVault); console.log(" reserve system:", reserveSystem); console.log(" requireVaultBacking:", requireVaultBacking); console.log(" requireReserveSystemBalance:", requireReserveSystemBalance); console.log(" requireTokenOwnerMatchVault:", requireTokenOwnerMatchVault); console.log(" configured cUSDT:", canonicalUSDT); console.log(" configured cUSDC:", canonicalUSDC); } }