Add mainnet checkpoint stack: ISO attestation, participant Etherscan surface, and services.
Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m3s
CI/CD Pipeline / Security Scanning (push) Successful in 2m18s
CI/CD Pipeline / Lint and Format (push) Failing after 34s
CI/CD Pipeline / Terraform Validation (push) Failing after 20s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 22s
Deploy ChainID 138 / Deploy ChainID 138 (push) Failing after 40s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 49s
OMNL reconcile anchor / Run omnl:reconcile and upload artifacts (push) Failing after 21s
Validation / validate-genesis (push) Successful in 25s
Validation / validate-terraform (push) Failing after 21s
Validation / validate-kubernetes (push) Failing after 8s
Validation / validate-smart-contracts (push) Failing after 8s
Validation / validate-security (push) Failing after 1m11s
Validation / validate-documentation (push) Failing after 14s
Verify Deployment / Verify Deployment (push) Failing after 45s

Ship AddressActivityRegistry V1/V2, ISO20022IntakeGateway, Chain138ParticipantSurface,
checkpoint hub contracts, checkpoint-core package, aggregator/indexer/sdk services,
relay profile guards, M00 diamond bridge facet, and OMNL compliance contracts.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
defiQUG
2026-05-25 00:30:45 -07:00
parent 9a83aa2034
commit c336809676
326 changed files with 21108 additions and 334 deletions

View File

@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {Script, console} from "forge-std/Script.sol";
import {CCIPRelayRouter} from "../contracts/relay/CCIPRelayRouter.sol";
import {CCIPRelayBridgeLINK} from "../contracts/relay/CCIPRelayBridgeLINK.sol";
/// @notice Deploy CCIPRelayBridgeLINK on destination chain and authorize on existing CCIPRelayRouter.
/// Env: PRIVATE_KEY, LINK_TOKEN_MAINNET (or DEST_LINK_ADDRESS), CCIP_RELAY_ROUTER_MAINNET
contract DeployCCIPRelayBridgeLINK is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
address link = vm.envAddress("LINK_TOKEN_MAINNET");
address relayRouter = vm.envAddress("CCIP_RELAY_ROUTER_MAINNET");
vm.startBroadcast(deployerPrivateKey);
CCIPRelayBridgeLINK linkBridge = new CCIPRelayBridgeLINK(link, relayRouter);
console.log("CCIPRelayBridgeLINK:", address(linkBridge));
CCIPRelayRouter(relayRouter).authorizeBridge(address(linkBridge));
console.log("Authorized on CCIPRelayRouter:", relayRouter);
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,45 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Script.sol";
import {IRouterClient} from "../contracts/ccip/IRouterClient.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @notice CCIP-send Chain 138 LINK to a destination-chain bridge contract (operator funding).
/// Env: PRIVATE_KEY, CCIP_ROUTER_CHAIN138, LINK_TOKEN_CHAIN138, DEST_SELECTOR, DEST_BRIDGE, LINK_AMOUNT_WEI
contract FundBridgeLinkViaCcip138 is Script {
function run() external {
uint256 deployerKey = vm.envUint("PRIVATE_KEY");
address router = vm.envAddress("CCIP_ROUTER_CHAIN138");
address link = vm.envAddress("LINK_TOKEN_CHAIN138");
uint64 destSelector = uint64(vm.envUint("DEST_SELECTOR"));
address destBridge = vm.envAddress("DEST_BRIDGE");
uint256 amount = vm.envUint("LINK_AMOUNT_WEI");
IRouterClient.TokenAmount[] memory tokenAmounts = new IRouterClient.TokenAmount[](1);
tokenAmounts[0] = IRouterClient.TokenAmount({
token: link,
amount: amount,
amountType: IRouterClient.TokenAmountType.Fiat
});
IRouterClient.EVM2AnyMessage memory message = IRouterClient.EVM2AnyMessage({
receiver: abi.encode(destBridge),
data: "",
tokenAmounts: tokenAmounts,
feeToken: link,
extraArgs: ""
});
uint256 fee = IRouterClient(router).getFee(destSelector, message);
console2.log("destBridge", destBridge);
console2.log("amount", amount);
console2.log("fee", fee);
vm.startBroadcast(deployerKey);
IERC20(link).approve(router, amount + fee);
(bytes32 messageId,) = IRouterClient(router).ccipSend(destSelector, message);
console2.logBytes32(messageId);
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,42 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Script.sol";
import {IRouterClient} from "@chainlink/contracts-ccip/contracts/interfaces/IRouterClient.sol";
import {Client} from "@chainlink/contracts-ccip/contracts/libraries/Client.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @notice CCIP-send canonical mainnet LINK to a destination-chain bridge contract.
/// Env: PRIVATE_KEY, CCIP_ROUTER_MAINNET, LINK_TOKEN_MAINNET, DEST_SELECTOR, DEST_BRIDGE, LINK_AMOUNT_WEI
contract FundBridgeLinkViaCcipMainnet is Script {
function run() external {
uint256 deployerKey = vm.envUint("PRIVATE_KEY");
address router = vm.envAddress("CCIP_ROUTER_MAINNET");
address link = vm.envAddress("LINK_TOKEN_MAINNET");
uint64 destSelector = uint64(vm.envUint("DEST_SELECTOR"));
address destBridge = vm.envAddress("DEST_BRIDGE");
uint256 amount = vm.envUint("LINK_AMOUNT_WEI");
Client.EVMTokenAmount[] memory tokenAmounts = new Client.EVMTokenAmount[](1);
tokenAmounts[0] = Client.EVMTokenAmount({token: link, amount: amount});
Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({
receiver: abi.encode(destBridge),
data: "",
tokenAmounts: tokenAmounts,
feeToken: link,
extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 200_000}))
});
uint256 fee = IRouterClient(router).getFee(destSelector, message);
console2.log("destBridge", destBridge);
console2.log("amount", amount);
console2.log("fee", fee);
vm.startBroadcast(deployerKey);
IERC20(link).approve(router, amount + fee);
bytes32 messageId = IRouterClient(router).ccipSend(destSelector, message);
console2.logBytes32(messageId);
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,49 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {Script, console2} from "forge-std/Script.sol";
import {Stabilizer} from "../../../contracts/bridge/trustless/integration/Stabilizer.sol";
import {StablecoinPegManager} from "../../../contracts/bridge/trustless/integration/StablecoinPegManager.sol";
import {CommodityPegManager} from "../../../contracts/bridge/trustless/integration/CommodityPegManager.sol";
/// @notice Finish Chain 138 Stabilizer stack after peg managers are already deployed.
/// @dev Env: STABLECOIN_PEG_MANAGER, COMMODITY_PEG_MANAGER, PRIVATE_POOL_REGISTRY, PRIVATE_KEY
contract DeployChain138StabilizerFinish is Script {
function run() external {
require(block.chainid == 138, "chain138 only");
uint256 pk = vm.envUint("PRIVATE_KEY");
address admin = vm.envOr("STABILIZER_ADMIN", vm.addr(pk));
address privatePoolRegistry = vm.envAddress("PRIVATE_POOL_REGISTRY");
address stablecoinPeg = vm.envAddress("STABLECOIN_PEG_MANAGER");
address commodityPeg = vm.envAddress("COMMODITY_PEG_MANAGER");
address cUsdc = vm.envOr("COMPLIANT_USDC_ADDRESS", vm.envOr("CUSDC_ADDRESS_138", address(0)));
address cUsdt = vm.envOr("COMPLIANT_USDT_ADDRESS", vm.envOr("CUSDT_ADDRESS_138", address(0)));
address weth = vm.envOr("WETH9", address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2));
address xau = vm.envOr("XAU_ADDRESS_138", vm.envOr("cXAUC_ADDRESS_138", address(0x290E52a8819A4fbD0714E517225429aA2B70EC6b)));
StablecoinPegManager spm = StablecoinPegManager(stablecoinPeg);
CommodityPegManager cpm = CommodityPegManager(commodityPeg);
vm.startBroadcast(pk);
spm.registerWETH(weth);
if (xau != address(0)) {
cpm.setXAUAddress(xau);
cpm.registerCommodity(xau, "XAU", 1e18);
}
Stabilizer stabilizer = new Stabilizer(admin, privatePoolRegistry);
stabilizer.setStablecoinPegSource(stablecoinPeg, cUsdc != address(0) ? cUsdc : cUsdt);
if (xau != address(0)) {
stabilizer.setCommodityPegSource(commodityPeg, xau);
}
vm.stopBroadcast();
console2.log("Stabilizer", address(stabilizer));
console2.log("StablecoinPegManager", stablecoinPeg);
console2.log("CommodityPegManager", commodityPeg);
}
}

View File

@@ -0,0 +1,57 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {Script, console2} from "forge-std/Script.sol";
import "../../../contracts/bridge/trustless/integration/Stabilizer.sol";
import "../../../contracts/bridge/trustless/integration/StablecoinPegManager.sol";
import "../../../contracts/bridge/trustless/integration/CommodityPegManager.sol";
/// @notice Deploy peg managers + Stabilizer on Chain 138 (Defi Oracle Meta).
/// @dev Requires PRIVATE_KEY, RESERVE_SYSTEM, PRIVATE_POOL_REGISTRY; optional STABILIZER_ADMIN, XAU peg asset.
contract DeployChain138StabilizerStack is Script {
function run() external {
require(block.chainid == 138, "chain138 only");
uint256 pk = vm.envUint("PRIVATE_KEY");
address deployer = vm.addr(pk);
address admin = vm.envOr("STABILIZER_ADMIN", deployer);
address reserveSystem = vm.envAddress("RESERVE_SYSTEM");
address privatePoolRegistry = vm.envAddress("PRIVATE_POOL_REGISTRY");
vm.startBroadcast(pk);
StablecoinPegManager stablecoinPeg = new StablecoinPegManager(reserveSystem);
CommodityPegManager commodityPeg = new CommodityPegManager(reserveSystem);
address cUsdc = vm.envOr("COMPLIANT_USDC_ADDRESS", vm.envOr("CUSDC_ADDRESS_138", address(0)));
address cUsdt = vm.envOr("COMPLIANT_USDT_ADDRESS", vm.envOr("CUSDT_ADDRESS_138", address(0)));
address weth = vm.envOr("WETH9", address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2));
address xau = vm.envOr("XAU_ADDRESS_138", vm.envOr("cXAUC_ADDRESS_138", address(0x290E52a8819A4fbD0714E517225429aA2B70EC6b)));
if (cUsdc != address(0)) {
stablecoinPeg.registerUSDStablecoin(cUsdc);
}
if (cUsdt != address(0)) {
stablecoinPeg.registerUSDStablecoin(cUsdt);
}
stablecoinPeg.registerWETH(weth);
if (xau != address(0)) {
commodityPeg.setXAUAddress(xau);
commodityPeg.registerCommodity(xau, "XAU", 1e18);
}
Stabilizer stabilizer = new Stabilizer(admin, privatePoolRegistry);
stabilizer.setStablecoinPegSource(address(stablecoinPeg), cUsdc != address(0) ? cUsdc : cUsdt);
if (xau != address(0)) {
stabilizer.setCommodityPegSource(address(commodityPeg), xau);
}
vm.stopBroadcast();
console2.log("StablecoinPegManager", address(stablecoinPeg));
console2.log("CommodityPegManager", address(commodityPeg));
console2.log("Stabilizer", address(stabilizer));
console2.log("admin", admin);
}
}

View File

