feat: bridges, PMM, flash workflow, token-aggregation, and deployment docs
- CCIP/trustless bridge contracts, GRU tokens, DEX/PMM tests, reserve vault. - Token-aggregation service routes, planner, chain config, relay env templates. - Config snapshots and multi-chain deployment markdown updates. - gitignore services/btc-intake/dist/ (tsc output); do not track dist. Run forge build && forge test before deploy (large solc graph). Made-with: Cursor
This commit is contained in:
36
script/deploy/DeployAaveQuotePushFlashReceiver.s.sol
Normal file
36
script/deploy/DeployAaveQuotePushFlashReceiver.s.sol
Normal file
@@ -0,0 +1,36 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Script, console} from "forge-std/Script.sol";
|
||||
import {AaveQuotePushFlashReceiver} from "../../contracts/flash/AaveQuotePushFlashReceiver.sol";
|
||||
|
||||
/**
|
||||
* @title DeployAaveQuotePushFlashReceiver
|
||||
* @notice Deploy the Aave V3 quote-push flash receiver.
|
||||
*
|
||||
* Env:
|
||||
* PRIVATE_KEY required
|
||||
* AAVE_POOL_ADDRESS optional; defaults to Aave V3 mainnet Pool
|
||||
*
|
||||
* Usage:
|
||||
* forge script script/deploy/DeployAaveQuotePushFlashReceiver.s.sol:DeployAaveQuotePushFlashReceiver \
|
||||
* --rpc-url $ETHEREUM_MAINNET_RPC --broadcast -vvvv
|
||||
*/
|
||||
contract DeployAaveQuotePushFlashReceiver is Script {
|
||||
address internal constant DEFAULT_AAVE_POOL_MAINNET = 0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2;
|
||||
|
||||
function run() external {
|
||||
uint256 pk = vm.envUint("PRIVATE_KEY");
|
||||
address pool = vm.envOr("AAVE_POOL_ADDRESS", DEFAULT_AAVE_POOL_MAINNET);
|
||||
address deployer = vm.addr(pk);
|
||||
|
||||
console.log("Deployer:", deployer);
|
||||
console.log("Aave Pool:", pool);
|
||||
|
||||
vm.startBroadcast(pk);
|
||||
AaveQuotePushFlashReceiver receiver = new AaveQuotePushFlashReceiver(pool);
|
||||
vm.stopBroadcast();
|
||||
|
||||
console.log("AaveQuotePushFlashReceiver:", address(receiver));
|
||||
}
|
||||
}
|
||||
146
script/deploy/DeployAndStageCompliantFiatTokensV2ForChain.s.sol
Normal file
146
script/deploy/DeployAndStageCompliantFiatTokensV2ForChain.s.sol
Normal file
@@ -0,0 +1,146 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Script, console} from "forge-std/Script.sol";
|
||||
import {CompliantUSDTTokenV2} from "../../contracts/tokens/CompliantUSDTTokenV2.sol";
|
||||
import {CompliantUSDCTokenV2} from "../../contracts/tokens/CompliantUSDCTokenV2.sol";
|
||||
import {UniversalAssetRegistry} from "../../contracts/registry/UniversalAssetRegistry.sol";
|
||||
|
||||
/**
|
||||
* @title DeployAndStageCompliantFiatTokensV2ForChain
|
||||
* @notice Deploy fresh source-aligned cUSDT V2 / cUSDC V2 contracts, optionally wire governance/disclosure metadata,
|
||||
* and stage them in UniversalAssetRegistry as version-aware GRU assets.
|
||||
*
|
||||
* Env:
|
||||
* PRIVATE_KEY (required)
|
||||
* INITIAL_OPERATOR (optional; default deployer)
|
||||
* ADMIN (optional; default deployer / OWNER alias)
|
||||
* OWNER (optional alias for ADMIN when ADMIN unset)
|
||||
* INITIAL_SUPPLY (optional; default 0 for safe promotion)
|
||||
* FORWARD_CANONICAL (optional; default true for promotion flow)
|
||||
* GOVERNANCE_CONTROLLER (optional; when set, calls setGovernanceController on fresh deployments)
|
||||
* UNIVERSAL_ASSET_REGISTRY (optional; when set and REGISTER_IN_GRU != 0, registers V2 assets)
|
||||
* REGISTER_IN_GRU (optional; default 1)
|
||||
* TOKEN_URI (optional generic fallback)
|
||||
* REGULATORY_DISCLOSURE_URI (optional)
|
||||
* REPORTING_URI (optional)
|
||||
* CUSDT_V2_TOKEN_URI / CUSDC_V2_TOKEN_URI (optional; per-token overrides)
|
||||
* CUSDT_V2_REGULATORY_DISCLOSURE_URI / CUSDC_V2_REGULATORY_DISCLOSURE_URI (optional; per-token overrides)
|
||||
* CUSDT_V2_REPORTING_URI / CUSDC_V2_REPORTING_URI (optional; per-token overrides)
|
||||
* DEPLOY_CUSDT_V2 / DEPLOY_CUSDC_V2 (optional; default both 1)
|
||||
*/
|
||||
contract DeployAndStageCompliantFiatTokensV2ForChain is Script {
|
||||
uint256 internal constant DEFAULT_INITIAL_SUPPLY = 0;
|
||||
|
||||
function run() external {
|
||||
uint256 pk = vm.envUint("PRIVATE_KEY");
|
||||
address deployer = vm.addr(pk);
|
||||
address initialOperator = vm.envOr("INITIAL_OPERATOR", deployer);
|
||||
address ownerAlias = vm.envOr("OWNER", deployer);
|
||||
address admin = vm.envOr("ADMIN", ownerAlias);
|
||||
uint256 initialSupply = vm.envOr("INITIAL_SUPPLY", DEFAULT_INITIAL_SUPPLY);
|
||||
bool forwardCanonical = vm.envOr("FORWARD_CANONICAL", true);
|
||||
address governanceController = vm.envOr("GOVERNANCE_CONTROLLER", address(0));
|
||||
address registryAddr = vm.envOr("UNIVERSAL_ASSET_REGISTRY", address(0));
|
||||
bool registerInGru = vm.envOr("REGISTER_IN_GRU", uint256(1)) != 0;
|
||||
string memory genericTokenURI = vm.envOr("TOKEN_URI", string(""));
|
||||
string memory disclosureURI = vm.envOr("REGULATORY_DISCLOSURE_URI", string(""));
|
||||
string memory reportingURI = vm.envOr("REPORTING_URI", string(""));
|
||||
|
||||
vm.startBroadcast(pk);
|
||||
|
||||
if (vm.envOr("DEPLOY_CUSDT_V2", uint256(1)) != 0) {
|
||||
CompliantUSDTTokenV2 cusdtV2 =
|
||||
new CompliantUSDTTokenV2(initialOperator, admin, initialSupply, forwardCanonical);
|
||||
_postDeploy(
|
||||
address(cusdtV2),
|
||||
vm.envOr("CUSDT_V2_TOKEN_URI", genericTokenURI),
|
||||
"cUSDT",
|
||||
governanceController,
|
||||
vm.envOr("CUSDT_V2_REGULATORY_DISCLOSURE_URI", disclosureURI),
|
||||
vm.envOr("CUSDT_V2_REPORTING_URI", reportingURI),
|
||||
registryAddr,
|
||||
registerInGru,
|
||||
"Tether USD (Compliant V2)",
|
||||
"cUSDT.v2"
|
||||
);
|
||||
console.log("cUSDT_V2", address(cusdtV2));
|
||||
}
|
||||
|
||||
if (vm.envOr("DEPLOY_CUSDC_V2", uint256(1)) != 0) {
|
||||
CompliantUSDCTokenV2 cusdcV2 =
|
||||
new CompliantUSDCTokenV2(initialOperator, admin, initialSupply, forwardCanonical);
|
||||
_postDeploy(
|
||||
address(cusdcV2),
|
||||
vm.envOr("CUSDC_V2_TOKEN_URI", genericTokenURI),
|
||||
"cUSDC",
|
||||
governanceController,
|
||||
vm.envOr("CUSDC_V2_REGULATORY_DISCLOSURE_URI", disclosureURI),
|
||||
vm.envOr("CUSDC_V2_REPORTING_URI", reportingURI),
|
||||
registryAddr,
|
||||
registerInGru,
|
||||
"USD Coin (Compliant V2)",
|
||||
"cUSDC.v2"
|
||||
);
|
||||
console.log("cUSDC_V2", address(cusdcV2));
|
||||
}
|
||||
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
|
||||
function _postDeploy(
|
||||
address token,
|
||||
string memory tokenURI,
|
||||
string memory symbolDisplay,
|
||||
address governanceController,
|
||||
string memory disclosureURI,
|
||||
string memory reportingURI,
|
||||
address registryAddr,
|
||||
bool registerInGru,
|
||||
string memory name,
|
||||
string memory versionedSymbol
|
||||
) internal {
|
||||
if (bytes(tokenURI).length > 0 || bytes(symbolDisplay).length > 0) {
|
||||
_setPresentationMetadata(token, tokenURI, symbolDisplay);
|
||||
}
|
||||
if (governanceController != address(0)) {
|
||||
_setGovernanceController(token, governanceController);
|
||||
}
|
||||
if (bytes(disclosureURI).length > 0 || bytes(reportingURI).length > 0) {
|
||||
_setDisclosureMetadata(token, disclosureURI, reportingURI);
|
||||
}
|
||||
if (registerInGru && registryAddr != address(0)) {
|
||||
UniversalAssetRegistry(registryAddr).registerGRUCompliantAsset(token, name, versionedSymbol, 6, "International");
|
||||
}
|
||||
}
|
||||
|
||||
function _setPresentationMetadata(address token, string memory tokenURI, string memory symbolDisplay) internal {
|
||||
(bool ok,) = token.call(
|
||||
abi.encodeWithSignature(
|
||||
"emergencySetPresentationMetadata(bool,string,string)",
|
||||
true,
|
||||
tokenURI,
|
||||
symbolDisplay
|
||||
)
|
||||
);
|
||||
require(ok, "emergencySetPresentationMetadata failed");
|
||||
}
|
||||
|
||||
function _setGovernanceController(address token, address governanceController) internal {
|
||||
(bool ok,) = token.call(
|
||||
abi.encodeWithSignature("setGovernanceController(address)", governanceController)
|
||||
);
|
||||
require(ok, "setGovernanceController failed");
|
||||
}
|
||||
|
||||
function _setDisclosureMetadata(address token, string memory disclosureURI, string memory reportingURI) internal {
|
||||
(bool ok,) = token.call(
|
||||
abi.encodeWithSignature(
|
||||
"emergencySetDisclosureMetadata(string,string)",
|
||||
disclosureURI,
|
||||
reportingURI
|
||||
)
|
||||
);
|
||||
require(ok, "emergencySetDisclosureMetadata failed");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Script, console} from "forge-std/Script.sol";
|
||||
import {CompliantFiatTokenV2} from "../../contracts/tokens/CompliantFiatTokenV2.sol";
|
||||
import {UniversalAssetRegistry} from "../../contracts/registry/UniversalAssetRegistry.sol";
|
||||
|
||||
/**
|
||||
* @title DeployAndStageGenericCompliantFiatTokenV2ForChain
|
||||
* @notice Deploy a generic GRU c* V2 asset, optionally wire governance / disclosure metadata,
|
||||
* and stage it in UniversalAssetRegistry.
|
||||
*
|
||||
* Env:
|
||||
* PRIVATE_KEY (required)
|
||||
* TOKEN_NAME (required)
|
||||
* TOKEN_SYMBOL (required)
|
||||
* CURRENCY_CODE (required)
|
||||
* TOKEN_DECIMALS (optional; default 6)
|
||||
* VERSION_TAG (optional; default "2")
|
||||
* INITIAL_OPERATOR (optional; default deployer)
|
||||
* ADMIN / OWNER (optional; default deployer)
|
||||
* INITIAL_SUPPLY (optional; default 0)
|
||||
* FORWARD_CANONICAL (optional; default true)
|
||||
* GOVERNANCE_CONTROLLER (optional)
|
||||
* UNIVERSAL_ASSET_REGISTRY (optional; when set and REGISTER_IN_GRU != 0, registers the asset)
|
||||
* REGISTER_IN_GRU (optional; default 1)
|
||||
* REGISTRY_NAME (optional; default TOKEN_NAME)
|
||||
* REGISTRY_SYMBOL (optional; default TOKEN_SYMBOL.VERSION_TAG lower-suffix style is not enforced)
|
||||
* TOKEN_URI / REGULATORY_DISCLOSURE_URI / REPORTING_URI (optional)
|
||||
*/
|
||||
contract DeployAndStageGenericCompliantFiatTokenV2ForChain is Script {
|
||||
uint256 internal constant DEFAULT_INITIAL_SUPPLY = 0;
|
||||
|
||||
function run() external {
|
||||
uint256 pk = vm.envUint("PRIVATE_KEY");
|
||||
address deployer = vm.addr(pk);
|
||||
address initialOperator = vm.envOr("INITIAL_OPERATOR", deployer);
|
||||
address ownerAlias = vm.envOr("OWNER", deployer);
|
||||
address admin = vm.envOr("ADMIN", ownerAlias);
|
||||
uint256 initialSupply = vm.envOr("INITIAL_SUPPLY", DEFAULT_INITIAL_SUPPLY);
|
||||
bool forwardCanonical = vm.envOr("FORWARD_CANONICAL", true);
|
||||
address governanceController = vm.envOr("GOVERNANCE_CONTROLLER", address(0));
|
||||
address registryAddr = vm.envOr("UNIVERSAL_ASSET_REGISTRY", address(0));
|
||||
bool registerInGru = vm.envOr("REGISTER_IN_GRU", uint256(1)) != 0;
|
||||
|
||||
string memory tokenName = vm.envString("TOKEN_NAME");
|
||||
string memory tokenSymbol = vm.envString("TOKEN_SYMBOL");
|
||||
string memory currencyCode = vm.envString("CURRENCY_CODE");
|
||||
uint8 tokenDecimals = uint8(vm.envOr("TOKEN_DECIMALS", uint256(6)));
|
||||
string memory versionTag = vm.envOr("VERSION_TAG", string("2"));
|
||||
string memory registryName = vm.envOr("REGISTRY_NAME", tokenName);
|
||||
string memory registrySymbol = vm.envOr("REGISTRY_SYMBOL", tokenSymbol);
|
||||
string memory tokenURI = vm.envOr("TOKEN_URI", string(""));
|
||||
string memory disclosureURI = vm.envOr("REGULATORY_DISCLOSURE_URI", string(""));
|
||||
string memory reportingURI = vm.envOr("REPORTING_URI", string(""));
|
||||
|
||||
vm.startBroadcast(pk);
|
||||
|
||||
CompliantFiatTokenV2 token = new CompliantFiatTokenV2(
|
||||
tokenName,
|
||||
tokenSymbol,
|
||||
tokenDecimals,
|
||||
currencyCode,
|
||||
versionTag,
|
||||
initialOperator,
|
||||
admin,
|
||||
initialSupply,
|
||||
forwardCanonical
|
||||
);
|
||||
|
||||
if (bytes(tokenURI).length > 0 || bytes(tokenSymbol).length > 0) {
|
||||
_setPresentationMetadata(address(token), tokenURI, tokenSymbol);
|
||||
}
|
||||
if (governanceController != address(0)) {
|
||||
_setGovernanceController(address(token), governanceController);
|
||||
}
|
||||
if (bytes(disclosureURI).length > 0 || bytes(reportingURI).length > 0) {
|
||||
_setDisclosureMetadata(address(token), disclosureURI, reportingURI);
|
||||
}
|
||||
if (registerInGru && registryAddr != address(0)) {
|
||||
UniversalAssetRegistry(registryAddr).registerGRUCompliantAsset(
|
||||
address(token),
|
||||
registryName,
|
||||
registrySymbol,
|
||||
tokenDecimals,
|
||||
"International"
|
||||
);
|
||||
}
|
||||
|
||||
console.log("generic_cstar_v2", address(token));
|
||||
console.log("token_symbol", tokenSymbol);
|
||||
console.log("currency_code", currencyCode);
|
||||
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
|
||||
function _setPresentationMetadata(address token, string memory tokenURI, string memory symbolDisplay) internal {
|
||||
(bool ok,) = token.call(
|
||||
abi.encodeWithSignature(
|
||||
"emergencySetPresentationMetadata(bool,string,string)",
|
||||
true,
|
||||
tokenURI,
|
||||
symbolDisplay
|
||||
)
|
||||
);
|
||||
require(ok, "emergencySetPresentationMetadata failed");
|
||||
}
|
||||
|
||||
function _setGovernanceController(address token, address governanceController) internal {
|
||||
(bool ok,) = token.call(
|
||||
abi.encodeWithSignature("setGovernanceController(address)", governanceController)
|
||||
);
|
||||
require(ok, "setGovernanceController failed");
|
||||
}
|
||||
|
||||
function _setDisclosureMetadata(address token, string memory disclosureURI, string memory reportingURI) internal {
|
||||
(bool ok,) = token.call(
|
||||
abi.encodeWithSignature(
|
||||
"emergencySetDisclosureMetadata(string,string)",
|
||||
disclosureURI,
|
||||
reportingURI
|
||||
)
|
||||
);
|
||||
require(ok, "emergencySetDisclosureMetadata failed");
|
||||
}
|
||||
}
|
||||
53
script/deploy/DeployCAUSDT.s.sol
Normal file
53
script/deploy/DeployCAUSDT.s.sol
Normal file
@@ -0,0 +1,53 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import "forge-std/Script.sol";
|
||||
import {CREATE2Factory} from "../../contracts/utils/CREATE2Factory.sol";
|
||||
import {CompliantFiatToken} from "../../contracts/tokens/CompliantFiatToken.sol";
|
||||
|
||||
/**
|
||||
* @title DeployCAUSDT
|
||||
* @notice Deterministically deploy the Chain 138 cAUSDT contract via CREATE2.
|
||||
*
|
||||
* Env:
|
||||
* PRIVATE_KEY (required)
|
||||
* CREATE2_FACTORY_ADDRESS (required; CREATE2_FACTORY accepted as fallback)
|
||||
* OWNER / ADMIN (optional; default deployer)
|
||||
* INITIAL_SUPPLY_CAUSDT (optional; defaults to 1_000_000e6)
|
||||
*/
|
||||
contract DeployCAUSDT is Script {
|
||||
uint8 constant DECIMALS = 6;
|
||||
string constant SYMBOL = "cAUSDT";
|
||||
string constant NAME = "Alltra USD Token (Compliant)";
|
||||
string constant CURRENCY_CODE = "USD";
|
||||
|
||||
function run() external returns (address deployed) {
|
||||
uint256 pk = vm.envUint("PRIVATE_KEY");
|
||||
address deployer = vm.addr(pk);
|
||||
address owner = vm.envOr("OWNER", deployer);
|
||||
address admin = vm.envOr("ADMIN", deployer);
|
||||
uint256 initialSupply = vm.envOr("INITIAL_SUPPLY_CAUSDT", uint256(1_000_000 * 10**6));
|
||||
|
||||
address factoryAddr = vm.envOr("CREATE2_FACTORY_ADDRESS", vm.envAddress("CREATE2_FACTORY"));
|
||||
require(factoryAddr != address(0), "CREATE2 factory required");
|
||||
CREATE2Factory factory = CREATE2Factory(factoryAddr);
|
||||
|
||||
uint256 salt = uint256(keccak256(abi.encodePacked("CompliantFiatToken.", SYMBOL)));
|
||||
bytes memory bytecode = abi.encodePacked(
|
||||
type(CompliantFiatToken).creationCode,
|
||||
abi.encode(NAME, SYMBOL, uint8(DECIMALS), CURRENCY_CODE, owner, admin, initialSupply)
|
||||
);
|
||||
|
||||
deployed = factory.computeAddress(bytecode, salt);
|
||||
if (deployed.code.length > 0) {
|
||||
console.log("cAUSDT already deployed", deployed);
|
||||
return deployed;
|
||||
}
|
||||
|
||||
vm.startBroadcast(pk);
|
||||
deployed = factory.deploy(bytecode, salt);
|
||||
vm.stopBroadcast();
|
||||
|
||||
console.log("cAUSDT", deployed);
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,10 @@ import {CompliantWrappedToken} from "../../contracts/tokens/CompliantWrappedToke
|
||||
* Env:
|
||||
* PRIVATE_KEY (required)
|
||||
* CW_BRIDGE_ADDRESS (required) — address that can mint/burn (e.g. CCIP receiver or custom bridge)
|
||||
* DEPLOY_CWUSDT=1, DEPLOY_CWUSDC=1, DEPLOY_CWEURC=1, ... (default all 1; set 0 to skip a token)
|
||||
* CW_STRICT_MODE=1 (optional) — revoke deployer MINTER/BURNER after bridge grant
|
||||
* CW_GOVERNANCE_ADMIN=0x... (optional) — grant DEFAULT_ADMIN_ROLE to governance; if strict, revoke deployer admin when governance is set
|
||||
* CW_FREEZE_OPERATIONAL_ROLES=1 (optional) — freeze future MINTER/BURNER changes after setup
|
||||
* DEPLOY_CWUSDT=1, DEPLOY_CWUSDC=1, DEPLOY_CWUSDW=1, DEPLOY_CWEURC=1, ... (default all 1; set 0 to skip a token)
|
||||
*/
|
||||
contract DeployCWTokens is Script {
|
||||
uint8 constant DECIMALS = 6;
|
||||
@@ -21,22 +24,27 @@ contract DeployCWTokens is Script {
|
||||
uint256 pk = vm.envUint("PRIVATE_KEY");
|
||||
address deployer = vm.addr(pk);
|
||||
address bridge = vm.envAddress("CW_BRIDGE_ADDRESS");
|
||||
bool strictMode = vm.envOr("CW_STRICT_MODE", uint256(0)) == 1;
|
||||
bool freezeOperationalRoles = vm.envOr("CW_FREEZE_OPERATIONAL_ROLES", uint256(0)) == 1;
|
||||
address governanceAdmin = vm.envOr("CW_GOVERNANCE_ADMIN", address(0));
|
||||
require(bridge != address(0), "CW_BRIDGE_ADDRESS required");
|
||||
|
||||
vm.startBroadcast(pk);
|
||||
|
||||
_deployOne(deployer, "Wrapped cUSDT", "cWUSDT", "DEPLOY_CWUSDT", bridge);
|
||||
_deployOne(deployer, "Wrapped cUSDC", "cWUSDC", "DEPLOY_CWUSDC", bridge);
|
||||
_deployOne(deployer, "Wrapped cEURC", "cWEURC", "DEPLOY_CWEURC", bridge);
|
||||
_deployOne(deployer, "Wrapped cEURT", "cWEURT", "DEPLOY_CWEURT", bridge);
|
||||
_deployOne(deployer, "Wrapped cGBPC", "cWGBPC", "DEPLOY_CWGBPC", bridge);
|
||||
_deployOne(deployer, "Wrapped cGBPT", "cWGBPT", "DEPLOY_CWGBPT", bridge);
|
||||
_deployOne(deployer, "Wrapped cAUDC", "cWAUDC", "DEPLOY_CWAUDC", bridge);
|
||||
_deployOne(deployer, "Wrapped cJPYC", "cWJPYC", "DEPLOY_CWJPYC", bridge);
|
||||
_deployOne(deployer, "Wrapped cCHFC", "cWCHFC", "DEPLOY_CWCHFC", bridge);
|
||||
_deployOne(deployer, "Wrapped cCADC", "cWCADC", "DEPLOY_CWCADC", bridge);
|
||||
_deployOne(deployer, "Wrapped cXAUC", "cWXAUC", "DEPLOY_CWXAUC", bridge);
|
||||
_deployOne(deployer, "Wrapped cXAUT", "cWXAUT", "DEPLOY_CWXAUT", bridge);
|
||||
_deployOne(deployer, "Wrapped cUSDT", "cWUSDT", "DEPLOY_CWUSDT", bridge, strictMode, governanceAdmin, freezeOperationalRoles);
|
||||
_deployOne(deployer, "Wrapped cUSDC", "cWUSDC", "DEPLOY_CWUSDC", bridge, strictMode, governanceAdmin, freezeOperationalRoles);
|
||||
_deployOne(deployer, "Wrapped cAUSDT", "cWAUSDT", "DEPLOY_CWAUSDT", bridge, strictMode, governanceAdmin, freezeOperationalRoles);
|
||||
_deployOne(deployer, "Wrapped cUSDW", "cWUSDW", "DEPLOY_CWUSDW", bridge, strictMode, governanceAdmin, freezeOperationalRoles);
|
||||
_deployOne(deployer, "Wrapped cEURC", "cWEURC", "DEPLOY_CWEURC", bridge, strictMode, governanceAdmin, freezeOperationalRoles);
|
||||
_deployOne(deployer, "Wrapped cEURT", "cWEURT", "DEPLOY_CWEURT", bridge, strictMode, governanceAdmin, freezeOperationalRoles);
|
||||
_deployOne(deployer, "Wrapped cGBPC", "cWGBPC", "DEPLOY_CWGBPC", bridge, strictMode, governanceAdmin, freezeOperationalRoles);
|
||||
_deployOne(deployer, "Wrapped cGBPT", "cWGBPT", "DEPLOY_CWGBPT", bridge, strictMode, governanceAdmin, freezeOperationalRoles);
|
||||
_deployOne(deployer, "Wrapped cAUDC", "cWAUDC", "DEPLOY_CWAUDC", bridge, strictMode, governanceAdmin, freezeOperationalRoles);
|
||||
_deployOne(deployer, "Wrapped cJPYC", "cWJPYC", "DEPLOY_CWJPYC", bridge, strictMode, governanceAdmin, freezeOperationalRoles);
|
||||
_deployOne(deployer, "Wrapped cCHFC", "cWCHFC", "DEPLOY_CWCHFC", bridge, strictMode, governanceAdmin, freezeOperationalRoles);
|
||||
_deployOne(deployer, "Wrapped cCADC", "cWCADC", "DEPLOY_CWCADC", bridge, strictMode, governanceAdmin, freezeOperationalRoles);
|
||||
_deployOne(deployer, "Wrapped cXAUC", "cWXAUC", "DEPLOY_CWXAUC", bridge, strictMode, governanceAdmin, freezeOperationalRoles);
|
||||
_deployOne(deployer, "Wrapped cXAUT", "cWXAUT", "DEPLOY_CWXAUT", bridge, strictMode, governanceAdmin, freezeOperationalRoles);
|
||||
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
@@ -46,12 +54,40 @@ contract DeployCWTokens is Script {
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
string memory envKey,
|
||||
address bridge
|
||||
address bridge,
|
||||
bool strictMode,
|
||||
address governanceAdmin,
|
||||
bool freezeOperationalRoles
|
||||
) internal {
|
||||
if (vm.envOr(envKey, uint256(1)) == 0) return;
|
||||
CompliantWrappedToken t = new CompliantWrappedToken(name, symbol, DECIMALS, admin);
|
||||
t.grantRole(t.MINTER_ROLE(), bridge);
|
||||
t.grantRole(t.BURNER_ROLE(), bridge);
|
||||
|
||||
if (strictMode) {
|
||||
t.revokeRole(t.MINTER_ROLE(), admin);
|
||||
t.revokeRole(t.BURNER_ROLE(), admin);
|
||||
}
|
||||
|
||||
if (governanceAdmin != address(0) && governanceAdmin != admin) {
|
||||
t.grantRole(t.DEFAULT_ADMIN_ROLE(), governanceAdmin);
|
||||
}
|
||||
|
||||
if (freezeOperationalRoles) {
|
||||
t.freezeOperationalRoles();
|
||||
}
|
||||
|
||||
if (strictMode && governanceAdmin != address(0) && governanceAdmin != admin) {
|
||||
t.revokeRole(t.DEFAULT_ADMIN_ROLE(), admin);
|
||||
}
|
||||
|
||||
console.log(symbol, address(t));
|
||||
console.log(" strictMode", strictMode);
|
||||
console.log(" governanceAdmin", governanceAdmin);
|
||||
console.log(" operationalRolesFrozen", t.operationalRolesFrozen());
|
||||
console.log(" deployerHasMinter", t.hasRole(t.MINTER_ROLE(), admin));
|
||||
console.log(" deployerHasBurner", t.hasRole(t.BURNER_ROLE(), admin));
|
||||
console.log(" bridgeHasMinter", t.hasRole(t.MINTER_ROLE(), bridge));
|
||||
console.log(" bridgeHasBurner", t.hasRole(t.BURNER_ROLE(), bridge));
|
||||
}
|
||||
}
|
||||
|
||||
56
script/deploy/DeployCompliantFiatTokensV2ForChain.s.sol
Normal file
56
script/deploy/DeployCompliantFiatTokensV2ForChain.s.sol
Normal file
@@ -0,0 +1,56 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Script, console} from "forge-std/Script.sol";
|
||||
import {CompliantUSDTTokenV2} from "../../contracts/tokens/CompliantUSDTTokenV2.sol";
|
||||
import {CompliantUSDCTokenV2} from "../../contracts/tokens/CompliantUSDCTokenV2.sol";
|
||||
|
||||
/**
|
||||
* @title DeployCompliantFiatTokensV2ForChain
|
||||
* @notice Deploy canonical cUSDT V2 / cUSDC V2 contracts to the current chain.
|
||||
* @dev Defaults to safe pre-cutover posture: new addresses with forwardCanonical disabled unless env overrides it.
|
||||
*
|
||||
* Env:
|
||||
* PRIVATE_KEY (required)
|
||||
* INITIAL_OPERATOR (optional; default deployer)
|
||||
* ADMIN (optional; default deployer)
|
||||
* OWNER (optional alias for ADMIN when ADMIN unset)
|
||||
* INITIAL_SUPPLY (optional; default 1_000_000e6)
|
||||
* FORWARD_CANONICAL=1 to mark deployed V2 as forward canonical immediately
|
||||
* DEPLOY_CUSDT_V2=1 / DEPLOY_CUSDC_V2=1 (default both 1)
|
||||
*/
|
||||
contract DeployCompliantFiatTokensV2ForChain is Script {
|
||||
uint256 internal constant DEFAULT_INITIAL_SUPPLY = 1_000_000 * 10 ** 6;
|
||||
|
||||
function run() external {
|
||||
uint256 pk = vm.envUint("PRIVATE_KEY");
|
||||
address deployer = vm.addr(pk);
|
||||
address initialOperator = vm.envOr("INITIAL_OPERATOR", deployer);
|
||||
address ownerAlias = vm.envOr("OWNER", deployer);
|
||||
address admin = vm.envOr("ADMIN", ownerAlias);
|
||||
uint256 initialSupply = vm.envOr("INITIAL_SUPPLY", DEFAULT_INITIAL_SUPPLY);
|
||||
bool forwardCanonical = vm.envOr("FORWARD_CANONICAL", false);
|
||||
|
||||
vm.startBroadcast(pk);
|
||||
|
||||
if (vm.envOr("DEPLOY_CUSDT_V2", uint256(1)) != 0) {
|
||||
CompliantUSDTTokenV2 cusdtV2 =
|
||||
new CompliantUSDTTokenV2(initialOperator, admin, initialSupply, forwardCanonical);
|
||||
console.log("cUSDT_V2", address(cusdtV2));
|
||||
console.log("cUSDT_V2_admin", admin);
|
||||
console.log("cUSDT_V2_initialOperator", initialOperator);
|
||||
console.log("cUSDT_V2_forwardCanonical", forwardCanonical);
|
||||
}
|
||||
|
||||
if (vm.envOr("DEPLOY_CUSDC_V2", uint256(1)) != 0) {
|
||||
CompliantUSDCTokenV2 cusdcV2 =
|
||||
new CompliantUSDCTokenV2(initialOperator, admin, initialSupply, forwardCanonical);
|
||||
console.log("cUSDC_V2", address(cusdcV2));
|
||||
console.log("cUSDC_V2_admin", admin);
|
||||
console.log("cUSDC_V2_initialOperator", initialOperator);
|
||||
console.log("cUSDC_V2_forwardCanonical", forwardCanonical);
|
||||
}
|
||||
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
}
|
||||
77
script/deploy/DeployCrossChainFlashInfrastructure.s.sol
Normal file
77
script/deploy/DeployCrossChainFlashInfrastructure.s.sol
Normal file
@@ -0,0 +1,77 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Script, console} from "forge-std/Script.sol";
|
||||
import {UniversalCCIPFlashBridgeAdapter} from "../../contracts/flash/UniversalCCIPFlashBridgeAdapter.sol";
|
||||
import {CrossChainFlashRepayReceiver} from "../../contracts/flash/CrossChainFlashRepayReceiver.sol";
|
||||
import {CrossChainFlashVaultCreditReceiver} from "../../contracts/flash/CrossChainFlashVaultCreditReceiver.sol";
|
||||
|
||||
/**
|
||||
* @title DeployCrossChainFlashInfrastructure
|
||||
* @notice Deploys the Chain 138 cross-chain flash adapter plus both CCIP receivers.
|
||||
*
|
||||
* Env:
|
||||
* PRIVATE_KEY required
|
||||
* FLASH_UNIVERSAL_CCIP_BRIDGE optional; fallback UNIVERSAL_CCIP_BRIDGE
|
||||
* FLASH_CCIP_ROUTER optional default router for both receivers
|
||||
* FLASH_REPAY_RECEIVER_ROUTER optional; fallback FLASH_CCIP_ROUTER / CCIP_ROUTER*
|
||||
* FLASH_VAULT_CREDIT_ROUTER optional; fallback FLASH_CCIP_ROUTER / CCIP_ROUTER*
|
||||
* CCIP_ROUTER optional fallback
|
||||
* CCIP_ROUTER_ADDRESS optional fallback
|
||||
* CCIP_ROUTER_CHAIN138 optional fallback
|
||||
*
|
||||
* Usage:
|
||||
* forge script script/deploy/DeployCrossChainFlashInfrastructure.s.sol:DeployCrossChainFlashInfrastructure \
|
||||
* --rpc-url $RPC_URL_138 --broadcast --with-gas-price 1000000000 -vvvv
|
||||
*/
|
||||
contract DeployCrossChainFlashInfrastructure is Script {
|
||||
function run() external {
|
||||
uint256 pk = vm.envUint("PRIVATE_KEY");
|
||||
address deployer = vm.addr(pk);
|
||||
|
||||
address universalBridge = vm.envOr("FLASH_UNIVERSAL_CCIP_BRIDGE", address(0));
|
||||
if (universalBridge == address(0)) {
|
||||
universalBridge = vm.envOr("UNIVERSAL_CCIP_BRIDGE", address(0));
|
||||
}
|
||||
require(universalBridge != address(0), "FLASH_UNIVERSAL_CCIP_BRIDGE or UNIVERSAL_CCIP_BRIDGE not set");
|
||||
|
||||
address router = vm.envOr("FLASH_CCIP_ROUTER", address(0));
|
||||
if (router == address(0)) {
|
||||
router = vm.envOr("CCIP_ROUTER", address(0));
|
||||
}
|
||||
if (router == address(0)) {
|
||||
router = vm.envOr("CCIP_ROUTER_ADDRESS", address(0));
|
||||
}
|
||||
if (router == address(0)) {
|
||||
router = vm.envOr("CCIP_ROUTER_CHAIN138", address(0));
|
||||
}
|
||||
require(router != address(0), "FLASH_CCIP_ROUTER or CCIP_ROUTER* not set");
|
||||
|
||||
address repayReceiverRouter = vm.envOr("FLASH_REPAY_RECEIVER_ROUTER", router);
|
||||
address vaultCreditRouter = vm.envOr("FLASH_VAULT_CREDIT_ROUTER", router);
|
||||
|
||||
console.log("Deployer:", deployer);
|
||||
console.log("UniversalCCIPBridge:", universalBridge);
|
||||
console.log("Repay receiver router:", repayReceiverRouter);
|
||||
console.log("Vault credit receiver router:", vaultCreditRouter);
|
||||
|
||||
vm.startBroadcast(pk);
|
||||
|
||||
UniversalCCIPFlashBridgeAdapter adapter = new UniversalCCIPFlashBridgeAdapter(universalBridge);
|
||||
CrossChainFlashRepayReceiver repayReceiver = new CrossChainFlashRepayReceiver(repayReceiverRouter);
|
||||
CrossChainFlashVaultCreditReceiver vaultCreditReceiver =
|
||||
new CrossChainFlashVaultCreditReceiver(vaultCreditRouter);
|
||||
|
||||
vm.stopBroadcast();
|
||||
|
||||
console.log("UniversalCCIPFlashBridgeAdapter:", address(adapter));
|
||||
console.log("CrossChainFlashRepayReceiver:", address(repayReceiver));
|
||||
console.log("CrossChainFlashVaultCreditReceiver:", address(vaultCreditReceiver));
|
||||
console.log("Export: CROSS_CHAIN_FLASH_BRIDGE_ADAPTER=%s", vm.toString(address(adapter)));
|
||||
console.log("Export: CROSS_CHAIN_FLASH_REPAY_RECEIVER=%s", vm.toString(address(repayReceiver)));
|
||||
console.log(
|
||||
"Export: CROSS_CHAIN_FLASH_VAULT_CREDIT_RECEIVER=%s",
|
||||
vm.toString(address(vaultCreditReceiver))
|
||||
);
|
||||
}
|
||||
}
|
||||
85
script/deploy/DeployGasCanonicalTokens.s.sol
Normal file
85
script/deploy/DeployGasCanonicalTokens.s.sol
Normal file
@@ -0,0 +1,85 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import "forge-std/Script.sol";
|
||||
import {CompliantFiatToken} from "../../contracts/tokens/CompliantFiatToken.sol";
|
||||
|
||||
/**
|
||||
* @title DeployGasCanonicalTokens
|
||||
* @notice Deploy Wave 1 gas-native canonical c* tokens on Chain 138.
|
||||
*
|
||||
* Env:
|
||||
* PRIVATE_KEY (required)
|
||||
* GAS_FAMILY (optional) - deploy one family only: eth_mainnet, eth_l2, bnb, pol, avax, cro, xdai, celo, wemix
|
||||
* GAS_INITIAL_OWNER (optional, defaults to deployer)
|
||||
* GAS_ADMIN (optional, defaults to deployer)
|
||||
* GAS_INITIAL_SUPPLY (optional, defaults to 0)
|
||||
* DEPLOY_GAS_<FAMILY>=0 to skip a family when GAS_FAMILY is unset
|
||||
*/
|
||||
contract DeployGasCanonicalTokens is Script {
|
||||
uint8 internal constant DECIMALS = 18;
|
||||
|
||||
function run() external {
|
||||
uint256 pk = vm.envUint("PRIVATE_KEY");
|
||||
address deployer = vm.addr(pk);
|
||||
address owner = vm.envOr("GAS_INITIAL_OWNER", deployer);
|
||||
address admin = vm.envOr("GAS_ADMIN", deployer);
|
||||
uint256 initialSupply = vm.envOr("GAS_INITIAL_SUPPLY", uint256(0));
|
||||
string memory targetFamily = vm.envOr("GAS_FAMILY", string(""));
|
||||
|
||||
vm.startBroadcast(pk);
|
||||
|
||||
_deployOne(owner, admin, initialSupply, targetFamily, "eth_mainnet", "DEPLOY_GAS_ETH_MAINNET", "Ethereum Mainnet Gas (Compliant)", "cETH", "ETH");
|
||||
_deployOne(owner, admin, initialSupply, targetFamily, "eth_l2", "DEPLOY_GAS_ETH_L2", "Ethereum L2 Gas (Compliant)", "cETHL2", "ETH");
|
||||
_deployOne(owner, admin, initialSupply, targetFamily, "bnb", "DEPLOY_GAS_BNB", "BNB Gas (Compliant)", "cBNB", "BNB");
|
||||
_deployOne(owner, admin, initialSupply, targetFamily, "pol", "DEPLOY_GAS_POL", "Polygon Gas (Compliant)", "cPOL", "POL");
|
||||
_deployOne(owner, admin, initialSupply, targetFamily, "avax", "DEPLOY_GAS_AVAX", "Avalanche Gas (Compliant)", "cAVAX", "AVAX");
|
||||
_deployOne(owner, admin, initialSupply, targetFamily, "cro", "DEPLOY_GAS_CRO", "Cronos Gas (Compliant)", "cCRO", "CRO");
|
||||
_deployOne(owner, admin, initialSupply, targetFamily, "xdai", "DEPLOY_GAS_XDAI", "Gnosis Gas (Compliant)", "cXDAI", "XDAI");
|
||||
_deployOne(owner, admin, initialSupply, targetFamily, "celo", "DEPLOY_GAS_CELO", "Celo Gas (Compliant)", "cCELO", "CELO");
|
||||
_deployOne(owner, admin, initialSupply, targetFamily, "wemix", "DEPLOY_GAS_WEMIX", "Wemix Gas (Compliant)", "cWEMIX", "WEMIX");
|
||||
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
|
||||
function _deployOne(
|
||||
address owner,
|
||||
address admin,
|
||||
uint256 initialSupply,
|
||||
string memory targetFamily,
|
||||
string memory familyKey,
|
||||
string memory envFlag,
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
string memory currencyCode
|
||||
) internal {
|
||||
if (!_shouldDeploy(targetFamily, familyKey, envFlag)) return;
|
||||
|
||||
CompliantFiatToken token = new CompliantFiatToken(
|
||||
name,
|
||||
symbol,
|
||||
DECIMALS,
|
||||
currencyCode,
|
||||
owner,
|
||||
admin,
|
||||
initialSupply
|
||||
);
|
||||
|
||||
console.log(symbol, address(token));
|
||||
console.log(" familyKey", familyKey);
|
||||
console.log(" owner", owner);
|
||||
console.log(" admin", admin);
|
||||
console.log(" initialSupply", initialSupply);
|
||||
}
|
||||
|
||||
function _shouldDeploy(
|
||||
string memory targetFamily,
|
||||
string memory familyKey,
|
||||
string memory envFlag
|
||||
) internal view returns (bool) {
|
||||
if (bytes(targetFamily).length != 0) {
|
||||
return keccak256(bytes(targetFamily)) == keccak256(bytes(familyKey));
|
||||
}
|
||||
return vm.envOr(envFlag, uint256(1)) != 0;
|
||||
}
|
||||
}
|
||||
34
script/deploy/DeployQuotePushFlashWorkflowBorrower.s.sol
Normal file
34
script/deploy/DeployQuotePushFlashWorkflowBorrower.s.sol
Normal file
@@ -0,0 +1,34 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Script, console} from "forge-std/Script.sol";
|
||||
import {QuotePushFlashWorkflowBorrower} from "../../contracts/flash/QuotePushFlashWorkflowBorrower.sol";
|
||||
|
||||
/**
|
||||
* @title DeployQuotePushFlashWorkflowBorrower
|
||||
* @notice Deploy the ERC-3156 quote-push borrower against a trusted flash lender.
|
||||
*
|
||||
* Env:
|
||||
* PRIVATE_KEY required
|
||||
* QUOTE_PUSH_FLASH_LENDER required
|
||||
*
|
||||
* Usage:
|
||||
* forge script script/deploy/DeployQuotePushFlashWorkflowBorrower.s.sol:DeployQuotePushFlashWorkflowBorrower \
|
||||
* --rpc-url <RPC> --broadcast -vvvv
|
||||
*/
|
||||
contract DeployQuotePushFlashWorkflowBorrower is Script {
|
||||
function run() external {
|
||||
uint256 pk = vm.envUint("PRIVATE_KEY");
|
||||
address lender = vm.envAddress("QUOTE_PUSH_FLASH_LENDER");
|
||||
address deployer = vm.addr(pk);
|
||||
|
||||
console.log("Deployer:", deployer);
|
||||
console.log("Trusted lender:", lender);
|
||||
|
||||
vm.startBroadcast(pk);
|
||||
QuotePushFlashWorkflowBorrower borrower = new QuotePushFlashWorkflowBorrower(lender);
|
||||
vm.stopBroadcast();
|
||||
|
||||
console.log("QuotePushFlashWorkflowBorrower:", address(borrower));
|
||||
}
|
||||
}
|
||||
59
script/deploy/DeploySimpleERC3156FlashVault.s.sol
Normal file
59
script/deploy/DeploySimpleERC3156FlashVault.s.sol
Normal file
@@ -0,0 +1,59 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Script, console} from "forge-std/Script.sol";
|
||||
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import {SimpleERC3156FlashVault} from "../../contracts/flash/SimpleERC3156FlashVault.sol";
|
||||
|
||||
/**
|
||||
* @title DeploySimpleERC3156FlashVault
|
||||
* @notice Deploy ERC-3156 flash vault for Chain 138; optional USDT whitelist + seed transfer from deployer.
|
||||
*
|
||||
* Env (broadcast):
|
||||
* PRIVATE_KEY — required
|
||||
* FLASH_VAULT_OWNER — optional; default: deployer
|
||||
* FLASH_VAULT_FEE_BPS — optional; default: 5 (0.05%)
|
||||
* FLASH_VAULT_TOKEN — optional; token to whitelist (default: official USDT Chain 138)
|
||||
* FLASH_VAULT_SEED_AMOUNT — optional; raw token units to transfer from deployer into vault after deploy (0 = skip)
|
||||
*
|
||||
* Usage:
|
||||
* forge script script/deploy/DeploySimpleERC3156FlashVault.s.sol:DeploySimpleERC3156FlashVault \
|
||||
* --rpc-url $RPC_URL_138 --broadcast -vvvv
|
||||
*/
|
||||
contract DeploySimpleERC3156FlashVault is Script {
|
||||
/// @dev Canonical official USDT (Chain 138) per project config / explorer.
|
||||
address internal constant DEFAULT_USDT_138 = 0x004b63A7B5b0E06f6bB6adb4a5F9f590BF3182D1;
|
||||
|
||||
function run() external {
|
||||
uint256 pk = vm.envUint("PRIVATE_KEY");
|
||||
address deployer = vm.addr(pk);
|
||||
address vaultOwner = vm.envOr("FLASH_VAULT_OWNER", deployer);
|
||||
uint256 feeBps = vm.envOr("FLASH_VAULT_FEE_BPS", uint256(5));
|
||||
address token = vm.envOr("FLASH_VAULT_TOKEN", DEFAULT_USDT_138);
|
||||
uint256 seedAmount = vm.envOr("FLASH_VAULT_SEED_AMOUNT", uint256(0));
|
||||
|
||||
console.log("Deployer:", deployer);
|
||||
console.log("Vault owner:", vaultOwner);
|
||||
console.log("feeBps:", feeBps);
|
||||
console.log("Whitelist token:", token);
|
||||
|
||||
vm.startBroadcast(pk);
|
||||
|
||||
SimpleERC3156FlashVault vault = new SimpleERC3156FlashVault(vaultOwner, feeBps);
|
||||
console.log("SimpleERC3156FlashVault:", address(vault));
|
||||
|
||||
if (vaultOwner == deployer) {
|
||||
vault.setTokenSupported(token, true);
|
||||
console.log("setTokenSupported: true");
|
||||
if (seedAmount > 0) {
|
||||
IERC20(token).transfer(address(vault), seedAmount);
|
||||
console.log("Seeded vault (raw units):", seedAmount);
|
||||
console.log("Vault balance:", IERC20(token).balanceOf(address(vault)));
|
||||
}
|
||||
} else {
|
||||
console.log("Owner != deployer: owner must call setTokenSupported + seed separately.");
|
||||
}
|
||||
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
}
|
||||
44
script/deploy/DeploySingleCWToken.s.sol
Normal file
44
script/deploy/DeploySingleCWToken.s.sol
Normal file
@@ -0,0 +1,44 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import "forge-std/Script.sol";
|
||||
import {CompliantWrappedToken} from "../../contracts/tokens/CompliantWrappedToken.sol";
|
||||
|
||||
/**
|
||||
* @title DeploySingleCWToken
|
||||
* @notice Deploy exactly one CompliantWrappedToken and grant MINTER/BURNER to the bridge.
|
||||
*
|
||||
* Env:
|
||||
* PRIVATE_KEY (required)
|
||||
* CW_BRIDGE_ADDRESS (required)
|
||||
* CW_TOKEN_NAME (required)
|
||||
* CW_TOKEN_SYMBOL (required)
|
||||
* CW_TOKEN_DECIMALS (optional, default 6)
|
||||
*/
|
||||
contract DeploySingleCWToken is Script {
|
||||
function run() external {
|
||||
uint256 pk = vm.envUint("PRIVATE_KEY");
|
||||
address admin = vm.addr(pk);
|
||||
address bridge = vm.envAddress("CW_BRIDGE_ADDRESS");
|
||||
string memory tokenName = vm.envString("CW_TOKEN_NAME");
|
||||
string memory tokenSymbol = vm.envString("CW_TOKEN_SYMBOL");
|
||||
uint8 decimals_ = uint8(vm.envOr("CW_TOKEN_DECIMALS", uint256(6)));
|
||||
|
||||
require(bridge != address(0), "CW_BRIDGE_ADDRESS required");
|
||||
require(bytes(tokenName).length != 0, "CW_TOKEN_NAME required");
|
||||
require(bytes(tokenSymbol).length != 0, "CW_TOKEN_SYMBOL required");
|
||||
|
||||
vm.startBroadcast(pk);
|
||||
|
||||
CompliantWrappedToken token = new CompliantWrappedToken(tokenName, tokenSymbol, decimals_, admin);
|
||||
token.grantRole(token.MINTER_ROLE(), bridge);
|
||||
token.grantRole(token.BURNER_ROLE(), bridge);
|
||||
|
||||
vm.stopBroadcast();
|
||||
|
||||
console.log(tokenSymbol, address(token));
|
||||
console.log(" bridge", bridge);
|
||||
console.log(" bridgeHasMinter", token.hasRole(token.MINTER_ROLE(), bridge));
|
||||
console.log(" bridgeHasBurner", token.hasRole(token.BURNER_ROLE(), bridge));
|
||||
}
|
||||
}
|
||||
73
script/deploy/DeployUSDWPublicWrapVault.s.sol
Normal file
73
script/deploy/DeployUSDWPublicWrapVault.s.sol
Normal file
@@ -0,0 +1,73 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Script, console} from "forge-std/Script.sol";
|
||||
import {CompliantWrappedToken} from "../../contracts/tokens/CompliantWrappedToken.sol";
|
||||
import {USDWPublicWrapVault} from "../../contracts/bridge/integration/USDWPublicWrapVault.sol";
|
||||
|
||||
/**
|
||||
* @title DeployUSDWPublicWrapVault
|
||||
* @notice Deploy the native USDW <-> cWUSDW wrap vault for a public chain.
|
||||
* @dev Use with an existing cWUSDW deployment on BSC or a newly deployed cWUSDW on Polygon.
|
||||
*
|
||||
* Env:
|
||||
* PRIVATE_KEY (required)
|
||||
* USDW_NATIVE_ADDRESS (required) // e.g. dwinUsdWinPublic.chains.56.usdwCurrent
|
||||
* CWUSDW_ADDRESS (required) // cWUSDW contract on the current public chain
|
||||
* USDW_WRAP_ADMIN (optional) // additional admin to grant after deployment
|
||||
* USDW_WRAP_OPERATOR (optional) // reserve seeding operator; default admin/deployer
|
||||
* USDW_WRAP_EMERGENCY_ADMIN (optional)
|
||||
* USDW_WRAP_GRANT_TOKEN_ROLES=1 // grant MINTER_ROLE and BURNER_ROLE on cWUSDW to the vault
|
||||
* USDW_WRAP_STRICT_ADMIN=1 // revoke deployer DEFAULT_ADMIN_ROLE after additional grants
|
||||
*/
|
||||
contract DeployUSDWPublicWrapVault is Script {
|
||||
function run() external {
|
||||
uint256 pk = vm.envUint("PRIVATE_KEY");
|
||||
address deployer = vm.addr(pk);
|
||||
address nativeUsdw = vm.envAddress("USDW_NATIVE_ADDRESS");
|
||||
address wrappedUsdw = vm.envAddress("CWUSDW_ADDRESS");
|
||||
address admin = vm.envOr("USDW_WRAP_ADMIN", deployer);
|
||||
address reserveOperator = vm.envOr("USDW_WRAP_OPERATOR", admin);
|
||||
address emergencyAdmin = vm.envOr("USDW_WRAP_EMERGENCY_ADMIN", admin);
|
||||
bool grantTokenRoles = vm.envOr("USDW_WRAP_GRANT_TOKEN_ROLES", uint256(0)) == 1;
|
||||
bool strictAdmin = vm.envOr("USDW_WRAP_STRICT_ADMIN", uint256(0)) == 1;
|
||||
|
||||
vm.startBroadcast(pk);
|
||||
|
||||
USDWPublicWrapVault vault = new USDWPublicWrapVault(deployer, nativeUsdw, wrappedUsdw);
|
||||
|
||||
if (admin != deployer) {
|
||||
vault.grantRole(vault.DEFAULT_ADMIN_ROLE(), admin);
|
||||
vault.grantRole(vault.RESERVE_OPERATOR_ROLE(), admin);
|
||||
vault.grantRole(vault.EMERGENCY_ADMIN_ROLE(), admin);
|
||||
}
|
||||
if (reserveOperator != admin && reserveOperator != deployer) {
|
||||
vault.grantRole(vault.RESERVE_OPERATOR_ROLE(), reserveOperator);
|
||||
}
|
||||
if (emergencyAdmin != admin && emergencyAdmin != deployer) {
|
||||
vault.grantRole(vault.EMERGENCY_ADMIN_ROLE(), emergencyAdmin);
|
||||
}
|
||||
|
||||
if (grantTokenRoles) {
|
||||
CompliantWrappedToken token = CompliantWrappedToken(wrappedUsdw);
|
||||
token.grantRole(token.MINTER_ROLE(), address(vault));
|
||||
token.grantRole(token.BURNER_ROLE(), address(vault));
|
||||
}
|
||||
|
||||
if (strictAdmin && admin != deployer) {
|
||||
vault.revokeRole(vault.DEFAULT_ADMIN_ROLE(), deployer);
|
||||
}
|
||||
|
||||
console.log("USDWPublicWrapVault", address(vault));
|
||||
console.log(" nativeUsdw", nativeUsdw);
|
||||
console.log(" wrappedUsdw", wrappedUsdw);
|
||||
console.log(" deployer", deployer);
|
||||
console.log(" admin", admin);
|
||||
console.log(" reserveOperator", reserveOperator);
|
||||
console.log(" emergencyAdmin", emergencyAdmin);
|
||||
console.log(" grantTokenRoles", grantTokenRoles);
|
||||
console.log(" strictAdmin", strictAdmin);
|
||||
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ contract RegisterGRUCompliantTokens is Script {
|
||||
|
||||
_register(registry, vm.envOr("CUSDT_ADDRESS_138", address(0)), "Tether USD (Compliant)", "cUSDT");
|
||||
_register(registry, vm.envOr("CUSDC_ADDRESS_138", address(0)), "USD Coin (Compliant)", "cUSDC");
|
||||
_register(registry, vm.envOr("CAUSDT_ADDRESS_138", address(0)), "Alltra USD Token (Compliant)", "cAUSDT");
|
||||
_register(registry, vm.envOr("CEURC_ADDRESS_138", address(0)), "Euro Coin (Compliant)", "cEURC");
|
||||
_register(registry, vm.envOr("CEURT_ADDRESS_138", address(0)), "Tether EUR (Compliant)", "cEURT");
|
||||
_register(registry, vm.envOr("CGBPC_ADDRESS_138", address(0)), "Pound Sterling (Compliant)", "cGBPC");
|
||||
|
||||
50
script/deploy/RegisterGRUCompliantTokensV2.s.sol
Normal file
50
script/deploy/RegisterGRUCompliantTokensV2.s.sol
Normal file
@@ -0,0 +1,50 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import "forge-std/Script.sol";
|
||||
import {UniversalAssetRegistry} from "../../contracts/registry/UniversalAssetRegistry.sol";
|
||||
|
||||
/**
|
||||
* @title RegisterGRUCompliantTokensV2
|
||||
* @notice Stage deployed c* V2 contracts in UniversalAssetRegistry using version-aware symbols.
|
||||
* @dev Keeps live V1 symbols untouched while allowing indexers/operators to discover V2 addresses.
|
||||
* Env: UNIVERSAL_ASSET_REGISTRY; optional CUSDT_V2_ADDRESS_138, CUSDC_V2_ADDRESS_138.
|
||||
*/
|
||||
contract RegisterGRUCompliantTokensV2 is Script {
|
||||
function run() external {
|
||||
address registryAddr = vm.envAddress("UNIVERSAL_ASSET_REGISTRY");
|
||||
UniversalAssetRegistry registry = UniversalAssetRegistry(registryAddr);
|
||||
uint256 pk = vm.envUint("PRIVATE_KEY");
|
||||
vm.startBroadcast(pk);
|
||||
|
||||
_register(
|
||||
registry,
|
||||
vm.envOr("CUSDT_V2_ADDRESS_138", address(0)),
|
||||
"Tether USD (Compliant V2)",
|
||||
"cUSDT.v2"
|
||||
);
|
||||
_register(
|
||||
registry,
|
||||
vm.envOr("CUSDC_V2_ADDRESS_138", address(0)),
|
||||
"USD Coin (Compliant V2)",
|
||||
"cUSDC.v2"
|
||||
);
|
||||
|
||||
vm.stopBroadcast();
|
||||
}
|
||||
|
||||
function _register(
|
||||
UniversalAssetRegistry registry,
|
||||
address tokenAddr,
|
||||
string memory name,
|
||||
string memory symbol
|
||||
) internal {
|
||||
if (tokenAddr == address(0)) return;
|
||||
if (registry.isAssetActive(tokenAddr)) {
|
||||
console.log("Skip (already registered):", symbol, vm.toString(tokenAddr));
|
||||
return;
|
||||
}
|
||||
registry.registerGRUCompliantAsset(tokenAddr, name, symbol, 6, "International");
|
||||
console.log("Registered GRU V2:", symbol, vm.toString(tokenAddr));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user