gcx/blockchain/genex-contracts/script/Deploy.s.sol

242 lines
9.3 KiB
Solidity
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "forge-std/Script.sol";
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
import "../src/Coupon.sol";
import "../src/CouponFactory.sol";
import "../src/Settlement.sol";
import "../src/Redemption.sol";
import "../src/Compliance.sol";
import "../src/Treasury.sol";
import "../src/Governance.sol";
import "../src/ExchangeRateOracle.sol";
import "../src/CouponBackedSecurity.sol";
import "../src/CouponBatch.sol";
import "../src/Redemption1155.sol";
/// @title Deploy — Genex 合约系统完整部署脚本
/// @notice 部署所有合约Transparent Proxy 模式) + 角色授权 + 初始化
contract Deploy is Script {
// 部署后的合约地址
ProxyAdmin public proxyAdmin;
address public coupon;
address public couponFactory;
address public settlement;
address public redemption;
address public compliance;
address public treasury;
address public governance;
address public oracle;
address public cbs;
address public couponBatch;
address public redemption1155;
function run() external {
uint256 deployerKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
address deployer = vm.addr(deployerKey);
address usdc = vm.envAddress("USDC_ADDRESS");
address platformFeeCollector = vm.envOr("FEE_COLLECTOR", deployer);
// 多签成员地址
address[] memory multisigMembers = new address[](5);
multisigMembers[0] = vm.envOr("MULTISIG_1", deployer);
multisigMembers[1] = vm.envOr("MULTISIG_2", deployer);
multisigMembers[2] = vm.envOr("MULTISIG_3", deployer);
multisigMembers[3] = vm.envOr("MULTISIG_4", deployer);
multisigMembers[4] = vm.envOr("MULTISIG_5", deployer);
vm.startBroadcast(deployerKey);
// ==========================================
// 1. 部署 ProxyAdmin
// ==========================================
proxyAdmin = new ProxyAdmin();
console.log("ProxyAdmin:", address(proxyAdmin));
// ==========================================
// 2. 部署 Compliance最先其他合约依赖它
// ==========================================
Compliance complianceImpl = new Compliance();
compliance = _deployProxy(
address(complianceImpl),
abi.encodeCall(Compliance.initialize, (deployer))
);
console.log("Compliance:", compliance);
// ==========================================
// 3. 部署 Coupon
// ==========================================
Coupon couponImpl = new Coupon();
coupon = _deployProxy(
address(couponImpl),
abi.encodeCall(Coupon.initialize, ("Genex Coupon", "GXC", deployer))
);
console.log("Coupon:", coupon);
// ==========================================
// 4. 部署 CouponFactory
// ==========================================
CouponFactory factoryImpl = new CouponFactory();
couponFactory = _deployProxy(
address(factoryImpl),
abi.encodeCall(CouponFactory.initialize, (coupon, compliance, deployer))
);
console.log("CouponFactory:", couponFactory);
// ==========================================
// 5. 部署 Settlement
// ==========================================
Settlement settlementImpl = new Settlement();
settlement = _deployProxy(
address(settlementImpl),
abi.encodeCall(Settlement.initialize, (coupon, compliance, usdc, deployer))
);
console.log("Settlement:", settlement);
// ==========================================
// 6. 部署 Redemption
// ==========================================
Redemption redemptionImpl = new Redemption();
redemption = _deployProxy(
address(redemptionImpl),
abi.encodeCall(Redemption.initialize, (coupon, compliance, deployer))
);
console.log("Redemption:", redemption);
// ==========================================
// 7. 部署 Treasury
// ==========================================
Treasury treasuryImpl = new Treasury();
treasury = _deployProxy(
address(treasuryImpl),
abi.encodeCall(Treasury.initialize, (usdc, platformFeeCollector, deployer))
);
console.log("Treasury:", treasury);
// ==========================================
// 8. 部署 Governance
// ==========================================
Governance governanceImpl = new Governance();
governance = _deployProxy(
address(governanceImpl),
abi.encodeCall(Governance.initialize, (multisigMembers, deployer))
);
console.log("Governance:", governance);
// ==========================================
// 9. 部署 ExchangeRateOracle
// ==========================================
ExchangeRateOracle oracleImpl = new ExchangeRateOracle();
oracle = _deployProxy(
address(oracleImpl),
abi.encodeCall(ExchangeRateOracle.initialize, (900, deployer))
);
console.log("ExchangeRateOracle:", oracle);
// ==========================================
// 10. 部署 CouponBatch (ERC-1155)
// ==========================================
CouponBatch couponBatchImpl = new CouponBatch();
couponBatch = _deployProxy(
address(couponBatchImpl),
abi.encodeCall(CouponBatch.initialize, ("https://genex.io/api/coupon-batch/{id}.json", deployer))
);
console.log("CouponBatch:", couponBatch);
// ==========================================
// 11. 部署 Redemption1155
// ==========================================
Redemption1155 redemption1155Impl = new Redemption1155();
redemption1155 = _deployProxy(
address(redemption1155Impl),
abi.encodeCall(Redemption1155.initialize, (couponBatch, compliance, deployer))
);
console.log("Redemption1155:", redemption1155);
// ==========================================
// 12. 部署 CouponBackedSecurity
// ==========================================
CouponBackedSecurity cbsImpl = new CouponBackedSecurity();
cbs = _deployProxy(
address(cbsImpl),
abi.encodeCall(CouponBackedSecurity.initialize, (coupon, compliance, usdc, deployer))
);
console.log("CouponBackedSecurity:", cbs);
// ==========================================
// 13. CouponFactory 关联 CouponBatch
// ==========================================
CouponFactory(couponFactory).setCouponBatchContract(couponBatch);
// ==========================================
// 14. 角色授权
// ==========================================
_grantRoles(deployer);
vm.stopBroadcast();
// 输出部署摘要
console.log("\n========== Deployment Summary ==========");
console.log("ProxyAdmin: ", address(proxyAdmin));
console.log("Compliance: ", compliance);
console.log("Coupon: ", coupon);
console.log("CouponFactory: ", couponFactory);
console.log("Settlement: ", settlement);
console.log("Redemption: ", redemption);
console.log("Treasury: ", treasury);
console.log("Governance: ", governance);
console.log("ExchangeRateOracle: ", oracle);
console.log("CouponBatch: ", couponBatch);
console.log("Redemption1155: ", redemption1155);
console.log("CouponBackedSecurity:", cbs);
console.log("=========================================");
}
/// @dev 部署 Transparent Proxy
function _deployProxy(address implementation, bytes memory initData) internal returns (address) {
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
implementation,
address(proxyAdmin),
initData
);
return address(proxy);
}
/// @dev 授予各合约之间的角色
function _grantRoles(address deployer) internal {
// CouponFactory 需要 Coupon 的 FACTORY_ROLE
Coupon(coupon).grantRole(
keccak256("FACTORY_ROLE"),
couponFactory
);
// Settlement 需要 Coupon 的 SETTLER_ROLE
Coupon(coupon).grantRole(
keccak256("SETTLER_ROLE"),
settlement
);
// Redemption 需要通过 Coupon.burn 权限owner 或 approved
// — Redemption 合约中 burn 通过 ownerOf 检查,无需额外角色
// CouponFactory 需要 CouponBatch 的 FACTORY_ROLE
CouponBatch(couponBatch).grantRole(
keccak256("FACTORY_ROLE"),
couponFactory
);
// Redemption1155 需要 CouponBatch 的 BURNER_ROLE
CouponBatch(couponBatch).grantRole(
keccak256("BURNER_ROLE"),
redemption1155
);
// Governance 的 MULTISIG_ROLE 在 initialize 中已设置
console.log("Roles granted successfully");
}
}