@@ -0,0 +1,230 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "forge-std/Script.sol";
import {RWATokenRegistry} from "../../../contracts/rwa/RWATokenRegistry.sol";
import {RWATokenFactory} from "../../../contracts/rwa/RWATokenFactory.sol";
import {IRWATokenFactory} from "../../../contracts/rwa/IRWATokenFactory.sol";
import {RWAToken} from "../../../contracts/rwa/RWAToken.sol";
import {UniversalAssetRegistry} from "../../../contracts/registry/UniversalAssetRegistry.sol";
/**
* @title DeployRWATokenFactory138
* @notice Deploy RWATokenRegistry + RWATokenFactory and optionally all five Li* M00 indices on Chain 138.
* @dev Taxonomy: config/rwa-capital-markets-taxonomy.v1.json. Not for c* eMoney (use DeployCompliantFiatTokens).
*
* Env:
* PRIVATE_KEY, OWNER, ADMIN, COMPLIANCE_ADMIN, INDEX_PUBLISHER
* UNIVERSAL_ASSET_REGISTRY (optional; pass address for factory wiring only)
* REGISTER_IN_UAR — default 0; use RegisterRWAIndicesInUAR138.s.sol after REGISTRAR_ROLE grant
* DEPLOY_LI_INDICES=1 to deploy LiXAU, LiPMG, LiBMG13 in one run
* RWA_INITIAL_INDEX_VALUE (default 1e6 = 1.0 at 6 decimals)
* RWA_INITIAL_SUPPLY (default 0 — mint via policy after index committee attestation)
* RWA_METHODOLOGY_HASH (required for DEPLOY_LI_INDICES; default from m00-li-index-methodology-hash.v1.json via cast)
* MULTISIG_ADMIN (optional) — grant factory DEPLOYER + registry/UAR REGISTRAR to multisig
*/
contract DeployRWATokenFactory138 is Script {
uint8 constant DECIMALS = 6;
uint256 constant DEFAULT_INDEX_VALUE = 1_000_000;
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address deployer = vm.addr(pk);
address owner = vm.envOr("OWNER", deployer);
address compliance = vm.envOr("COMPLIANCE_ADMIN", deployer);
address publisher = vm.envOr("INDEX_PUBLISHER", deployer);
address uar = vm.envOr("UNIVERSAL_ASSET_REGISTRY", address(0));
// UAR registration reverts if factory lacks REGISTRAR_ROLE — keep off during one-shot deploy.
bool registerInUar = vm.envOr("REGISTER_IN_UAR", uint256(0)) != 0;
require(
!registerInUar || uar != address(0),
"REGISTER_IN_UAR requires UNIVERSAL_ASSET_REGISTRY"
);
uint256 initialIndexValue = vm.envOr("RWA_INITIAL_INDEX_VALUE", DEFAULT_INDEX_VALUE);
uint256 initialSupply = vm.envOr("RWA_INITIAL_SUPPLY", uint256(0));
address multisig = vm.envOr("MULTISIG_ADMIN", address(0));
address governance = vm.envOr("GOVERNANCE_CONTROLLER", address(0));
vm.startBroadcast(pk);
// Deployer holds DEFAULT_ADMIN during bootstrap so grants succeed in one broadcast.
RWATokenRegistry registry = new RWATokenRegistry(deployer);
RWATokenFactory factory = new RWATokenFactory(deployer, address(registry), uar);
registry.grantRole(registry.REGISTRAR_ROLE(), address(factory));
if (registerInUar && uar != address(0)) {
UniversalAssetRegistry(uar).grantRole(
UniversalAssetRegistry(uar).REGISTRAR_ROLE(),
address(factory)
);
}
if (multisig != address(0)) {
factory.grantRole(factory.DEPLOYER_ROLE(), multisig);
registry.grantRole(registry.REGISTRAR_ROLE(), multisig);
}
if (governance != address(0)) {
factory.grantRole(factory.DEFAULT_ADMIN_ROLE(), governance);
registry.grantRole(registry.DEFAULT_ADMIN_ROLE(), governance);
}
console.log("RWATokenRegistry", address(registry));
console.log("RWATokenFactory", address(factory));
if (vm.envOr("DEPLOY_LI_INDICES", uint256(0)) != 0) {
bytes32 methodologyHash = _resolveMethodologyHash();
_deployAllLi(
factory,
owner,
compliance,
publisher,
initialIndexValue,
initialSupply,
registerInUar,
methodologyHash
);
}
vm.stopBroadcast();
}
function _resolveMethodologyHash() internal view returns (bytes32) {
string memory envHash = vm.envOr("RWA_METHODOLOGY_HASH", string(""));
if (bytes(envHash).length > 0) {
return vm.parseBytes32(envHash);
}
revert("RWA_METHODOLOGY_HASH required when DEPLOY_LI_INDICES=1");
}
function _deployAllLi(
RWATokenFactory factory,
address owner,
address compliance,
address publisher,
uint256 initialIndexValue,
uint256 initialSupply,
bool registerInUar,
bytes32 methodologyHash
) internal {
_deployLi(
factory,
owner,
compliance,
publisher,
"LiXAU",
"XAU Liquidity Index (M00)",
"LiXAU",
"Precious Metals",
"Commodity Index",
"Gold",
initialIndexValue,
initialSupply,
registerInUar,
methodologyHash
);
_deployLi(
factory,
owner,
compliance,
publisher,
"LiPMG",
"Precious Metals Group Index (M00)",
"LiPMG",
"Precious Metals",
"Basket Index",
"Precious Metals",
initialIndexValue,
initialSupply,
registerInUar,
methodologyHash
);
_deployLi(
factory,
owner,
compliance,
publisher,
"LiBMG1",
"Base Metals Group Index 1 (M00)",
"LiBMG1",
"Industrial Metals",
"Basket Index",
"Base Metals",
initialIndexValue,
initialSupply,
registerInUar,
methodologyHash
);
_deployLi(
factory,
owner,
compliance,
publisher,
"LiBMG2",
"Base Metals Group Index 2 (M00)",
"LiBMG2",
"Industrial Metals",
"Basket Index",
"Battery Materials",
initialIndexValue,
initialSupply,
registerInUar,
methodologyHash
);
_deployLi(
factory,
owner,
compliance,
publisher,
"LiBMG3",
"Base Metals Group Index 3 (M00)",
"LiBMG3",
"Industrial Metals",
"Basket Index",
"Building Metals",
initialIndexValue,
initialSupply,
registerInUar,
methodologyHash
);
}
function _deployLi(
RWATokenFactory factory,
address owner,
address compliance,
address publisher,
string memory ticker,
string memory name,
string memory symbol,
string memory assetGroup,
string memory instrumentType,
string memory underlying,
uint256 initialIndexValue,
uint256 initialSupply,
bool registerInUar,
bytes32 methodologyHash
) internal {
address token = factory.deployRWAIndex(
IRWATokenFactory.RWAProductConfig({
indexTicker: ticker,
name: name,
symbol: symbol,
decimals: DECIMALS,
assetClass: "Commodities",
assetGroup: assetGroup,
instrumentType: instrumentType,
underlyingAsset: underlying,
gruLayer: "M00",
jurisdiction: "International",
initialOwner: owner,
complianceAdmin: compliance,
indexPublisher: publisher,
initialIndexValue: initialIndexValue,
initialSupply: initialSupply,
methodologyDocumentHash: methodologyHash,
registerInUniversalAssetRegistry: registerInUar
})
);
console.log(ticker, token);
}
}

View File

@@ -0,0 +1,68 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "forge-std/Script.sol";
import {RWATokenRegistry} from "../../../contracts/rwa/RWATokenRegistry.sol";
import {UniversalAssetRegistry} from "../../../contracts/registry/UniversalAssetRegistry.sol";
import {IRWAToken} from "../../../contracts/rwa/IRWAToken.sol";
/**
* @title RegisterRWAIndicesInUAR138
* @notice Register deployed Li* tokens in UniversalAssetRegistry (run after factory deploy + REGISTRAR_ROLE grant).
* @dev Requires RWA_TOKEN_REGISTRY and UNIVERSAL_ASSET_REGISTRY. Broadcaster must hold UAR REGISTRAR_ROLE
* or factory must have been granted REGISTRAR_ROLE and this script calls via factory (not implemented — direct UAR calls).
*
* Env: PRIVATE_KEY, RWA_TOKEN_REGISTRY, UNIVERSAL_ASSET_REGISTRY
* Optional: LI_TICKERS=LiXAU,LiPMG,LiBMG1,LiBMG2,LiBMG3 (default all five)
*/
contract RegisterRWAIndicesInUAR138 is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address registryAddr = vm.envAddress("RWA_TOKEN_REGISTRY");
address uarAddr = vm.envAddress("UNIVERSAL_ASSET_REGISTRY");
RWATokenRegistry registry = RWATokenRegistry(registryAddr);
UniversalAssetRegistry uar = UniversalAssetRegistry(uarAddr);
vm.startBroadcast(pk);
string memory tickersEnv = vm.envOr("LI_TICKERS", string(""));
if (bytes(tickersEnv).length > 0) {
string[] memory parts = vm.split(tickersEnv, ",");
for (uint256 i = 0; i < parts.length; i++) {
_registerOne(registry, uar, parts[i]);
}
} else {
_registerOne(registry, uar, "LiXAU");
_registerOne(registry, uar, "LiPMG");
_registerOne(registry, uar, "LiBMG1");
_registerOne(registry, uar, "LiBMG2");
_registerOne(registry, uar, "LiBMG3");
}
vm.stopBroadcast();
}
function _registerOne(RWATokenRegistry registry, UniversalAssetRegistry uar, string memory ticker) internal {
address token = registry.getToken(ticker);
require(token != address(0), "token missing");
IRWAToken rwa = IRWAToken(token);
uar.registerRWAIndexAsset(
token,
_nameFor(ticker),
ticker,
6,
"International"
);
console.log("UAR registered", ticker, token);
}
function _nameFor(string memory ticker) internal pure returns (string memory) {
if (keccak256(bytes(ticker)) == keccak256("LiXAU")) return "XAU Liquidity Index (M00)";
if (keccak256(bytes(ticker)) == keccak256("LiPMG")) return "Precious Metals Group Index (M00)";
if (keccak256(bytes(ticker)) == keccak256("LiBMG1")) return "Base Metals Group Index 1 (M00)";
if (keccak256(bytes(ticker)) == keccak256("LiBMG2")) return "Base Metals Group Index 2 (M00)";
if (keccak256(bytes(ticker)) == keccak256("LiBMG3")) return "Base Metals Group Index 3 (M00)";
return ticker;
}
}

View File

@@ -0,0 +1,70 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "forge-std/Script.sol";
import {RWATokenFactory} from "../../../contracts/rwa/RWATokenFactory.sol";
import {RWATokenRegistry} from "../../../contracts/rwa/RWATokenRegistry.sol";
import {PolicyProfileRegistry} from "../../../contracts/universal-resource/PolicyProfileRegistry.sol";
import {OMNLJurisdictionPolicyRegistry} from "../../../contracts/hybx-omnl/OMNLJurisdictionPolicyRegistry.sol";
/**
* @title WireRWATokenFactoryWeb3Controls138
* @notice Post-deploy: C-W3-01 jurisdiction policy, C-W3-08 profile hash, C-W3-04 multisig roles, C-W3-07 governance admin.
* Env: RWA_TOKEN_FACTORY, RWA_TOKEN_REGISTRY, POLICY_PROFILE_REGISTRY, OMNL_JURISDICTION_REGISTRY,
* ID_JURISDICTION_POLICY_HASH, M00_PROFILE_CONTENT_HASH, OMNL_COMPLIANCE_MULTISIG, GOVERNANCE_CONTROLLER
*/
contract WireRWATokenFactoryWeb3Controls138 is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address factoryAddr = vm.envAddress("RWA_TOKEN_FACTORY");
address multisig = vm.envOr("OMNL_COMPLIANCE_MULTISIG", vm.envOr("MULTISIG_ADMIN", address(0)));
address governance = vm.envOr("GOVERNANCE_CONTROLLER", address(0));
vm.startBroadcast(pk);
RWATokenFactory factory = RWATokenFactory(factoryAddr);
if (multisig != address(0)) {
if (!factory.hasRole(factory.DEPLOYER_ROLE(), multisig)) {
factory.grantRole(factory.DEPLOYER_ROLE(), multisig);
}
console.log("DEPLOYER_ROLE ->", multisig);
}
if (governance != address(0)) {
if (!factory.hasRole(factory.DEFAULT_ADMIN_ROLE(), governance)) {
factory.grantRole(factory.DEFAULT_ADMIN_ROLE(), governance);
}
console.log("DEFAULT_ADMIN_ROLE ->", governance);
}
address pprAddr = vm.envOr("POLICY_PROFILE_REGISTRY", address(0));
if (pprAddr != address(0)) {
bytes32 profileHash = vm.envBytes32("M00_PROFILE_CONTENT_HASH");
PolicyProfileRegistry(pprAddr).publishProfile(
"m00_commodity_index_v1",
profileHash,
1,
block.timestamp
);
console.log("Published m00_commodity_index_v1 on PolicyProfileRegistry");
}
address jurAddr = vm.envOr("OMNL_JURISDICTION_REGISTRY", address(0));
if (jurAddr != address(0)) {
bytes32 idPolicyHash = vm.envBytes32("ID_JURISDICTION_POLICY_HASH");
bytes32 jurisdictionId = keccak256("ID");
OMNLJurisdictionPolicyRegistry(jurAddr).publishPolicy(
jurisdictionId,
idPolicyHash,
3,
2,
2,
true
);
console.log("Published ID jurisdiction policy");
}
vm.stopBroadcast();
}
}

View File

