Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions script/res/known-cyber-corps-v3-dev.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
{
"data": [
{
"chainId": 84532,
"address": "0x738B533fB2a4183b69E38c14E359a2FcaB5Fbc87"
},
{
"chainId": 84532,
"address": "0x6e71076A1396E468490ed5E0F427b895E8F01E09"
},
{
"chainId": 84532,
"address": "0x274c7B5edc5f088D880839a0d1287e5DA7Df3504"
},
{
"chainId": 84532,
"address": "0x08D471C689e8aaB6dF2ea6860daa039C036810c2"
},
{
"chainId": 84532,
"address": "0x1f1592BEAa33AF86C34cA6AB42b03E812e331e2D"
},
{
"chainId": 84532,
"address": "0x62F767A4538dFF18c43EAAeA84ec721B7f289a1d"
},
{
"chainId": 84532,
"address": "0xa2611914370b8ff3973573833C1cAe2D4bc754e6"
},
{
"chainId": 84532,
"address": "0xFC870033B8DD920aE0227F2dbBE984EFE62F850C"
},
{
"chainId": 84532,
"address": "0x3Aa81226f2E952fEdf6055c8c909F620b89B68aF"
},
{
"chainId": 84532,
"address": "0xc2Bb4af9b2d65Ec277F813FCF0b17cbc5bD9DDa1"
},
{
"chainId": 84532,
"address": "0x170a7b6225992a3605C6DcB5E0E46396f4E4E3B6"
},
{
"chainId": 84532,
"address": "0x085073B6e8cbDAE2E24668FCfE212bBD56Cc2dB3"
},
{
"chainId": 84532,
"address": "0x0423Aa59402624D6f17685DF388B682be515A978"
},
{
"chainId": 84532,
"address": "0x9C33033f1D7E7316c936aBb30A368F93c1D02CCf"
},
{
"chainId": 84532,
"address": "0x8412329B3CB87D125Adfc14904DAE896424b8d01"
},
{
"chainId": 84532,
"address": "0x71E5249396811547d9C654A29153eF3Cc0AA045d"
},
{
"chainId": 84532,
"address": "0xB49c65A5626f266a735cb319Af4b623D5A8dAC5e"
},
{
"chainId": 84532,
"address": "0xD2cD7416F07381203b4e5096667E7483cb371A37"
},
{
"chainId": 84532,
"address": "0x3231DF81Db0F50680067b627C4335509A3D74613"
},
{
"chainId": 84532,
"address": "0xD8e877608a71A1d79181178d84C76989D7ea1DfB"
},
{
"chainId": 84532,
"address": "0x074fb622a4A2CCB6dB81b2871Bd49f379b6E20c8"
},
{
"chainId": 84532,
"address": "0x89812667009AA0B51b19a4Ed0228b0920d8F5d91"
},
{
"chainId": 84532,
"address": "0x04812316D6a64B32d5DdEe21F8E12d2a87bbF32A"
}
]
}
258 changes: 258 additions & 0 deletions script/upgrade-and-migrate-base-sep-im-rm-factory-addrs.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.18;

import {Script} from "forge-std/Script.sol";
import {Test, console2} from "forge-std/Test.sol";
import {CyberCorpFactory} from "../src/CyberCorpFactory.sol";
import {CyberCertPrinter} from "../src/CyberCertPrinter.sol";
import {IIssuanceManager} from "../src/interfaces/IIssuanceManager.sol";
import {CyberCorpSingleFactory} from "../src/CyberCorpSingleFactory.sol";
import {BorgAuth} from "../src/libs/auth.sol";
import {CyberAgreementRegistry} from "../src/CyberAgreementRegistry.sol";
import {CyberCorpSingleFactory} from "../src/CyberCorpSingleFactory.sol";
import {IDealManager} from "../src/interfaces/IDealManager.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {CertificateDetails} from "../src/storage/CyberCertPrinterStorage.sol";
import "../src/CyberCorpConstants.sol";
import {CertificateUriBuilder} from "../src/CertificateUriBuilder.sol";
import {SAFTExtension} from "../src/storage/extensions/SAFTExtension.sol";
import {DealManagerStorage} from "../src/storage/DealManagerStorage.sol";
import {CyberCorp} from "../src/CyberCorp.sol";
import {ILegacyFactory} from "./interfaces/ILegacyFactory.sol";
import {KnownAddressesLoader} from "./libs/KnownAddressesLoader.sol";
import {IssuanceManagerFactory} from "../src/IssuanceManagerFactory.sol";
import {IssuanceManagerWithFactoryMigration} from "../src/IssuanceManagerWithFactoryMigration.sol";
import {DealManagerFactory} from "../src/DealManagerFactory.sol";
import {DealManager} from "../src/DealManager.sol";
import {RoundManagerFactory} from "../src/RoundManagerFactory.sol";
import {RoundManagerWithFactoryMigration} from "../src/RoundManagerWithFactoryMigration.sol";