@@ -18,54 +18,68 @@ import {VaultFactory} from "../../../contracts/vault/VaultFactory.sol";
* CUSDC_ADDRESS_138 - (optional) Compliant USDC; if set, creates vault → acUSDC + vdcUSDC.
* CUSDT_ADDRESS_138 - (optional) Compliant USDT; if set, creates vault → acUSDT + vdcUSDT.
* COMPLIANT_USDC_ADDRESS, COMPLIANT_USDT_ADDRESS - Fallback env names if CUSDC/CUSDT_138 unset.
* cEURC_ADDRESS_138, cEURT_ADDRESS_138, cGBPC_ADDRESS_138, cGBPT_ADDRESS_138,
* cAUDC_ADDRESS_138, cJPYC_ADDRESS_138, cCHFC_ADDRESS_138, cCADC_ADDRESS_138,
* cXAUC_ADDRESS_138, cXAUT_ADDRESS_138 - Optional additional base tokens (6 decimals).
*/
contract DeployAcVdcSdcVaults is Script {
uint8 constant DECIMALS = 6;
bool constant DEBT_TRANSFERABLE = true;
struct TokenSpec {
string envPrimary;
string envAlt;
string label;
}
TokenSpec[] internal tokens;
function _initTokens() internal {
tokens.push(TokenSpec("CUSDC_ADDRESS_138", "COMPLIANT_USDC_ADDRESS", "USDC"));
tokens.push(TokenSpec("CUSDT_ADDRESS_138", "COMPLIANT_USDT_ADDRESS", "USDT"));
tokens.push(TokenSpec("cEURC_ADDRESS_138", "", "EURC"));
tokens.push(TokenSpec("cEURT_ADDRESS_138", "", "EURT"));
tokens.push(TokenSpec("cGBPC_ADDRESS_138", "", "GBPC"));
tokens.push(TokenSpec("cGBPT_ADDRESS_138", "", "GBPT"));
tokens.push(TokenSpec("cAUDC_ADDRESS_138", "", "AUDC"));
tokens.push(TokenSpec("cJPYC_ADDRESS_138", "", "JPYC"));
tokens.push(TokenSpec("cCHFC_ADDRESS_138", "", "CHFC"));
tokens.push(TokenSpec("cCADC_ADDRESS_138", "", "CADC"));
tokens.push(TokenSpec("cXAUC_ADDRESS_138", "", "XAUC"));
tokens.push(TokenSpec("cXAUT_ADDRESS_138", "", "XAUT"));
}
function run() external {
_initTokens();
uint256 pk = vm.envUint("PRIVATE_KEY");
address deployer = vm.addr(pk);
address owner = vm.envOr("OWNER", deployer);
address entity = vm.envOr("ENTITY", deployer);
address factoryAddr = vm.envAddress("VAULT_FACTORY_ADDRESS");
if (factoryAddr == address(0)) {
factoryAddr = vm.envOr("VAULT_FACTORY", address(0));
}
require(factoryAddr != address(0), "VAULT_FACTORY_ADDRESS required");
VaultFactory factory = VaultFactory(factoryAddr);
address cUsdc = _getToken("CUSDC_ADDRESS_138", "COMPLIANT_USDC_ADDRESS");
address cUsdt = _getToken("CUSDT_ADDRESS_138", "COMPLIANT_USDT_ADDRESS");
vm.startBroadcast(pk);
if (cUsdc != address(0)) {
for (uint256 i = 0; i < tokens.length; i++) {
address base = _getToken(tokens[i].envPrimary, tokens[i].envAlt);
if (base == address(0)) continue;
(address vault, address depositToken, address debtToken) = factory.createVaultWithDecimals(
owner,
entity,
cUsdc,
cUsdc,
base,
base,
DECIMALS,
DECIMALS,
DEBT_TRANSFERABLE
);
console.log("USDC vault:", vault);
console.log("acUSDC (deposit):", depositToken);
console.log("vdcUSDC (debt):", debtToken);
}
if (cUsdt != address(0)) {
(address vault, address depositToken, address debtToken) = factory.createVaultWithDecimals(
owner,
entity,
cUsdt,
cUsdt,
DECIMALS,
DECIMALS,
DEBT_TRANSFERABLE
);
console.log("USDT vault:", vault);
console.log("acUSDT (deposit):", depositToken);
console.log("vdcUSDT (debt):", debtToken);
console.log(string.concat(tokens[i].label, " vault:"), vault);
console.log(string.concat("ac", tokens[i].label, " (deposit):"), depositToken);
console.log(string.concat("vdc", tokens[i].label, " (debt):"), debtToken);
}
vm.stopBroadcast();

View File

@@ -0,0 +1,56 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {VaultFactory} from "../../../contracts/vault/VaultFactory.sol";
/// @notice M1 vault basket for ALL Mainnet (651940): AUSDC, AUSDT, WALL.
contract DeployAcVdcSdcVaults651940 is Script {
uint8 constant DECIMALS = 6;
bool constant DEBT_TRANSFERABLE = true;
uint8 constant GRU_TIER_M1 = 2;
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address deployer = vm.addr(pk);
address owner = vm.envOr("OWNER", deployer);
address entity = vm.envOr("ENTITY", vm.envOr("GRU_OMNL_ENTITY_ADDRESS", deployer));
address factoryAddr = vm.envAddress("VAULT_FACTORY_ADDRESS");
VaultFactory factory = VaultFactory(factoryAddr);
bytes32 ibanHash = vm.envBytes32("GRU_IBAN_HASH");
bytes32 policyProfileKey = vm.envOr("GRU_POLICY_PROFILE_KEY", bytes32(0));
address[] memory bases = new address[](3);
string[] memory labels = new string[](3);
bases[0] = vm.envAddress("CUSDC_ADDRESS_651940");
labels[0] = "AUSDC";
bases[1] = vm.envAddress("AUSDT_ADDRESS_651940");
labels[1] = "AUSDT";
bases[2] = vm.envAddress("WALL_ADDRESS_651940");
labels[2] = "WALL";
uint256 startIdx = vm.envOr("GRU_VAULT_START_INDEX", uint256(0));
uint256 endIdx = vm.envOr("GRU_VAULT_END_INDEX", bases.length);
vm.startBroadcast(pk);
for (uint256 i = startIdx; i < endIdx && i < bases.length; i++) {
(address vault, address depositToken, address debtToken) = factory.createVaultWithDecimalsGRU(
owner,
entity,
bases[i],
bases[i],
DECIMALS,
DECIMALS,
DEBT_TRANSFERABLE,
GRU_TIER_M1,
ibanHash,
policyProfileKey
);
console.log(string.concat(labels[i], " vault:"), vault);
console.log(string.concat("ac", labels[i], ":"), depositToken);
console.log(string.concat("vdc", labels[i], ":"), debtToken);
}
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,85 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {VaultFactory} from "../../../contracts/vault/VaultFactory.sol";
/**
* @title DeployAcVdcSdcVaultsGRU
* @notice Create M1 ac/vdc vault pairs with GRU tier + IBAN + policy profile anchors.
*/
contract DeployAcVdcSdcVaultsGRU is Script {
uint8 constant DECIMALS = 6;
bool constant DEBT_TRANSFERABLE = true;
uint8 constant GRU_TIER_M1 = 2;
struct TokenSpec {
string envPrimary;
string envAlt;
string label;
}
TokenSpec[] internal tokens;
function _initTokens() internal {
tokens.push(TokenSpec("CUSDC_ADDRESS_138", "COMPLIANT_USDC_ADDRESS", "USDC"));
tokens.push(TokenSpec("CUSDT_ADDRESS_138", "COMPLIANT_USDT_ADDRESS", "USDT"));
tokens.push(TokenSpec("cEURC_ADDRESS_138", "", "EURC"));
tokens.push(TokenSpec("cEURT_ADDRESS_138", "", "EURT"));
tokens.push(TokenSpec("cGBPC_ADDRESS_138", "", "GBPC"));
tokens.push(TokenSpec("cGBPT_ADDRESS_138", "", "GBPT"));
tokens.push(TokenSpec("cAUDC_ADDRESS_138", "", "AUDC"));
tokens.push(TokenSpec("cJPYC_ADDRESS_138", "", "JPYC"));
tokens.push(TokenSpec("cCHFC_ADDRESS_138", "", "CHFC"));
tokens.push(TokenSpec("cCADC_ADDRESS_138", "", "CADC"));
tokens.push(TokenSpec("cXAUC_ADDRESS_138", "", "XAUC"));
tokens.push(TokenSpec("cXAUT_ADDRESS_138", "", "XAUT"));
}
function run() external {
_initTokens();
uint256 pk = vm.envUint("PRIVATE_KEY");
address deployer = vm.addr(pk);
address owner = vm.envOr("OWNER", deployer);
address entity = vm.envOr("ENTITY", vm.envOr("GRU_OMNL_ENTITY_ADDRESS", deployer));
address factoryAddr = vm.envAddress("VAULT_FACTORY_ADDRESS");
VaultFactory factory = VaultFactory(factoryAddr);
bytes32 ibanHash = vm.envBytes32("GRU_IBAN_HASH");
bytes32 policyProfileKey = vm.envOr("GRU_POLICY_PROFILE_KEY", bytes32(0));
uint256 startIdx = vm.envOr("GRU_VAULT_START_INDEX", uint256(0));
uint256 endIdx = vm.envOr("GRU_VAULT_END_INDEX", tokens.length);
vm.startBroadcast(pk);
for (uint256 i = startIdx; i < endIdx && i < tokens.length; i++) {
address base = _getToken(tokens[i].envPrimary, tokens[i].envAlt);
if (base == address(0)) continue;
(address vault, address depositToken, address debtToken) = factory.createVaultWithDecimalsGRU(
owner,
entity,
base,
base,
DECIMALS,
DECIMALS,
DEBT_TRANSFERABLE,
GRU_TIER_M1,
ibanHash,
policyProfileKey
);
console.log(string.concat(tokens[i].label, " vault:"), vault);
console.log(string.concat("ac", tokens[i].label, ":"), depositToken);
console.log(string.concat("vdc", tokens[i].label, ":"), debtToken);
}
vm.stopBroadcast();
}
function _getToken(string memory primary, string memory altKey) internal view returns (address) {
address a = vm.envOr(primary, address(0));
if (a != address(0)) return a;
if (bytes(altKey).length == 0) return address(0);
return vm.envOr(altKey, address(0));
}
}

View File

@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {CREATE2Factory} from "../../../contracts/utils/CREATE2Factory.sol";
/// @notice Deploy CREATE2Factory when missing on target chain (one-time CREATE).
contract DeployCREATE2FactoryIfNeeded is Script {
function run() external {
address existing = vm.envOr("CREATE2_FACTORY_ADDRESS", address(0));
if (existing != address(0) && existing.code.length > 0) {
console2.log("CREATE2Factory already live:", existing);
return;
}
vm.startBroadcast(vm.envUint("PRIVATE_KEY"));
CREATE2Factory factory = new CREATE2Factory();
vm.stopBroadcast();
console2.log("CREATE2Factory deployed:", address(factory));
}
}

View File

@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {GRUEntityIbanRegistry} from "../../../contracts/vault/GRUEntityIbanRegistry.sol";
import {GRUVaultIndex} from "../../../contracts/vault/GRUVaultIndex.sol";
import {VaultFactory} from "../../../contracts/vault/VaultFactory.sol";
/// @notice Deploy GRU protocol registries and wire an existing or new VaultFactory.
/// @dev Run after DeployVaultSystem or pass VAULT_FACTORY_ADDRESS to wire index on live factory.
contract DeployGRUVaultProtocol is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address admin = vm.envOr("GRU_VAULT_ADMIN", vm.addr(pk));
vm.startBroadcast(pk);
GRUEntityIbanRegistry ibanRegistry = new GRUEntityIbanRegistry(admin);
GRUVaultIndex vaultIndex = new GRUVaultIndex(admin);
address factoryAddr = vm.envOr("VAULT_FACTORY_ADDRESS", address(0));
if (factoryAddr != address(0)) {
VaultFactory(factoryAddr).setGruVaultIndex(address(vaultIndex));
vaultIndex.grantFactoryRole(factoryAddr);
console2.log("Wired VaultFactory", factoryAddr);
}
vm.stopBroadcast();
console2.log("GRUEntityIbanRegistry", address(ibanRegistry));
console2.log("GRUVaultIndex", address(vaultIndex));
console2.log("admin", admin);
}
}

View File

@@ -0,0 +1,50 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {CREATE2Factory} from "../../../contracts/utils/CREATE2Factory.sol";
import {GRUEntityIbanRegistry} from "../../../contracts/vault/GRUEntityIbanRegistry.sol";
import {GRUVaultIndex} from "../../../contracts/vault/GRUVaultIndex.sol";
import {VaultFactory} from "../../../contracts/vault/VaultFactory.sol";
/// @notice Deterministic GRU registry deploy via CREATE2Factory (cross-chain parity).
contract DeployGRUVaultRegistriesCreate2 is Script {
uint256 constant SALT_IBAN = uint256(keccak256("GRUEntityIbanRegistry"));
uint256 constant SALT_INDEX = uint256(keccak256("GRUVaultIndex"));
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address admin = vm.envOr("GRU_VAULT_ADMIN", vm.addr(pk));
address factoryAddr = vm.envAddress("CREATE2_FACTORY_ADDRESS");
CREATE2Factory factory = CREATE2Factory(factoryAddr);
bytes memory ibanInit = abi.encodePacked(type(GRUEntityIbanRegistry).creationCode, abi.encode(admin));
bytes memory indexInit = abi.encodePacked(type(GRUVaultIndex).creationCode, abi.encode(admin));
address predictedIban = factory.computeAddress(ibanInit, SALT_IBAN);
address predictedIndex = factory.computeAddress(indexInit, SALT_INDEX);
vm.startBroadcast(pk);
address ibanReg = predictedIban.code.length > 0
? predictedIban
: factory.deploy(ibanInit, SALT_IBAN);
address vaultIndex = predictedIndex.code.length > 0
? predictedIndex
: factory.deploy(indexInit, SALT_INDEX);
address factoryAddrVault = vm.envOr("VAULT_FACTORY_ADDRESS", address(0));
if (factoryAddrVault != address(0) && factoryAddrVault.code.length > 0) {
VaultFactory(factoryAddrVault).setGruVaultIndex(vaultIndex);
GRUVaultIndex(vaultIndex).grantFactoryRole(factoryAddrVault);
console2.log("Wired VaultFactory", factoryAddrVault);
}
vm.stopBroadcast();
console2.log("CREATE2Factory", factoryAddr);
console2.log("GRUEntityIbanRegistry", ibanReg);
console2.log("GRUVaultIndex", vaultIndex);
}
}

View File

@@ -0,0 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {GRUVaultIndex} from "../../../contracts/vault/GRUVaultIndex.sol";
/// @notice Deploy GRUVaultIndex v2 (patch + import support) on hub 138.
contract DeployNewGRUVaultIndex138 is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address admin = vm.addr(pk);
vm.startBroadcast(pk);
GRUVaultIndex idx = new GRUVaultIndex(admin);
vm.stopBroadcast();
console2.log("GRUVaultIndex:", address(idx));
}
}

View File

@@ -0,0 +1,50 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {Vault} from "../../../contracts/vault/Vault.sol";
import {VaultFactory} from "../../../contracts/vault/VaultFactory.sol";
import {DepositToken} from "../../../contracts/vault/tokens/DepositToken.sol";
import {DebtToken} from "../../../contracts/vault/tokens/DebtToken.sol";
import {Ledger} from "../../../contracts/vault/Ledger.sol";
import {RegulatedEntityRegistry} from "../../../contracts/vault/RegulatedEntityRegistry.sol";
/// @notice Deploy VaultFactory on 651940 after core system addresses are live.
contract DeployVaultFactory651940 is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address admin = vm.addr(pk);
RegulatedEntityRegistry entityRegistry =
RegulatedEntityRegistry(vm.envAddress("REGULATED_ENTITY_REGISTRY"));
Ledger ledger = Ledger(vm.envAddress("LEDGER_ADDRESS"));
address collateralAdapter = vm.envAddress("COLLATERAL_ADAPTER_ADDRESS");
address eMoneyJoinAddr = vm.envAddress("EMONEY_JOIN_ADDRESS");
vm.startBroadcast(pk);
Vault vaultImpl = new Vault(
admin, admin, address(ledger), address(entityRegistry), collateralAdapter, eMoneyJoinAddr
);
DepositToken depositTokenImpl = new DepositToken();
DebtToken debtTokenImpl = new DebtToken();
VaultFactory vaultFactory = new VaultFactory(
admin,
address(vaultImpl),
address(depositTokenImpl),
address(debtTokenImpl),
address(ledger),
address(entityRegistry),
collateralAdapter,
eMoneyJoinAddr
);
console.log("Vault Factory:", address(vaultFactory));
ledger.grantRole(ledger.VAULT_FACTORY_ROLE(), address(vaultFactory));
entityRegistry.grantRole(entityRegistry.REGISTRAR_ROLE(), address(vaultFactory));
vm.stopBroadcast();
console.log("=== [651940] VaultFactory wired ===");
}
}

View File

@@ -126,8 +126,8 @@ contract DeployVaultSystem is Script {
// Step 10: Grant roles and configure
console.log("\n10. Configuring roles and parameters...");
// Grant factory vault role
ledger.grantVaultRole(address(vaultFactory));
// Grant factory permission to register vaults on ledger
ledger.grantRole(ledger.VAULT_FACTORY_ROLE(), address(vaultFactory));
// Set risk parameters (registers assets and sets params)
ledger.setRiskParameters(
@@ -146,7 +146,7 @@ contract DeployVaultSystem is Script {
}
// Grant factory role to create vaults
entityRegistry.grantRole(keccak256("ENTITY_REGISTRAR_ROLE"), address(vaultFactory));
entityRegistry.grantRole(entityRegistry.REGISTRAR_ROLE(), address(vaultFactory));
vm.stopBroadcast();

View File

@@ -0,0 +1,71 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {RegulatedEntityRegistry} from "../../../contracts/vault/RegulatedEntityRegistry.sol";
import {XAUOracle} from "../../../contracts/vault/XAUOracle.sol";
import {RateAccrual} from "../../../contracts/vault/RateAccrual.sol";
import {Ledger} from "../../../contracts/vault/Ledger.sol";
import {Liquidation} from "../../../contracts/vault/Liquidation.sol";
import {CollateralAdapter} from "../../../contracts/vault/adapters/CollateralAdapter.sol";
import {eMoneyJoin} from "../../../contracts/vault/adapters/eMoneyJoin.sol";
import {Aggregator} from "../../../contracts/oracle/Aggregator.sol";
/// @notice Deploy vault system core on ALL Mainnet (651940) without VaultFactory (forge broadcast workaround).
contract DeployVaultSystem651940Core is Script {
uint256 public constant DEFAULT_LIQUIDATION_RATIO = 10000;
uint256 public constant DEFAULT_CREDIT_MULTIPLIER = 50000;
uint256 public constant DEFAULT_DEBT_CEILING = 1000000e18;
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address admin = vm.addr(pk);
address treasury = vm.envOr("TREASURY_ADDRESS", admin);
address ethAddress = address(0);
vm.startBroadcast(pk);
console.log("=== [651940] Vault system core ===");
RegulatedEntityRegistry entityRegistry = new RegulatedEntityRegistry(admin);
console.log("RegulatedEntityRegistry:", address(entityRegistry));
Aggregator ethPriceFeed = new Aggregator("ETH/XAU", admin, 3600, 50);
ethPriceFeed.addTransmitter(admin);
ethPriceFeed.updateAnswer(0.05e18);
console.log("ETH Price Feed:", address(ethPriceFeed));
Aggregator btcPriceFeed = new Aggregator("BTC/XAU", admin, 3600, 50);
btcPriceFeed.addTransmitter(admin);
btcPriceFeed.updateAnswer(0.5e18);
console.log("BTC Price Feed:", address(btcPriceFeed));
XAUOracle xauOracle = new XAUOracle(admin);
xauOracle.addPriceFeed(address(ethPriceFeed), 10000);
xauOracle.addPriceFeed(address(btcPriceFeed), 10000);
xauOracle.updatePrice();
console.log("XAU Oracle:", address(xauOracle));
RateAccrual rateAccrual = new RateAccrual(admin);
rateAccrual.setInterestRate(address(0), 500);
console.log("Rate Accrual:", address(rateAccrual));
Ledger ledger = new Ledger(admin, address(xauOracle), address(rateAccrual));
console.log("Ledger:", address(ledger));
Liquidation liquidation = new Liquidation(admin, address(ledger), address(xauOracle), treasury);
console.log("Liquidation:", address(liquidation));
CollateralAdapter collateralAdapter = new CollateralAdapter(admin, address(ledger));
console.log("Collateral Adapter:", address(collateralAdapter));
eMoneyJoin eMoneyJoinContract = new eMoneyJoin(admin);
console.log("eMoney Join:", address(eMoneyJoinContract));
ledger.setRiskParameters(
ethAddress, DEFAULT_DEBT_CEILING, DEFAULT_LIQUIDATION_RATIO, DEFAULT_CREDIT_MULTIPLIER
);
vm.stopBroadcast();
console.log("=== [651940] core complete (VaultFactory separate) ===");
}
}

View File

@@ -0,0 +1,94 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {Ledger} from "../../../contracts/vault/Ledger.sol";
import {RegulatedEntityRegistry} from "../../../contracts/vault/RegulatedEntityRegistry.sol";
import {XAUOracle} from "../../../contracts/vault/XAUOracle.sol";
import {RateAccrual} from "../../../contracts/vault/RateAccrual.sol";
import {Liquidation} from "../../../contracts/vault/Liquidation.sol";
import {CollateralAdapter} from "../../../contracts/vault/adapters/CollateralAdapter.sol";
import {eMoneyJoin} from "../../../contracts/vault/adapters/eMoneyJoin.sol";
import {Vault} from "../../../contracts/vault/Vault.sol";
import {VaultFactory} from "../../../contracts/vault/VaultFactory.sol";
import {DepositToken} from "../../../contracts/vault/tokens/DepositToken.sol";
import {DebtToken} from "../../../contracts/vault/tokens/DebtToken.sol";
import {Aggregator} from "../../../contracts/oracle/Aggregator.sol";
/**
* @title DeployVaultSystemFinish
* @notice Resume vault system deploy when DeployVaultSystem broadcast stalled mid-flight.
* @dev Requires env addresses for components already on-chain (see run-gru-vault-protocol-operator.sh).
*/
contract DeployVaultSystemFinish is Script {
uint256 public constant DEFAULT_LIQUIDATION_RATIO = 10000;
uint256 public constant DEFAULT_CREDIT_MULTIPLIER = 50000;
uint256 public constant DEFAULT_DEBT_CEILING = 1000000e18;
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address admin = vm.addr(pk);
address treasury = vm.envOr("TREASURY_ADDRESS", admin);
address ethAddress = address(0);
RegulatedEntityRegistry entityRegistry =
RegulatedEntityRegistry(vm.envAddress("REGULATED_ENTITY_REGISTRY"));
XAUOracle xauOracle = XAUOracle(vm.envAddress("XAU_ORACLE_ADDRESS"));
address ethPriceFeed = vm.envAddress("ETH_PRICE_FEED_ADDRESS");
address btcPriceFeed = vm.envAddress("BTC_PRICE_FEED_ADDRESS");
vm.startBroadcast(pk);
console.log("=== Finishing Vault System (from XAUOracle config) ===");
xauOracle.addPriceFeed(ethPriceFeed, 10000);
xauOracle.addPriceFeed(btcPriceFeed, 10000);
Aggregator(ethPriceFeed).updateAnswer(0.05e18);
Aggregator(btcPriceFeed).updateAnswer(0.5e18);
xauOracle.updatePrice();
console.log("XAUOracle configured");
RateAccrual rateAccrual = new RateAccrual(admin);
rateAccrual.setInterestRate(address(0), 500);
console.log("RateAccrual:", address(rateAccrual));
Ledger ledger = new Ledger(admin, address(xauOracle), address(rateAccrual));
console.log("Ledger:", address(ledger));
Liquidation liquidation = new Liquidation(admin, address(ledger), address(xauOracle), treasury);
console.log("Liquidation:", address(liquidation));
CollateralAdapter collateralAdapter = new CollateralAdapter(admin, address(ledger));
console.log("Collateral Adapter:", address(collateralAdapter));
eMoneyJoin eMoneyJoinContract = new eMoneyJoin(admin);
console.log("eMoney Join:", address(eMoneyJoinContract));
Vault vaultImpl = new Vault(
admin, admin, address(ledger), address(entityRegistry), address(collateralAdapter), address(eMoneyJoinContract)
);
DepositToken depositTokenImpl = new DepositToken();
DebtToken debtTokenImpl = new DebtToken();
VaultFactory vaultFactory = new VaultFactory(
admin,
address(vaultImpl),
address(depositTokenImpl),
address(debtTokenImpl),
address(ledger),
address(entityRegistry),
address(collateralAdapter),
address(eMoneyJoinContract)
);
console.log("Vault Factory:", address(vaultFactory));
ledger.grantRole(ledger.VAULT_FACTORY_ROLE(), address(vaultFactory));
ledger.setRiskParameters(ethAddress, DEFAULT_DEBT_CEILING, DEFAULT_LIQUIDATION_RATIO, DEFAULT_CREDIT_MULTIPLIER);
entityRegistry.grantRole(entityRegistry.REGISTRAR_ROLE(), address(vaultFactory));
vm.stopBroadcast();
console.log("\n=== Vault System Finish Complete ===");
}
}

View File

@@ -0,0 +1,66 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {GRUVaultIndex} from "../../../contracts/vault/GRUVaultIndex.sol";
interface IGRUVaultIndexLegacy {
function allVaults(uint256 index) external view returns (address);
function vaults(address vault)
external
view
returns (
address entity,
address baseToken,
address depositToken,
address debtToken,
uint8 gruTier,
bytes32 ibanHash,
bytes32 policyProfileKey,
uint256 recordedAt,
bool active
);
}
/// @notice Import one legacy vault record into new GRUVaultIndex (use GRU_MIGRATE_INDEX).
contract ImportGruVaultRecord138 is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address oldIndex = vm.envAddress("OLD_GRU_VAULT_INDEX");
address newIndex = vm.envAddress("NEW_GRU_VAULT_INDEX");
bytes32 policyKey = vm.envBytes32("GRU_POLICY_PROFILE_KEY");
uint256 idx = vm.envUint("GRU_MIGRATE_INDEX");
IGRUVaultIndexLegacy legacy = IGRUVaultIndexLegacy(oldIndex);
GRUVaultIndex target = GRUVaultIndex(newIndex);
address vault;
try legacy.allVaults(idx) returns (address v) {
vault = v;
} catch {
revert("ImportGruVaultRecord138: index out of range");
}
(
address entity,
address baseToken,
address depositToken,
address debtToken,
uint8 gruTier,
bytes32 ibanHash,
bytes32 existingKey,
uint256 recordedAt,
bool active
) = legacy.vaults(vault);
require(active, "ImportGruVaultRecord138: inactive");
bytes32 key = existingKey == bytes32(0) ? policyKey : existingKey;
vm.startBroadcast(pk);
target.importVault(
vault, entity, baseToken, depositToken, debtToken, gruTier, ibanHash, key, recordedAt
);
vm.stopBroadcast();
console2.log("Imported", vault, "policy", vm.toString(key));
}
}

View File

@@ -0,0 +1,82 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {GRUVaultIndex} from "../../../contracts/vault/GRUVaultIndex.sol";
import {VaultFactory} from "../../../contracts/vault/VaultFactory.sol";
interface IGRUVaultIndexLegacy {
function allVaults(uint256 index) external view returns (address);
function vaults(address vault)
external
view
returns (
address entity,
address baseToken,
address depositToken,
address debtToken,
uint8 gruTier,
bytes32 ibanHash,
bytes32 policyProfileKey,
uint256 recordedAt,
bool active
);
}
/// @notice Deploy GRUVaultIndex v2 and migrate records from legacy index with policy profile backfill.
contract MigrateGRUVaultIndex138 is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address admin = vm.addr(pk);
address oldIndex = vm.envAddress("OLD_GRU_VAULT_INDEX");
address factory = vm.envAddress("VAULT_FACTORY_ADDRESS");
bytes32 policyKey = vm.envBytes32("GRU_POLICY_PROFILE_KEY");
vm.startBroadcast(pk);
GRUVaultIndex newIndex = new GRUVaultIndex(admin);
console2.log("New GRUVaultIndex:", address(newIndex));
IGRUVaultIndexLegacy legacy = IGRUVaultIndexLegacy(oldIndex);
uint256 imported;
for (uint256 i = 0; i < 32; i++) {
address vault;
try legacy.allVaults(i) returns (address v) {
vault = v;
} catch {
break;
}
if (vault == address(0)) break;
(
address entity,
address baseToken,
address depositToken,
address debtToken,
uint8 gruTier,
bytes32 ibanHash,
bytes32 existingKey,
uint256 recordedAt,
bool active
) = legacy.vaults(vault);
if (!active) continue;
bytes32 key = existingKey == bytes32(0) ? policyKey : existingKey;
newIndex.importVault(
vault, entity, baseToken, depositToken, debtToken, gruTier, ibanHash, key, recordedAt
);
imported++;
console2.log("Imported vault", vault);
}
newIndex.grantFactoryRole(factory);
VaultFactory(factory).setGruVaultIndex(address(newIndex));
vm.stopBroadcast();
console2.log("Migrated vault count:", imported);
console2.log("Update GRU_VAULT_INDEX to", address(newIndex));
}
}