contract UpgradeAndMigrateBaseSepImRmFactoryAddrsScript is Script {
mapping(address => uint256) private corpOwnerPrivateKeyLookup;

function run() public {
runWithArgs(
vm.envUint("PRIVATE_KEY_MAIN"), // deployerPrivateKey
vm.envUint("CORP_OWNER_PKS", ","), // corpOwnerPrivateKeys
type(uint256).max // maxCount
);
}

/// @dev Input argument is not private key because tests will prank the deployer for real-world simulation
function runWithArgs(
uint256 deployerPrivateKey,
uint256[] memory corpOwnerPrivateKeys,
uint256 maxCount
) public {
address deployer = vm.addr(deployerPrivateKey);
string memory saltStr = "MetaLexCyberCorp.PublicRounds.UpgradeV3.0.1";
bytes32 salt = bytes32(keccak256(bytes(saltStr)));

// Compile a lookup table of corp owners (for accepting upgrades)
for (uint256 i = 0; i < corpOwnerPrivateKeys.length; i++) {
address corpOwner = vm.addr(corpOwnerPrivateKeys[i]);
corpOwnerPrivateKeyLookup[corpOwner] = corpOwnerPrivateKeys[i];
}

console2.log("deployer: %s", deployer);
console2.log("salt string: %s", saltStr);
console2.log("loaded corp owners: %d", corpOwnerPrivateKeys.length);

CyberCorpFactory cyberCorpFactory = CyberCorpFactory(0x51413048f3Dfc4516e95BC8e249341B1D53B6cB2);
CyberCorpSingleFactory cyberCorpSingleFactory = CyberCorpSingleFactory(cyberCorpFactory.cyberCorpSingleFactory());
DealManagerFactory dmFactory = DealManagerFactory(cyberCorpFactory.dealManagerFactory());

// Legacy corp's IssuanceManagerFactory (for upgrading beacons)
ILegacyFactory legacyImFactory = ILegacyFactory(0xA32547aAdAA4975082D729c79e79dBaE4385EBCf);

// Deprecated develop-version of v3 RoundManagerFactory (we need it later for providing reference implementation with migration features)
IssuanceManagerFactory deprecatingImFactory = IssuanceManagerFactory(0xbbD386D237f3b407E6511A52488850b1Da0cCad2);
RoundManagerFactory deprecatingRmFactory = RoundManagerFactory(0x9E2A3a07711Ce4b5A2F4D62a5c8f8B5307Af9C34);

// Newly deployed factories that we want to use
IssuanceManagerFactory imFactory = IssuanceManagerFactory(0xD353972D7955F421d94d0eA8c42c88c417F7155A);
RoundManagerFactory rmFactory = RoundManagerFactory(0xc9d5d0DeDD124f9351E5880469f25AB41869aeb9);

vm.startBroadcast(deployerPrivateKey);

// 1) Replace CyberCorpFactory's IssuanceManagerFactory with the newly deployed ones
// Set new IssuanceManager's reference implementation to the old one since they are functionally identical
address refIm = deprecatingImFactory.getRefImplementation();
imFactory.setRefImplementation(refIm);
cyberCorpFactory.setIssuanceManagerFactory(address(imFactory));
vm.assertEq(cyberCorpFactory.issuanceManagerFactory(), address(imFactory), "unexpected IssuanceManagerFactory");
vm.assertEq(imFactory.getRefImplementation(), refIm, "unexpected IssuanceManager reference implementation");
console2.log("CyberCorpFactory.issuanceManagerFactory set to: %s", address(imFactory));

// 2) Replace CyberCorpFactory's RoundManagerFactory with the newly deployed ones
cyberCorpFactory.setRoundManagerFactory(address(rmFactory));
vm.assertEq(cyberCorpFactory.roundManagerFactory(), address(rmFactory), "unexpected RoundManagerFactory");
console2.log("CyberCorpFactory.roundManagerFactory set to: %s", address(rmFactory));

// Load all known cyber corps
address[] memory knownLegacyCyberCorps = KnownAddressesLoader.load(block.chainid, "/script/res/known-cyber-corps.json", maxCount);
address[] memory knownDevV3CyberCorps = KnownAddressesLoader.load(block.chainid, "/script/res/known-cyber-corps-v3-dev.json", maxCount);

// 3) Deploy temporary contracts for migration

IssuanceManagerWithFactoryMigration imWithMigrationImpl = new IssuanceManagerWithFactoryMigration();
RoundManagerWithFactoryMigration rmWithMigrationImpl = new RoundManagerWithFactoryMigration();

// Sanity check: the hard-coded factory addresses should match the current factories
vm.assertEq(
imWithMigrationImpl.NEW_UPGRADE_FACTORY(),
address(imFactory),
string(abi.encodePacked("IssuanceManagerWithFactoryMigration.NEW_UPGRADE_FACTORY should point to the current factory"))
);
vm.assertEq(
rmWithMigrationImpl.NEW_UPGRADE_FACTORY(),
address(rmFactory),
string(abi.encodePacked("RoundManagerWithFactoryMigration.NEW_UPGRADE_FACTORY should point to the current factory"))
);

// 4a) Upgrade issuance manager beacon to a special implementation with migration features
legacyImFactory.upgradeImplementation(address(imWithMigrationImpl));
vm.assertEq(legacyImFactory.getBeaconImplementation(), address(imWithMigrationImpl), "beacon implementation should be upgraded with migration features by now");
console2.log("Set new beacon implementation (with migration features): %s for legacy IssuanceManagerFactory: %s", address(imWithMigrationImpl), address(legacyImFactory));

// 4b) Set the reference implementation on the deprecating IssuanceManagerFactory (so the dev-v3 corps can accept it)
deprecatingImFactory.setRefImplementation(address(imWithMigrationImpl));

// 4c) Set the reference implementation on the deprecating RoundManagerFactory (so the corps can accept it)
deprecatingRmFactory.setRefImplementation(address(rmWithMigrationImpl));

vm.stopBroadcast();

// 5) Migrate each legacy corp one-by-one
for (uint256 i = 0; i < knownLegacyCyberCorps.length; i++) {
CyberCorp corp = CyberCorp(knownLegacyCyberCorps[i]);

// If we don't have the corp owner's private key, we will skip migrating the corp completely so it does not stuck in an intermediate state
uint256 corpOwnerPrivateKey = corpOwnerPrivateKeyLookup[corp.companyPayable()];
if (corpOwnerPrivateKey == 0) {
console2.log("private key not found for legacy corp owner: %s, skipping corp: %s", corp.companyPayable(), address(corp));
continue;
}

// Sanity check: all other factories should match
vm.assertEq(
corp.upgradeFactory(),
address(cyberCorpSingleFactory),
string(abi.encodePacked("legacy cyberCorp: ", vm.toString(address(corp)), " should point to the current CyberCorpSingleFactory"))
);
vm.assertEq(
_getDealManagerUpgradeFactory(corp.dealManager()),
address(dmFactory),
string(abi.encodePacked("legacy cyberCorp: ", vm.toString(address(corp)), " should point to the current DealManagerFactory"))
);

// Migrate legacy corp's IssuanceManager (beacon-based)
vm.startBroadcast(deployerPrivateKey);

IssuanceManagerWithFactoryMigration im = IssuanceManagerWithFactoryMigration(corp.issuanceManager());
im.migrateUpgradeFactory();
vm.assertEq(
im.getUpgradeFactory(),
address(imFactory),
string(abi.encodePacked("legacy cyberCorp: ", vm.toString(address(corp)), " should point to the current IssuanceManagerFactory after migration"))
);

vm.stopBroadcast();

// Migrate legacy corp's RoundManager (UUPSUpgradeable-based, need co-approval)
vm.startBroadcast(corpOwnerPrivateKey);

// Accept round manager upgrade to the temporary implementation with migration feature
RoundManagerWithFactoryMigration rm = RoundManagerWithFactoryMigration(corp.roundManager());
rm.upgradeToAndCall(
address(rmWithMigrationImpl),
abi.encodeWithSelector(rm.migrateUpgradeFactory.selector) // perform migration atomically
);
vm.assertEq(
rm.getUpgradeFactory(),
address(rmFactory),
string(abi.encodePacked("legacy cyberCorp: ", vm.toString(address(corp)), " should point to the current RoundManagerFactory after migration"))
);

vm.stopBroadcast();

console2.log("Migrated legacy CyberCorp: %s", address(corp));
}

// 6) Migrate each dev-v3 corp one-by-one
for (uint256 i = 0; i < knownDevV3CyberCorps.length; i++) {
CyberCorp corp = CyberCorp(knownDevV3CyberCorps[i]);

// If we don't have the corp owner's private key, we will skip migrating the corp completely so it does not stuck in an intermediate state
uint256 corpOwnerPrivateKey = corpOwnerPrivateKeyLookup[corp.companyPayable()];
if (corpOwnerPrivateKey == 0) {
console2.log("private key not found for dev-v3 corp owner: %s, skipping corp: %s", corp.companyPayable(), address(corp));
continue;
}

// Sanity check: all other factories should match
vm.assertEq(
corp.upgradeFactory(),
address(cyberCorpSingleFactory),
string(abi.encodePacked("legacy cyberCorp: ", vm.toString(address(corp)), " should point to the current CyberCorpSingleFactory"))
);
vm.assertEq(
_getDealManagerUpgradeFactory(corp.dealManager()),
address(dmFactory),
string(abi.encodePacked("legacy cyberCorp: ", vm.toString(address(corp)), " should point to the current DealManagerFactory"))
);

vm.startBroadcast(corpOwnerPrivateKey);

// Migrate legacy corp's IssuanceManager (UUPSUpgradeable-based, need co-approval)
// Accept round manager upgrade to the temporary implementation with migration feature
IssuanceManagerWithFactoryMigration im = IssuanceManagerWithFactoryMigration(corp.issuanceManager());
im.upgradeToAndCall(
address(imWithMigrationImpl),
abi.encodeWithSelector(im.migrateUpgradeFactory.selector) // perform migration atomically
);
vm.assertEq(
im.getUpgradeFactory(),
address(imFactory),
string(abi.encodePacked("legacy cyberCorp: ", vm.toString(address(corp)), " should point to the current IssuanceManagerFactory after migration"))
);

// Migrate legacy corp's RoundManager (UUPSUpgradeable-based, need co-approval)
// Accept round manager upgrade to the temporary implementation with migration feature
RoundManagerWithFactoryMigration rm = RoundManagerWithFactoryMigration(corp.roundManager());
rm.upgradeToAndCall(
address(rmWithMigrationImpl),
abi.encodeWithSelector(rm.migrateUpgradeFactory.selector) // perform migration atomically
);
vm.assertEq(
rm.getUpgradeFactory(),
address(rmFactory),
string(abi.encodePacked("legacy cyberCorp: ", vm.toString(address(corp)), " should point to the current RoundManagerFactory after migration"))
);

vm.stopBroadcast();

console2.log("Migrated dev-v3 CyberCorp: %s", address(corp));
}

// 7a) Revert to the normal implementation since migration is done
vm.startBroadcast(deployerPrivateKey);

address imRefImpl = imFactory.getRefImplementation();
legacyImFactory.upgradeImplementation(imRefImpl);
vm.assertEq(legacyImFactory.getBeaconImplementation(), imRefImpl, "beacon implementation should be upgraded without migration features by now");
console2.log("Set new beacon implementation (without migration features): %s for legacy IssuanceManagerFactory: %s", address(imRefImpl), address(legacyImFactory));

// 7b) No need to revert deprecatingImFactory.refImplementation() since it is deprecating
// 7c) No need to revert deprecatingRmFactory.refImplementation() since it is deprecating

vm.stopBroadcast();
}

function _getDealManagerUpgradeFactory(address target) internal view returns (address) {
// `upgradeFactory` is at slot 1 of `DealManagerStorage.STORAGE_POSITION`
bytes32 slotData = vm.load(target, bytes32(uint256(DealManagerStorage.STORAGE_POSITION) + 1));
return address(uint160(uint256(slotData)));
}
}
Loading
Loading