View File

@@ -0,0 +1,44 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {RegulatedEntityRegistry} from "../../../contracts/vault/RegulatedEntityRegistry.sol";
import {GRUEntityIbanRegistry} from "../../../contracts/vault/GRUEntityIbanRegistry.sol";
/// @notice Register OMNL/DBIS entity + IBAN binding for GRU vault operations.
contract RegisterGRUEntityAndIban is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address entity = vm.envOr("GRU_OMNL_ENTITY_ADDRESS", vm.addr(pk));
address entityRegistryAddr = vm.envAddress("REGULATED_ENTITY_REGISTRY");
address ibanRegistryAddr = vm.envAddress("GRU_ENTITY_IBAN_REGISTRY");
bytes32 jurisdictionHash = vm.envOr("GRU_JURISDICTION_HASH", keccak256("OMNL"));
bytes32 ibanHash = vm.envBytes32("GRU_IBAN_HASH");
address directIban = vm.envOr("GRU_DIRECT_IBAN_ADDRESS", entity);
RegulatedEntityRegistry entityRegistry = RegulatedEntityRegistry(entityRegistryAddr);
GRUEntityIbanRegistry ibanRegistry = GRUEntityIbanRegistry(ibanRegistryAddr);
vm.startBroadcast(pk);
if (!entityRegistry.isEligible(entity)) {
address[] memory wallets = new address[](1);
wallets[0] = entity;
entityRegistry.registerEntity(entity, jurisdictionHash, wallets);
console2.log("Registered entity", entity);
} else {
console2.log("Entity already registered", entity);
}
(address existing,,, bool active) = ibanRegistry.getRecord(ibanHash);
if (!active) {
ibanRegistry.registerIban(ibanHash, entity, jurisdictionHash, directIban);
console2.log("Registered IBAN hash", vm.toString(ibanHash));
} else {
console2.log("IBAN already active for entity", existing);
}
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,44 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {Ledger} from "../../../contracts/vault/Ledger.sol";
/// @notice Register M1 c* tokens as ledger assets with default GRU vault risk parameters.
contract RegisterGruVaultLedgerAssets is Script {
uint256 constant DEFAULT_DEBT_CEILING = 1_000_000e18;
uint256 constant DEFAULT_LIQUIDATION_RATIO = 10_000;
uint256 constant DEFAULT_CREDIT_MULTIPLIER = 50_000;
function run() external {
address ledgerAddr = vm.envAddress("LEDGER_ADDRESS");
Ledger ledger = Ledger(ledgerAddr);
vm.startBroadcast(vm.envUint("PRIVATE_KEY"));
_registerIfSet(ledger, vm.envOr("CUSDC_ADDRESS_138", vm.envOr("COMPLIANT_USDC_ADDRESS", address(0))));
_registerIfSet(ledger, vm.envOr("CUSDT_ADDRESS_138", vm.envOr("COMPLIANT_USDT_ADDRESS", address(0))));
_registerIfSet(ledger, vm.envOr("cEURC_ADDRESS_138", address(0)));
_registerIfSet(ledger, vm.envOr("cEURT_ADDRESS_138", address(0)));
_registerIfSet(ledger, vm.envOr("cGBPC_ADDRESS_138", address(0)));
_registerIfSet(ledger, vm.envOr("cGBPT_ADDRESS_138", address(0)));
_registerIfSet(ledger, vm.envOr("cAUDC_ADDRESS_138", address(0)));
_registerIfSet(ledger, vm.envOr("cJPYC_ADDRESS_138", address(0)));
_registerIfSet(ledger, vm.envOr("cCHFC_ADDRESS_138", address(0)));
_registerIfSet(ledger, vm.envOr("cCADC_ADDRESS_138", address(0)));
_registerIfSet(ledger, vm.envOr("cXAUC_ADDRESS_138", address(0)));
_registerIfSet(ledger, vm.envOr("cXAUT_ADDRESS_138", address(0)));
_registerIfSet(ledger, vm.envOr("CUSDC_ADDRESS_651940", vm.envOr("AUSDC_ADDRESS_651940", address(0))));
_registerIfSet(ledger, vm.envOr("AUSDT_ADDRESS_651940", vm.envOr("CUSDT_ADDRESS_651940", address(0))));
_registerIfSet(ledger, vm.envOr("WALL_ADDRESS_651940", address(0)));
vm.stopBroadcast();
}
function _registerIfSet(Ledger ledger, address asset) internal {
if (asset == address(0)) return;
ledger.setRiskParameters(asset, DEFAULT_DEBT_CEILING, DEFAULT_LIQUIDATION_RATIO, DEFAULT_CREDIT_MULTIPLIER);
console2.log("Registered ledger asset", asset);
}
}

View File

@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {VaultFactory} from "../../../contracts/vault/VaultFactory.sol";
import {GRUVaultIndex} from "../../../contracts/vault/GRUVaultIndex.sol";
/// @notice Wire an existing VaultFactory to an existing GRUVaultIndex (post-deploy on any chain).
contract WireGRUVaultFactoryToIndex is Script {
function run() external {
address factoryAddr = vm.envAddress("VAULT_FACTORY_ADDRESS");
address indexAddr = vm.envAddress("GRU_VAULT_INDEX");
vm.startBroadcast(vm.envUint("PRIVATE_KEY"));
VaultFactory(factoryAddr).setGruVaultIndex(indexAddr);
GRUVaultIndex(indexAddr).grantFactoryRole(factoryAddr);
vm.stopBroadcast();
console2.log("Wired VaultFactory", factoryAddr);
console2.log("GRUVaultIndex", indexAddr);
}
}

View File

@@ -0,0 +1,24 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {ComplianceCore} from "../../contracts/hybx-omnl/ComplianceCore.sol";
/// @notice Deploy ComplianceCore pointing at ReserveCommitmentStore v2 (immutable reserves pointer).
contract DeployOMNLComplianceCoreV2 is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address registry = vm.envAddress("OMNL_INSTRUMENT_REGISTRY_138");
address reserves = vm.envAddress("OMNL_RESERVE_STORE_V2_138");
address breakers = vm.envAddress("OMNL_CIRCUIT_BREAKER_138");
vm.startBroadcast(pk);
ComplianceCore coreV2 = new ComplianceCore(registry, reserves, breakers);
vm.stopBroadcast();
console2.log("ComplianceCoreV2", address(coreV2));
console2.log("registry", registry);
console2.log("reservesV2", reserves);
console2.log("breakers", breakers);
}
}

View File

@@ -6,8 +6,11 @@ import {InstrumentRegistry} from "../../contracts/hybx-omnl/InstrumentRegistry.s
import {ReserveCommitmentStore} from "../../contracts/hybx-omnl/ReserveCommitmentStore.sol";
import {OMNLCircuitBreaker} from "../../contracts/hybx-omnl/OMNLCircuitBreaker.sol";
import {ComplianceCore} from "../../contracts/hybx-omnl/ComplianceCore.sol";
import {OMNLJurisdictionPolicyRegistry} from "../../contracts/hybx-omnl/OMNLJurisdictionPolicyRegistry.sol";
import {OMNLNotaryRegistry} from "../../contracts/hybx-omnl/OMNLNotaryRegistry.sol";
import {OMNLComplianceMultisig} from "../../contracts/hybx-omnl/OMNLComplianceMultisig.sol";
/// @notice Deploy core OMNL stack (registry, reserves, breakers, compliance). Mirror receiver is chain-specific.
/// @notice Deploy core OMNL stack + Web3 compliance (registry, reserves, breakers, compliance, notary, multisig).
contract DeployOMNLStack is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
@@ -20,11 +23,22 @@ contract DeployOMNLStack is Script {
OMNLCircuitBreaker breakers = new OMNLCircuitBreaker(admin);
ComplianceCore core = new ComplianceCore(address(registry), address(reserves), address(breakers));
OMNLJurisdictionPolicyRegistry jurisdiction = new OMNLJurisdictionPolicyRegistry(admin);
OMNLNotaryRegistry notary = new OMNLNotaryRegistry(admin, address(jurisdiction));
OMNLComplianceMultisig multisig = new OMNLComplianceMultisig(admin, address(notary));
bytes32 jurId = keccak256("ID");
bytes32 matrixId = keccak256("ID-OMNL-001");
reserves.configureNotaryGate(address(notary), false, jurId, matrixId);
vm.stopBroadcast();
console2.log("InstrumentRegistry", address(registry));
console2.log("ReserveCommitmentStore", address(reserves));
console2.log("OMNLCircuitBreaker", address(breakers));
console2.log("ComplianceCore", address(core));
console2.log("OMNLJurisdictionPolicyRegistry", address(jurisdiction));
console2.log("OMNLNotaryRegistry", address(notary));
console2.log("OMNLComplianceMultisig", address(multisig));
}
}

View File

@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {OMNLJurisdictionPolicyRegistry} from "../../contracts/hybx-omnl/OMNLJurisdictionPolicyRegistry.sol";
import {OMNLNotaryRegistry} from "../../contracts/hybx-omnl/OMNLNotaryRegistry.sol";
import {OMNLComplianceMultisig} from "../../contracts/hybx-omnl/OMNLComplianceMultisig.sol";
/// @notice Deploy Web3 compliance layer: jurisdiction policy registry, notary, multisig.
contract DeployOMNLWeb3Compliance is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address admin = vm.envOr("OMNL_WEB3_ADMIN", vm.addr(pk));
vm.startBroadcast(pk);
OMNLJurisdictionPolicyRegistry jurisdiction = new OMNLJurisdictionPolicyRegistry(admin);
OMNLNotaryRegistry notary = new OMNLNotaryRegistry(admin, address(jurisdiction));
OMNLComplianceMultisig multisig = new OMNLComplianceMultisig(admin, address(notary));
vm.stopBroadcast();
console2.log("OMNLJurisdictionPolicyRegistry", address(jurisdiction));
console2.log("OMNLNotaryRegistry", address(notary));
console2.log("OMNLComplianceMultisig", address(multisig));
}
}

View File

@@ -0,0 +1,42 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {ReserveCommitmentStore} from "../../contracts/hybx-omnl/ReserveCommitmentStore.sol";
/// @notice Deploy ReserveCommitmentStore v2 (notary gate ABI), migrate commitment from legacy store.
contract MigrateOMNLReserveStoreV2 is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address admin = vm.envOr("OMNL_WEB3_ADMIN", vm.addr(pk));
address legacyStore = vm.envAddress("OMNL_RESERVE_STORE_138");
address notary = vm.envAddress("OMNL_NOTARY_REGISTRY");
bytes32 lineId = vm.envBytes32("OMNL_HEALTH_LINE_ID");
bytes32 jurId = keccak256(bytes(vm.envOr("OMNL_JURISDICTION_ID", string("ID"))));
bytes32 matrixId = keccak256(bytes(vm.envOr("OMNL_MATRIX_CONTROL_ID", string("ID-OMNL-001"))));
bool requireNotary = vm.envOr("OMNL_REQUIRE_NOTARIZED_RESERVE", false);
uint256 attTh = vm.envOr("OMNL_RESERVE_ATTESTATION_THRESHOLD", uint256(3));
ReserveCommitmentStore legacy = ReserveCommitmentStore(legacyStore);
ReserveCommitmentStore.Commitment memory c = legacy.getCommitment(lineId);
address mirror = legacy.mirrorReceiver();
vm.startBroadcast(pk);
ReserveCommitmentStore storeV2 = new ReserveCommitmentStore(admin);
storeV2.configureNotaryGate(notary, requireNotary, jurId, matrixId);
storeV2.setAttestationThreshold(attTh);
if (mirror != address(0)) {
storeV2.setMirrorReceiver(mirror);
}
storeV2.commitReserve(lineId, c.R, c.validUntil, c.evidenceHash, c.merkleRoot);
vm.stopBroadcast();
console2.log("ReserveCommitmentStoreV2", address(storeV2));
console2.log("legacyStore", legacyStore);
console2.log("notaryGate", notary);
console2.log("migratedVersion", storeV2.getCommitment(lineId).version);
}
}

View File

@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {OMNLJurisdictionPolicyRegistry} from "../../contracts/hybx-omnl/OMNLJurisdictionPolicyRegistry.sol";
/// @notice Publish Indonesia pilot policy (extend via env for more jurisdictions).
contract PublishJurisdictionPolicies is Script {
function run() external {
address registry = vm.envAddress("OMNL_JURISDICTION_REGISTRY");
bytes32 policyHash = vm.envBytes32("OMNL_JURISDICTION_POLICY_HASH");
uint256 pk = vm.envUint("PRIVATE_KEY");
bytes32 jurId = keccak256(bytes(vm.envOr("OMNL_JURISDICTION_ID", string("ID"))));
uint8 notaryTh = uint8(vm.envOr("OMNL_NOTARY_THRESHOLD", uint256(3)));
uint8 reserveTh = uint8(vm.envOr("OMNL_RESERVE_ATTESTATION_THRESHOLD", uint256(3)));
uint8 adminTh = uint8(vm.envOr("OMNL_ADMIN_MULTISIG_THRESHOLD", uint256(3)));
bool prod = vm.envOr("OMNL_JURISDICTION_PRODUCTION_READY", true);
vm.startBroadcast(pk);
OMNLJurisdictionPolicyRegistry(registry).publishPolicy(
jurId, policyHash, notaryTh, reserveTh, adminTh, prod
);
vm.stopBroadcast();
console2.log("Published policy for jurisdiction", vm.toString(jurId));
}
}

View File

@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {ReserveCommitmentStore} from "../../contracts/hybx-omnl/ReserveCommitmentStore.sol";
/// @notice Refresh reserve TTL and optionally bump R / evidence hashes.
contract RefreshReserveAttestation is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address storeAddr = vm.envAddress("OMNL_RESERVE_STORE_138");
bytes32 lineId = vm.envBytes32("OMNL_HEALTH_LINE_ID");
uint256 ttlDays = vm.envOr("OMNL_RESERVE_TTL_DAYS", uint256(90));
uint256 validUntil = block.timestamp + ttlDays * 1 days;
ReserveCommitmentStore store = ReserveCommitmentStore(storeAddr);
ReserveCommitmentStore.Commitment memory c = store.getCommitment(lineId);
uint256 R = vm.envOr("OMNL_RESERVE_R", c.R);
bytes32 evidence = vm.envOr("OMNL_RESERVE_EVIDENCE_HASH", c.evidenceHash);
bytes32 merkle = vm.envOr("OMNL_RESERVE_MERKLE_ROOT", c.merkleRoot);
vm.startBroadcast(pk);
store.commitReserve(lineId, R, validUntil, evidence, merkle);
vm.stopBroadcast();
console2.log("Reserve refreshed lineId", vm.toString(lineId));
console2.log("validUntil", validUntil);
console2.log("R", R);
}
}

View File

@@ -0,0 +1,47 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IMintableM0 {
function mint(address to, uint256 amount) external;
function mint(address to, uint256 amount, bytes32 reasonHash) external;
}
/// @notice Mint M0 (cUSDT) so that S1 <= 5 * S0 for the health line (policy cap remediation).
contract RemediateOmnlM1Cap is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address tokenM0 = vm.envAddress("OMNL_TOKEN_M0");
address tokenM1 = vm.envAddress("OMNL_TOKEN_M1");
address mintTo = vm.envOr("OMNL_M1_REMEDIATION_MINT_TO", vm.addr(pk));
uint256 s0 = IERC20(tokenM0).totalSupply();
uint256 s1 = IERC20(tokenM1).totalSupply();
uint256 requiredS0 = (s1 + 4) / 5;
if (s0 >= requiredS0) {
console2.log("No mint required; s0", s0, "requiredS0", requiredS0);
return;
}
uint256 delta = requiredS0 - s0;
bytes32 reason = keccak256("OMNL-M1-CAP-REMEDIATION");
vm.startBroadcast(pk);
IMintableM0 m0 = IMintableM0(tokenM0);
try m0.mint(mintTo, delta, reason) {
} catch {
m0.mint(mintTo, delta);
}
vm.stopBroadcast();
uint256 s0After = IERC20(tokenM0).totalSupply();
uint256 s1After = IERC20(tokenM1).totalSupply();
bool m1OkAfter = s1After <= s0After * 5;
console2.log("Minted delta", delta, "to", mintTo);
console2.log("s0After", s0After);
console2.log("s1After", s1After);
console2.log("m1OkAfter", m1OkAfter);
}
}

View File

@@ -0,0 +1,33 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {ReserveCommitmentStore} from "../../contracts/hybx-omnl/ReserveCommitmentStore.sol";
import {OMNLNotaryRegistry} from "../../contracts/hybx-omnl/OMNLNotaryRegistry.sol";
import {OMNLComplianceMultisig} from "../../contracts/hybx-omnl/OMNLComplianceMultisig.sol";
/// @notice Wire reserve store notary gate + align attestation threshold with jurisdiction policy.
contract WireOMNLWeb3Compliance is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address reserves = vm.envAddress("OMNL_RESERVE_COMMITMENT_STORE");
address notary = vm.envAddress("OMNL_NOTARY_REGISTRY");
OMNLComplianceMultisig multisig = OMNLComplianceMultisig(payable(vm.envAddress("OMNL_COMPLIANCE_MULTISIG")));
bytes32 jurId = keccak256(bytes(vm.envOr("OMNL_JURISDICTION_ID", string("ID"))));
bytes32 matrixId = keccak256(bytes(vm.envOr("OMNL_MATRIX_CONTROL_ID", string("ID-OMNL-001"))));
bool requireNotary = vm.envOr("OMNL_REQUIRE_NOTARIZED_RESERVE", true);
uint256 attTh = vm.envOr("OMNL_RESERVE_ATTESTATION_THRESHOLD", uint256(3));
vm.startBroadcast(pk);
ReserveCommitmentStore(reserves).configureNotaryGate(notary, requireNotary, jurId, matrixId);
ReserveCommitmentStore(reserves).setAttestationThreshold(attTh);
address admin = vm.addr(pk);
OMNLNotaryRegistry(notary).grantRole(OMNLNotaryRegistry(notary).NOTARY_ADMIN_ROLE(), address(multisig));
multisig.grantRole(multisig.PROPOSER_ROLE(), admin);
vm.stopBroadcast();
console2.log("Wired notary gate on ReserveCommitmentStore", reserves);
}
}

View File

@@ -0,0 +1,151 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "forge-std/Script.sol";
import {GrcDiamond} from "@gru/GrcDiamond.sol";
import {IDiamondCut} from "@gru/interfaces/IDiamondCut.sol";
import {PauseFacet} from "@gru/facets/PauseFacet.sol";
import {AccessFacet} from "@gru/facets/AccessFacet.sol";
import {M00MainnetBridgeFacet} from "../../contracts/m00-diamond/facets/M00MainnetBridgeFacet.sol";
import {M00DiamondInit} from "../../contracts/m00-diamond/M00DiamondInit.sol";
import {RWAInstrumentFacet} from "../../contracts/rwa/diamond/facets/RWAInstrumentFacet.sol";
import {RWADocumentFacet} from "../../contracts/rwa/diamond/facets/RWADocumentFacet.sol";
import {RWAStandardsRegistryFacet} from "../../contracts/rwa/diamond/facets/RWAStandardsRegistryFacet.sol";
import {IM00MainnetBridgeFacet} from "../../contracts/m00-diamond/interfaces/IM00MainnetBridgeFacet.sol";
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
/**
* @title DeployM00DiamondHub138
* @notice Deploy GRC-2535 M00 Diamond hub on Chain 138 with RWA + mainnet mirror/tether/checkpoint bridge facet.
* @dev Paris profile mandatory. Wire env from project .env (load-project-env before forge).
*
* Env: PRIVATE_KEY, GOVERNANCE_CONTROLLER or OWNER
* CHAIN138_BATCH_EMITTER, TRANSACTION_MIRROR_ADDRESS (138 local), CHAIN138_MAINNET_CHECKPOINT_PROXY (mainnet)
* TRANSACTION_MIRROR_MAINNET, MAINNET_TETHER_ADDRESS
* RWA_TOKEN_FACTORY, RWA_TOKEN_REGISTRY
*/
contract DeployM00DiamondHub138 is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address deployer = vm.addr(pk);
address governance = vm.envOr("GOVERNANCE_CONTROLLER", vm.envOr("OWNER", deployer));
vm.startBroadcast(pk);
// Diamond owner must be broadcaster for initial diamondCut (ErrUpgradeRole otherwise).
GrcDiamond diamond = new GrcDiamond(deployer, "M00.1.0");
PauseFacet pause = new PauseFacet();
AccessFacet access = new AccessFacet();
M00MainnetBridgeFacet bridge = new M00MainnetBridgeFacet(governance);
RWAInstrumentFacet rwaInst = new RWAInstrumentFacet(governance);
RWADocumentFacet rwaDoc = new RWADocumentFacet(governance);
RWAStandardsRegistryFacet rwaStd = new RWAStandardsRegistryFacet(governance);
M00DiamondInit init = new M00DiamondInit();
IDiamondCut.FacetCut[] memory cut = _buildCuts(
address(pause), address(access), address(bridge), address(rwaInst), address(rwaDoc), address(rwaStd)
);
IM00MainnetBridgeFacet.BridgeConfig memory cfg = IM00MainnetBridgeFacet.BridgeConfig({
chain138BatchEmitter: vm.envOr("CHAIN138_BATCH_EMITTER", address(0)),
chain138Mirror: vm.envOr("TRANSACTION_MIRROR_ADDRESS", address(0)),
mainnetCheckpoint: vm.envOr("CHAIN138_MAINNET_CHECKPOINT_PROXY", address(0)),
mainnetMirror: vm.envOr("TRANSACTION_MIRROR_MAINNET", address(0)),
mainnetTether: vm.envOr("MAINNET_TETHER_ADDRESS", address(0)),
rwaTokenFactory: vm.envOr("RWA_TOKEN_FACTORY", address(0)),
rwaTokenRegistry: vm.envOr("RWA_TOKEN_REGISTRY", address(0))
});
diamond.diamondCut(cut, address(init), abi.encodeCall(M00DiamondInit.init, (cfg, governance)));
console.log("M00Diamond", address(diamond));
console.log("M00MainnetBridgeFacet", address(bridge));
console.log("RWAInstrumentFacet", address(rwaInst));
vm.stopBroadcast();
}
function _buildCuts(
address pause,
address access,
address bridge,
address rwaInst,
address rwaDoc,
address rwaStd
) internal pure returns (IDiamondCut.FacetCut[] memory cut) {
cut = new IDiamondCut.FacetCut[](6);
cut[0] = _add(pause, _pauseSelectors());
cut[1] = _add(access, _accessSelectors());
cut[2] = _add(bridge, _bridgeSelectors());
cut[3] = _add(rwaInst, _rwaInstSelectors());
cut[4] = _add(rwaDoc, _rwaDocSelectors());
cut[5] = _add(rwaStd, _rwaStdSelectors());
}
function _add(address facet, bytes4[] memory sels)
internal
pure
returns (IDiamondCut.FacetCut memory)
{
return IDiamondCut.FacetCut({
facetAddress: facet,
action: IDiamondCut.FacetCutAction.Add,
functionSelectors: sels
});
}
function _pauseSelectors() internal pure returns (bytes4[] memory s) {
s = new bytes4[](4);
s[0] = PauseFacet.setGlobalPause.selector;
s[1] = PauseFacet.setFunctionPause.selector;
s[2] = PauseFacet.isPaused.selector;
s[3] = PauseFacet.isGlobalPaused.selector;
}
function _accessSelectors() internal pure returns (bytes4[] memory s) {
s = new bytes4[](6);
s[0] = AccessFacet.grantRoles.selector;
s[1] = AccessFacet.revokeRoles.selector;
s[2] = AccessFacet.ROLE_UPGRADE_BIT.selector;
s[3] = AccessFacet.ROLE_GOVERNANCE_BIT.selector;
s[4] = AccessFacet.ROLE_INDEX_BIT.selector;
s[5] = AccessFacet.ROLE_MONETARY_BIT.selector;
}
function _bridgeSelectors() internal pure returns (bytes4[] memory s) {
s = new bytes4[](11);
s[0] = M00MainnetBridgeFacet.wireMainnetBridge.selector;
s[1] = M00MainnetBridgeFacet.getMainnetBridgeConfig.selector;
s[2] = M00MainnetBridgeFacet.commitBatchOn138.selector;
s[3] = M00MainnetBridgeFacet.sendBatchToMainnet.selector;
s[4] = M00MainnetBridgeFacet.scheduleMirrorToMainnet.selector;
s[5] = M00MainnetBridgeFacet.mirrorOnMainnet.selector;
s[6] = M00MainnetBridgeFacet.anchorStateProofOnMainnet.selector;
s[7] = M00MainnetBridgeFacet.ackInboundCheckpoint.selector;
s[8] = IAccessControl.grantRole.selector;
s[9] = IAccessControl.revokeRole.selector;
s[10] = IAccessControl.hasRole.selector;
}
function _rwaInstSelectors() internal pure returns (bytes4[] memory s) {
s = new bytes4[](5);
s[0] = RWAInstrumentFacet.setIssuanceMode.selector;
s[1] = RWAInstrumentFacet.setInstrumentIdentity.selector;
s[2] = RWAInstrumentFacet.setTokenPointer.selector;
s[3] = RWAInstrumentFacet.getIssuanceMode.selector;
s[4] = RWAInstrumentFacet.getTokenPointer.selector;
}
function _rwaDocSelectors() internal pure returns (bytes4[] memory s) {
s = new bytes4[](2);
s[0] = RWADocumentFacet.anchorDocument.selector;
s[1] = RWADocumentFacet.setPrimaryContentHash.selector;
}
function _rwaStdSelectors() internal pure returns (bytes4[] memory s) {
s = new bytes4[](3);
s[0] = RWAStandardsRegistryFacet.enableStandard.selector;
s[1] = RWAStandardsRegistryFacet.disableStandard.selector;
s[2] = RWAStandardsRegistryFacet.bindAssetStandardFacet.selector;
}
}

View File

@@ -0,0 +1,33 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "forge-std/Script.sol";
import {IDiamondCut} from "@gru/interfaces/IDiamondCut.sol";
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
/**
* @notice Add OZ AccessControl admin selectors to existing M00MainnetBridgeFacet on live hub.
*/
contract UpgradeM00DiamondAcl138 is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address diamond = vm.envAddress("M00_DIAMOND_HUB");
address bridgeFacet = vm.envAddress("M00_MAINNET_BRIDGE_FACET");
bytes4[] memory sels = new bytes4[](3);
sels[0] = IAccessControl.grantRole.selector;
sels[1] = IAccessControl.revokeRole.selector;
sels[2] = IAccessControl.hasRole.selector;
IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](1);
cut[0] = IDiamondCut.FacetCut({
facetAddress: bridgeFacet,
action: IDiamondCut.FacetCutAction.Add,
functionSelectors: sels
});
vm.startBroadcast(pk);
IDiamondCut(diamond).diamondCut(cut, address(0), "");
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,35 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script} from "forge-std/Script.sol";
import {CheckpointHubConfig} from "../../contracts/mainnet-checkpoint/libraries/CheckpointHubConfig.sol";
import {BatchEmitterConfig} from "../../contracts/mainnet-checkpoint/libraries/BatchEmitterConfig.sol";
/// @notice Shared env → config parsing for deploy/configure scripts.
abstract contract CheckpointConfigScript is Script {
function hubConfigFromEnv() internal view returns (CheckpointHubConfig.HubConfig memory cfg) {
cfg = CheckpointHubConfig.mainnetDefaults();
cfg.batchSize = uint16(vm.envOr("CHECKPOINT_BATCH_SIZE", uint256(cfg.batchSize)));
cfg.maxBatchWaitSeconds = uint32(vm.envOr("CHECKPOINT_MAX_WAIT_SECONDS", uint256(cfg.maxBatchWaitSeconds)));
cfg.minPaymentValueWei = vm.envOr("CHECKPOINT_MIN_PAYMENT_VALUE_WEI", uint256(0));
cfg.requireValidatorSigs = vm.envOr("CHECKPOINT_REQUIRE_VALIDATOR_SIGS", cfg.requireValidatorSigs);
cfg.allowCalldataOnlySubmit = vm.envOr("CHECKPOINT_ALLOW_CALLDATA_ONLY", cfg.allowCalldataOnlySubmit);
cfg.allowCCIPIngress = vm.envOr("CHECKPOINT_ALLOW_CCIP_INGRESS", cfg.allowCCIPIngress);
cfg.enforcePreviousBatchId = vm.envOr("CHECKPOINT_ENFORCE_PREVIOUS_BATCH_ID", cfg.enforcePreviousBatchId);
cfg.ccipRouter = vm.envOr("CCIP_ROUTER_MAINNET", address(0));
cfg.sourceChainSelector = uint64(vm.envOr("CCIP_CHAIN_SELECTOR_138", uint256(0)));
cfg.batchEmitterOnSource = vm.envOr("CHAIN138_BATCH_EMITTER", address(0));
cfg.legacyMirrorV1 = vm.envOr("TRANSACTION_MIRROR_MAINNET", address(0));
cfg.legacyTetherV1 = vm.envOr("MAINNET_TETHER_ADDRESS", address(0));
cfg.submitterAttestationSigner = vm.envOr("CHECKPOINT_ATTESTATION_SIGNER", address(0));
CheckpointHubConfig.validate(cfg);
}
function emitterConfigFromEnv() internal view returns (BatchEmitterConfig.EmitterConfig memory cfg) {
cfg.ccipRouter = vm.envAddress("CCIP_ROUTER_CHAIN138");
cfg.linkToken = vm.envAddress("LINK_TOKEN_CHAIN138");
cfg.mainnetChainSelector = uint64(vm.envUint("CCIP_CHAIN_SELECTOR_MAINNET"));
cfg.mainnetCheckpoint = vm.envAddress("CHAIN138_MAINNET_CHECKPOINT_PROXY");
BatchEmitterConfig.validate(cfg);
}
}

View File

@@ -0,0 +1,81 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {SubmitRateLimitExtension} from "../../contracts/mainnet-checkpoint/extensions/SubmitRateLimitExtension.sol";
import {TimelockSubmitExtension} from "../../contracts/mainnet-checkpoint/extensions/TimelockSubmitExtension.sol";
import {ValidatorSigVerifierExtension} from "../../contracts/mainnet-checkpoint/extensions/ValidatorSigVerifierExtension.sol";
import {TokenTransferFilterExtension} from "../../contracts/mainnet-checkpoint/extensions/TokenTransferFilterExtension.sol";
import {ZkStateRootVerifierExtension} from "../../contracts/mainnet-checkpoint/extensions/ZkStateRootVerifierExtension.sol";
import {BlockHeaderOracleExtension} from "../../contracts/mainnet-checkpoint/extensions/BlockHeaderOracleExtension.sol";
import {MinPaymentValueExtension} from "../../contracts/mainnet-checkpoint/extensions/MinPaymentValueExtension.sol";
/// @notice Per-extension granular tuning from env (post-deploy).
contract ConfigureCheckpointExtensions is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(pk);
address rateLimit = vm.envOr("EXT_RATE_LIMIT", address(0));
if (rateLimit != address(0)) {
uint256 maxPerHour = vm.envOr("CHECKPOINT_RATE_LIMIT_MAX_PER_HOUR", uint256(120));
SubmitRateLimitExtension(rateLimit).setMaxBatchesPerHour(maxPerHour);
console.log("RateLimit max/hour", maxPerHour);
}
address timelock = vm.envOr("EXT_TIMELOCK", address(0));
if (timelock != address(0)) {
uint256 delay = vm.envOr("CHECKPOINT_TIMELOCK_DELAY_SECONDS", uint256(48 hours));
TimelockSubmitExtension(timelock).setDelay(delay);
console.log("Timelock delay", delay);
}
address validator = vm.envOr("EXT_VALIDATOR_SIG", address(0));
if (validator != address(0)) {
address hub = vm.envAddress("CHAIN138_MAINNET_CHECKPOINT_PROXY");
ValidatorSigVerifierExtension(validator).setVerifyingContract(hub);
uint256 threshold = vm.envOr("CHECKPOINT_VALIDATOR_THRESHOLD", uint256(1));
address[] memory addrs = new address[](1);
addrs[0] = vm.envOr("CHECKPOINT_VALIDATOR_ADDRESS", vm.addr(pk));
ValidatorSigVerifierExtension(validator).setValidators(addrs, threshold);
}
address tokenFilter = vm.envOr("EXT_TOKEN_FILTER", address(0));
if (tokenFilter != address(0)) {
TokenTransferFilterExtension filter = TokenTransferFilterExtension(tokenFilter);
bool allowNative = vm.envOr("CHECKPOINT_TOKEN_FILTER_ALLOW_NATIVE", true);
uint256 minNative = vm.envOr("CHECKPOINT_TOKEN_FILTER_MIN_NATIVE_WEI", uint256(0));
filter.setAllowNative(allowNative, minNative);
_allowToken(filter, vm.envOr("CUSDT_CHAIN138", address(0)));
_allowToken(filter, vm.envOr("CUSDC_CHAIN138", address(0)));
}
address zk = vm.envOr("EXT_ZK_STATE_ROOT", address(0));
if (zk != address(0)) {
bool requireZk = vm.envOr("CHECKPOINT_REQUIRE_ZK_PROOF", false);
ZkStateRootVerifierExtension(zk).setRequireZkProof(requireZk);
}
address blockOracle = vm.envOr("EXT_BLOCK_ORACLE", address(0));
if (blockOracle != address(0)) {
BlockHeaderOracleExtension oracle = BlockHeaderOracleExtension(blockOracle);
oracle.setRequireOracleRecord(vm.envOr("CHECKPOINT_BLOCK_ORACLE_REQUIRED", true));
address updater = vm.envOr("CHECKPOINT_ORACLE_UPDATER", vm.addr(pk));
oracle.grantRole(keccak256("ORACLE_UPDATER_ROLE"), updater);
}
address minPay = vm.envOr("EXT_MIN_PAYMENT", address(0));
address hubProxy = vm.envOr("CHAIN138_MAINNET_CHECKPOINT_PROXY", address(0));
if (minPay != address(0) && hubProxy != address(0)) {
MinPaymentValueExtension(minPay).setHub(hubProxy);
}
vm.stopBroadcast();
}
function _allowToken(TokenTransferFilterExtension filter, address token) internal {
if (token == address(0)) return;
filter.setAllowedToken(token, true);
console.log("Allowed token", token);
}
}

View File

@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {Chain138MainnetCheckpoint} from "../../contracts/mainnet-checkpoint/Chain138MainnetCheckpoint.sol";
import {CheckpointHubConfig} from "../../contracts/mainnet-checkpoint/libraries/CheckpointHubConfig.sol";
import {CheckpointConfigScript} from "./CheckpointConfigLib.s.sol";
/// @notice Apply granular hub config from env (post-deploy). Run predeploy gate first.
contract ConfigureCheckpointHub is CheckpointConfigScript {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address proxy = vm.envAddress("CHAIN138_MAINNET_CHECKPOINT_PROXY");
Chain138MainnetCheckpoint hub = Chain138MainnetCheckpoint(proxy);
CheckpointHubConfig.HubConfig memory cfg = hubConfigFromEnv();
vm.startBroadcast(pk);
hub.applyConfig(cfg);
vm.stopBroadcast();
CheckpointHubConfig.HubConfig memory onChain = hub.getFullConfig();
console.log("batchSize", onChain.batchSize);
console.log("maxBatchWaitSeconds", onChain.maxBatchWaitSeconds);
console.log("allowCCIPIngress", onChain.allowCCIPIngress);
}
}

View File

@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {AddressActivityRegistry} from "../../contracts/mainnet-checkpoint/AddressActivityRegistry.sol";
contract DeployAddressActivityRegistry is Script {
function run() external {
address admin = vm.envOr("CHECKPOINT_ADMIN", msg.sender);
vm.startBroadcast();
AddressActivityRegistry registry = new AddressActivityRegistry(admin);
console.log("AddressActivityRegistry:", address(registry));
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {AddressActivityRegistryV2} from "../../contracts/mainnet-checkpoint/AddressActivityRegistryV2.sol";
contract DeployAddressActivityRegistryV2 is Script {
function run() external {
address admin = vm.envOr("CHECKPOINT_ADMIN", msg.sender);
vm.startBroadcast();
AddressActivityRegistryV2 registry = new AddressActivityRegistryV2(admin);
console.log("AddressActivityRegistryV2:", address(registry));
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,49 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {MirrorDetailExtension} from "../../contracts/mainnet-checkpoint/extensions/MirrorDetailExtension.sol";
import {ValidatorSigVerifierExtension} from "../../contracts/mainnet-checkpoint/extensions/ValidatorSigVerifierExtension.sol";
import {AttestationURIExtension} from "../../contracts/mainnet-checkpoint/extensions/AttestationURIExtension.sol";
import {SubmitRateLimitExtension} from "../../contracts/mainnet-checkpoint/extensions/SubmitRateLimitExtension.sol";
import {TokenTransferFilterExtension} from "../../contracts/mainnet-checkpoint/extensions/TokenTransferFilterExtension.sol";
import {CwTransportLinkExtension} from "../../contracts/mainnet-checkpoint/extensions/CwTransportLinkExtension.sol";
import {TimelockSubmitExtension} from "../../contracts/mainnet-checkpoint/extensions/TimelockSubmitExtension.sol";
import {MetricsExtension} from "../../contracts/mainnet-checkpoint/extensions/MetricsExtension.sol";
import {ZkStateRootVerifierExtension} from "../../contracts/mainnet-checkpoint/extensions/ZkStateRootVerifierExtension.sol";
import {PaymasterHintExtension} from "../../contracts/mainnet-checkpoint/extensions/PaymasterHintExtension.sol";
import {L2OracleAdapterExtension} from "../../contracts/mainnet-checkpoint/extensions/L2OracleAdapterExtension.sol";
import {BlockHeaderOracleExtension} from "../../contracts/mainnet-checkpoint/extensions/BlockHeaderOracleExtension.sol";
import {MinPaymentValueExtension} from "../../contracts/mainnet-checkpoint/extensions/MinPaymentValueExtension.sol";
import {LegacyCheckpointAdapter} from "../../contracts/mainnet-checkpoint/LegacyCheckpointAdapter.sol";
/// @notice Deploy all optional extension modules + legacy read adapter (non-proxy).
contract DeployAllCheckpointExtensions is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address admin = vm.envOr("CHECKPOINT_ADMIN", vm.addr(pk));
address checkpoint = vm.envAddress("CHAIN138_MAINNET_CHECKPOINT_PROXY");
address mirror = vm.envOr("TRANSACTION_MIRROR_MAINNET", address(0));
address tether = vm.envOr("MAINNET_TETHER_ADDRESS", address(0));
vm.startBroadcast(pk);
console.log("MirrorDetail:", address(new MirrorDetailExtension()));
console.log("ValidatorSig:", address(new ValidatorSigVerifierExtension()));
console.log("AttestationURI:", address(new AttestationURIExtension()));
console.log("RateLimit:", address(new SubmitRateLimitExtension()));
console.log("TokenFilter:", address(new TokenTransferFilterExtension()));
console.log("CwLink:", address(new CwTransportLinkExtension()));
console.log("Timelock:", address(new TimelockSubmitExtension()));
console.log("Metrics:", address(new MetricsExtension()));
console.log("ZkStateRoot:", address(new ZkStateRootVerifierExtension()));
console.log("PaymasterHint:", address(new PaymasterHintExtension()));
console.log("L2Oracle:", address(new L2OracleAdapterExtension()));
console.log("BlockOracle:", address(new BlockHeaderOracleExtension(admin)));
console.log("MinPayment:", address(new MinPaymentValueExtension()));
console.log("AddressActivityRegistry: deploy separately via scripts/deployment/deploy-address-activity-registry.sh");
if (mirror != address(0) && tether != address(0)) {
console.log("LegacyAdapter:", address(new LegacyCheckpointAdapter(checkpoint, mirror, tether)));
}
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {Chain138BatchEmitter} from "../../contracts/mainnet-checkpoint/chain138/Chain138BatchEmitter.sol";
contract DeployChain138BatchEmitter is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address admin = vm.envOr("CHECKPOINT_ADMIN", vm.addr(pk));
address ccipRouter = vm.envAddress("CCIP_ROUTER_CHAIN138");
address linkToken = vm.envAddress("LINK_TOKEN_CHAIN138");
uint64 mainnetSelector = uint64(vm.envUint("CCIP_CHAIN_SELECTOR_MAINNET"));
address mainnetCheckpoint = vm.envAddress("CHAIN138_MAINNET_CHECKPOINT_PROXY");
vm.startBroadcast(pk);
Chain138BatchEmitter impl = new Chain138BatchEmitter();
bytes memory initData = abi.encodeCall(
Chain138BatchEmitter.initialize,
(admin, ccipRouter, linkToken, mainnetSelector, mainnetCheckpoint)
);
ERC1967Proxy proxy = new ERC1967Proxy(address(impl), initData);
console.log("Chain138BatchEmitter impl:", address(impl));
console.log("Chain138BatchEmitter proxy:", address(proxy));
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {Chain138MainnetCheckpoint} from "../../contracts/mainnet-checkpoint/Chain138MainnetCheckpoint.sol";
contract DeployChain138MainnetCheckpoint is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address admin = vm.envOr("CHECKPOINT_ADMIN", vm.addr(pk));
address ccipRouter = vm.envAddress("CCIP_ROUTER_MAINNET");
uint64 sourceSelector = uint64(vm.envUint("CCIP_CHAIN_SELECTOR_138"));
address batchEmitter = vm.envOr("CHAIN138_BATCH_EMITTER", address(0));
vm.startBroadcast(pk);
Chain138MainnetCheckpoint impl = new Chain138MainnetCheckpoint();
bytes memory initData = abi.encodeCall(
Chain138MainnetCheckpoint.initialize,
(admin, ccipRouter, sourceSelector, batchEmitter)
);
ERC1967Proxy proxy = new ERC1967Proxy(address(impl), initData);
console.log("Chain138MainnetCheckpoint impl:", address(impl));
console.log("Chain138MainnetCheckpoint proxy:", address(proxy));
console.log("Admin:", admin);
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {Chain138ParticipantSurface} from "../../contracts/mainnet-checkpoint/Chain138ParticipantSurface.sol";
contract DeployChain138ParticipantSurface is Script {
function run() external {
address admin = vm.envOr("CHECKPOINT_ADMIN", msg.sender);
vm.startBroadcast();
Chain138ParticipantSurface surface = new Chain138ParticipantSurface(admin);
console.log("Chain138ParticipantSurface:", address(surface));
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {ISO20022IntakeGateway} from "../../contracts/mainnet-checkpoint/ISO20022IntakeGateway.sol";
contract DeployISO20022IntakeGateway is Script {
function run() external {
address admin = vm.envOr("CHECKPOINT_ADMIN", msg.sender);
vm.startBroadcast();
ISO20022IntakeGateway gateway = new ISO20022IntakeGateway(admin);
console.log("ISO20022IntakeGateway:", address(gateway));
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {Chain138MainnetCheckpoint} from "../../contracts/mainnet-checkpoint/Chain138MainnetCheckpoint.sol";
import {ExtensionIds} from "../../contracts/mainnet-checkpoint/libraries/ExtensionIds.sol";
/// @notice Re-enable extensions after hub v3 + token filter replace (env: EXT_VALIDATOR_SIG optional sanity).
contract ReenableCheckpointExtensions is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
Chain138MainnetCheckpoint hub = Chain138MainnetCheckpoint(vm.envAddress("CHAIN138_MAINNET_CHECKPOINT_PROXY"));
vm.startBroadcast(pk);
hub.setExtensionActive(ExtensionIds.VALIDATOR_SIG, true);
console.log("VALIDATOR_SIG active");
hub.setExtensionActive(ExtensionIds.TOKEN_FILTER, true);
console.log("TOKEN_FILTER active");
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,42 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {Chain138MainnetCheckpoint} from "../../contracts/mainnet-checkpoint/Chain138MainnetCheckpoint.sol";
import {ExtensionIds} from "../../contracts/mainnet-checkpoint/libraries/ExtensionIds.sol";
import {ICheckpointExtension} from "../../contracts/mainnet-checkpoint/interfaces/ICheckpointExtension.sol";
/// @notice Register deployed extensions on the checkpoint hub (env: EXT_* addresses).
contract RegisterCheckpointExtensions is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address proxy = vm.envAddress("CHAIN138_MAINNET_CHECKPOINT_PROXY");
Chain138MainnetCheckpoint hub = Chain138MainnetCheckpoint(proxy);
vm.startBroadcast(pk);
_register(hub, ExtensionIds.METRICS, vm.envAddress("EXT_METRICS"));
_register(hub, ExtensionIds.CONTENT_URI, vm.envAddress("EXT_ATTESTATION_URI"));
_register(hub, ExtensionIds.RATE_LIMIT, vm.envAddress("EXT_RATE_LIMIT"));
_register(hub, ExtensionIds.VALIDATOR_SIG, vm.envAddress("EXT_VALIDATOR_SIG"));
_register(hub, ExtensionIds.TOKEN_FILTER, vm.envAddress("EXT_TOKEN_FILTER"));
_register(hub, ExtensionIds.CW_LINK, vm.envAddress("EXT_CW_LINK"));
_register(hub, ExtensionIds.GOV_TIMELOCK, vm.envAddress("EXT_TIMELOCK"));
_register(hub, ExtensionIds.MIRROR_DETAIL, vm.envAddress("EXT_MIRROR_DETAIL"));
_register(hub, ExtensionIds.ZK_STATE_ROOT, vm.envAddress("EXT_ZK_STATE_ROOT"));
_register(hub, ExtensionIds.PAYMASTER_HINT, vm.envAddress("EXT_PAYMASTER_HINT"));
_register(hub, ExtensionIds.L2_ORACLE, vm.envAddress("EXT_L2_ORACLE"));
_register(hub, ExtensionIds.BLOCK_ORACLE, vm.envAddress("EXT_BLOCK_ORACLE"));
_register(hub, ExtensionIds.MIN_PAYMENT, vm.envAddress("EXT_MIN_PAYMENT"));
vm.stopBroadcast();
}
function _register(Chain138MainnetCheckpoint hub, bytes32 id, address module) internal {
if (module == address(0)) return;
uint32 hooks = ICheckpointExtension(module).HOOK_BEFORE_SUBMIT()
| ICheckpointExtension(module).HOOK_AFTER_SUBMIT()
| ICheckpointExtension(module).HOOK_ON_CCIP()
| ICheckpointExtension(module).HOOK_VERIFY_LEAF();
hub.registerExtension(id, module, hooks);
console.log("Registered", vm.toString(id), module);
}
}

View File

@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {Chain138MainnetCheckpoint} from "../../contracts/mainnet-checkpoint/Chain138MainnetCheckpoint.sol";
import {MirrorDetailExtension} from "../../contracts/mainnet-checkpoint/extensions/MirrorDetailExtension.sol";
import {ExtensionIds} from "../../contracts/mainnet-checkpoint/libraries/ExtensionIds.sol";
contract ReplaceMirrorDetailExtension is Script {
function run() external {
address proxy = vm.envAddress("CHAIN138_MAINNET_CHECKPOINT_PROXY");
address oldMirror = vm.envAddress("EXT_MIRROR_DETAIL");
uint256 pk = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(pk);
MirrorDetailExtension mirror = new MirrorDetailExtension();
console.log("New MirrorDetail:", address(mirror));
Chain138MainnetCheckpoint hub = Chain138MainnetCheckpoint(proxy);
hub.setExtensionActive(ExtensionIds.MIRROR_DETAIL, true);
hub.revokeExtension(ExtensionIds.MIRROR_DETAIL);
hub.registerExtension(ExtensionIds.MIRROR_DETAIL, address(mirror), mirror.HOOK_AFTER_SUBMIT());
hub.setExtensionActive(ExtensionIds.MIRROR_DETAIL, true);
console.log("Replaced mirror (old was):", oldMirror);
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,40 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {Chain138MainnetCheckpoint} from "../../contracts/mainnet-checkpoint/Chain138MainnetCheckpoint.sol";
import {ExtensionIds} from "../../contracts/mainnet-checkpoint/libraries/ExtensionIds.sol";
import {TokenTransferFilterExtension} from "../../contracts/mainnet-checkpoint/extensions/TokenTransferFilterExtension.sol";
import {ICheckpointExtension} from "../../contracts/mainnet-checkpoint/interfaces/ICheckpointExtension.sol";
/// @notice Deploy fixed TokenTransferFilterExtension and swap on hub (revoke + register).
contract ReplaceTokenTransferFilterExtension is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
address hubAddr = vm.envAddress("CHAIN138_MAINNET_CHECKPOINT_PROXY");
Chain138MainnetCheckpoint hub = Chain138MainnetCheckpoint(hubAddr);
vm.startBroadcast(pk);
TokenTransferFilterExtension filter = new TokenTransferFilterExtension();
console.log("New TokenTransferFilter:", address(filter));
bool allowNative = vm.envOr("CHECKPOINT_TOKEN_FILTER_ALLOW_NATIVE", true);
uint256 minNative = vm.envOr("CHECKPOINT_TOKEN_FILTER_MIN_NATIVE_WEI", uint256(0));
filter.setAllowNative(allowNative, minNative);
bytes32 id = ExtensionIds.TOKEN_FILTER;
(, , bool wasActive) = hub.getExtension(id);
if (!wasActive) {
hub.setExtensionActive(id, true);
}
hub.revokeExtension(id);
uint32 hooks = ICheckpointExtension(address(filter)).HOOK_BEFORE_SUBMIT()
| ICheckpointExtension(address(filter)).HOOK_AFTER_SUBMIT()
| ICheckpointExtension(address(filter)).HOOK_ON_CCIP()
| ICheckpointExtension(address(filter)).HOOK_VERIFY_LEAF();
hub.registerExtension(id, address(filter), hooks);
hub.setExtensionActive(id, true);
console.log("TOKEN_FILTER registered and active");
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {Chain138MainnetCheckpoint} from "../../contracts/mainnet-checkpoint/Chain138MainnetCheckpoint.sol";
/// @notice Replay aggregator calldata on a mainnet fork to surface revert reason.
contract SimulateSubmitFromCalldata is Script {
function run() external {
address hub = vm.envAddress("CHAIN138_MAINNET_CHECKPOINT_PROXY");
bytes memory data = vm.envBytes("CHECKPOINT_SUBMIT_CALLDATA");
vm.prank(vm.envAddress("CHECKPOINT_SUBMIT_FROM"));
(bool ok, bytes memory ret) = hub.call(data);
if (!ok) {
if (ret.length > 0) {
console.logBytes(ret);
}
revert("submit simulation failed");
}
console.log("ok, latest", Chain138MainnetCheckpoint(hub).getLatestBatchId());
}
}

View File

@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {Chain138MainnetCheckpoint} from "../../contracts/mainnet-checkpoint/Chain138MainnetCheckpoint.sol";
/// @notice UUPS upgrade: extension hook wiring (validator sigs vs leaf payload). IMPLEMENTATION_VERSION 3.
contract UpgradeChain138MainnetCheckpointV3 is Script {
function run() external {
address proxy = vm.envAddress("CHAIN138_MAINNET_CHECKPOINT_PROXY");
uint256 pk = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(pk);
Chain138MainnetCheckpoint newImpl = new Chain138MainnetCheckpoint();
console.log("New impl:", address(newImpl));
Chain138MainnetCheckpoint(proxy).upgradeToAndCall(address(newImpl), "");
console.log("Upgraded proxy:", proxy);
require(Chain138MainnetCheckpoint(proxy).IMPLEMENTATION_VERSION() == 3, "version");
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,20 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console} from "forge-std/Script.sol";
import {Chain138MainnetCheckpoint} from "../../contracts/mainnet-checkpoint/Chain138MainnetCheckpoint.sol";
/// @notice UUPS upgrade: PaymentLeafV2 submit + V2 extension payloads. IMPLEMENTATION_VERSION 4.
contract UpgradeChain138MainnetCheckpointV4 is Script {
function run() external {
address proxy = vm.envAddress("CHAIN138_MAINNET_CHECKPOINT_PROXY");
uint256 pk = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(pk);
Chain138MainnetCheckpoint newImpl = new Chain138MainnetCheckpoint();
console.log("New impl v4:", address(newImpl));
Chain138MainnetCheckpoint(proxy).upgradeToAndCall(address(newImpl), "");
require(Chain138MainnetCheckpoint(proxy).IMPLEMENTATION_VERSION() == 4, "version");
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Script.sol";
import {CWMirrorMeshBatch} from "../../contracts/ops/CWMirrorMeshBatch.sol";
contract DeployCWMirrorMeshBatch is Script {
function run() external returns (CWMirrorMeshBatch batch) {
address bridge = vm.envAddress("CW_L1_BRIDGE_CHAIN138");
address link = vm.envAddress("LINK_TOKEN_CHAIN138");
vm.startBroadcast();
batch = new CWMirrorMeshBatch(bridge, link);
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Script, console2} from "forge-std/Script.sol";
import {PolicyProfileRegistry} from "../../../contracts/universal-resource/PolicyProfileRegistry.sol";
/// @notice Publish commercial_emoney_m1_v1 profile anchor on live PolicyProfileRegistry.
contract PublishCommercialEmoneyM1Profile is Script {
function run() external {
PolicyProfileRegistry reg = PolicyProfileRegistry(vm.envAddress("POLICY_PROFILE_REGISTRY_ADDRESS"));
bytes32 contentHash = vm.envBytes32("COMMERCIAL_EMONEY_M1_CONTENT_HASH");
vm.startBroadcast(vm.envUint("PRIVATE_KEY"));
reg.publishProfile("commercial_emoney_m1_v1", contentHash, 1, block.timestamp);
vm.stopBroadcast();
bytes32 key = reg.profileKey("commercial_emoney_m1_v1");
console2.log("Published commercial_emoney_m1_v1");
console2.logBytes32(key);
}
}