Skip to content
Draft
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
9 changes: 5 additions & 4 deletions deployment.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ staking-rewards-impl-prev = "0x2d57bc44e3c1fe4ceec8f2bf9ea0ac954b527e43"
staking-rewards-deployer = "0xb13573c6ceb505a7bdd4fa3ad7b473c5c5d36b19"
povw-minter = "0xbfce7c2d5e7eddeab71b3eeed770713c8b755397"
staking-minter = "0x459d87d54808fac136ddcf439fcc1d8a238311c7"
circulating-zkc = "0x15eB8cA378E33381c867573EF2f25Ca1010f866d"
circulating-zkc-impl = "0xB0615B524a560b307C8fc486928B989a8b1234DA"
circulating-zkc-admin = "0xb13573c6ceb505a7bdd4fa3ad7b473c5c5d36b19"
circulating-zkc-commit = "9d0b6a9b541d3b6980893b3385d33d12b173f232"
supply-calculator = "0x15eB8cA378E33381c867573EF2f25Ca1010f866d"
supply-calculator-impl = "0x1ff6f81ea7f5e6feafaafb0fc5983576096ded1d"
supply-calculator-admin = "0xb13573c6ceb505a7bdd4fa3ad7b473c5c5d36b19"
supply-calculator-commit = "537c077"
zkc-commit = "5b8310b"
vezkc-commit = "caa29df"
staking-rewards-commit = "24e6b5a"
supply-calculator-admin-2 = "0xb04d1a222789a76e74168a919b43b20f66e24f0b"

[deployment.ethereum-sepolia]
name = "Ethereum Sepolia"
Expand Down
17 changes: 17 additions & 0 deletions foundry.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"lib/forge-std": {
"rev": "77041d2ce690e692d6e03cc812b57d1ddaa4d505"
},
"lib/openzeppelin-contracts": {
"rev": "9393147db73ae6261b67cb03003370e9a7fa2448"
},
"lib/openzeppelin-contracts-upgradeable": {
"rev": "a2c43a5aed2ac0153340c93ed452915b650d1921"
},
"lib/openzeppelin-foundry-upgrades": {
"rev": "cfd861bc18ef4737e82eae6ec75304e27af699ef"
},
"lib/prb-math": {
"rev": "dae52a48422f7464e7eeb4eea824f44dde7dfabe"
}
}
8 changes: 4 additions & 4 deletions script/BaseDeployment.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,10 @@ abstract contract BaseDeployment is Script {
}

/**
* @notice Updates the CirculatingZKC contract commit hash in deployment.toml via FFI
* @notice Updates the SupplyCalculator contract commit hash in deployment.toml via FFI
* @param deploymentKey The chain key (e.g., "anvil", "ethereum-mainnet")
*/
function _updateCirculatingZKCCommit(string memory deploymentKey) internal {
function _updateSupplyCalculatorCommit(string memory deploymentKey) internal {
string[] memory args = new string[](4);
args[0] = "git";
args[1] = "rev-parse";
Expand All @@ -145,13 +145,13 @@ abstract contract BaseDeployment is Script {
bytes memory result = vm.ffi(args);
string memory commit = string(result);

// Update deployment.toml with CirculatingZKC commit
// Update deployment.toml with SupplyCalculator commit
string[] memory updateArgs = new string[](6);
updateArgs[0] = "python3";
updateArgs[1] = "update_deployment_toml.py";
updateArgs[2] = "--chain-key";
updateArgs[3] = deploymentKey;
updateArgs[4] = "--circulating-zkc-commit";
updateArgs[4] = "--supply-calculator-commit";
updateArgs[5] = commit;

vm.ffi(updateArgs);
Expand Down
24 changes: 17 additions & 7 deletions script/Config.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ struct DeploymentConfig {
address stakingRewardsDeployer;
address povwMinter;
address stakingMinter;
address circulatingZKC;
address circulatingZKCImpl;
address circulatingZKCAdmin;
address supplyCalculator;
address supplyCalculatorImpl;
address supplyCalculatorImplPrev;
address supplyCalculatorAdmin;
address supplyCalculatorAdmin2;
string zkcCommit;
string veZKCCommit;
string stakingRewardsCommit;
string circulatingZKCCommit;
string supplyCalculatorCommit;
}

library ConfigLoader {
Expand Down Expand Up @@ -76,9 +78,14 @@ library ConfigLoader {
_readAddressOrZero(vm, toml, string.concat(keyPrefix, ".staking-rewards-deployer"));
config.povwMinter = _readAddressOrZero(vm, toml, string.concat(keyPrefix, ".povw-minter"));
config.stakingMinter = _readAddressOrZero(vm, toml, string.concat(keyPrefix, ".staking-minter"));
config.circulatingZKC = _readAddressOrZero(vm, toml, string.concat(keyPrefix, ".circulating-zkc"));
config.circulatingZKCImpl = _readAddressOrZero(vm, toml, string.concat(keyPrefix, ".circulating-zkc-impl"));
config.circulatingZKCAdmin = _readAddressOrZero(vm, toml, string.concat(keyPrefix, ".circulating-zkc-admin"));
config.supplyCalculator = _readAddressOrZero(vm, toml, string.concat(keyPrefix, ".supply-calculator"));
config.supplyCalculatorImpl = _readAddressOrZero(vm, toml, string.concat(keyPrefix, ".supply-calculator-impl"));
config.supplyCalculatorImplPrev =
_readAddressOrZero(vm, toml, string.concat(keyPrefix, ".supply-calculator-impl-prev"));
config.supplyCalculatorAdmin =
_readAddressOrZero(vm, toml, string.concat(keyPrefix, ".supply-calculator-admin"));
config.supplyCalculatorAdmin2 =
_readAddressOrZero(vm, toml, string.concat(keyPrefix, ".supply-calculator-admin-2"));

// Read per-contract deployment commits, default to empty string if not found
string memory zkcCommitKey = string.concat(keyPrefix, ".zkc-commit");
Expand All @@ -90,6 +97,9 @@ library ConfigLoader {
string memory stakingRewardsCommitKey = string.concat(keyPrefix, ".staking-rewards-commit");
config.stakingRewardsCommit = _readStringOrEmpty(toml, stakingRewardsCommitKey);

string memory supplyCalculatorCommitKey = string.concat(keyPrefix, ".supply-calculator-commit");
config.supplyCalculatorCommit = _readStringOrEmpty(toml, supplyCalculatorCommitKey);

return (config, deploymentKey);
}

Expand Down
44 changes: 22 additions & 22 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {console2} from "forge-std/Script.sol";
import {ZKC} from "../src/ZKC.sol";
import {veZKC} from "../src/veZKC.sol";
import {StakingRewards} from "../src/rewards/StakingRewards.sol";
import {CirculatingZKC} from "../src/circulating/CirculatingZKC.sol";
import {SupplyCalculator} from "../src/calculators/SupplyCalculator.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
import {ConfigLoader, DeploymentConfig} from "./Config.s.sol";
Expand Down Expand Up @@ -213,18 +213,18 @@ contract DeployStakingRewards is BaseDeployment {
}

/**
* Sample Usage for CirculatingZKC deployment:
* Sample Usage for SupplyCalculator deployment:
*
* export CHAIN_KEY="anvil"
* export INITIAL_UNLOCKED="500000000000000000000000000" # 500M tokens
* export SALT="0x0000000000000000000000000000000000000000000000000000000000000001"
*
* forge script script/Deploy.s.sol:DeployCirculatingZKC \
* forge script script/Deploy.s.sol:DeploySupplyCalculator \
* --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
* --broadcast \
* --rpc-url http://127.0.0.1:8545
*/
contract DeployCirculatingZKC is BaseDeployment {
contract DeploySupplyCalculator is BaseDeployment {
function setUp() public {}

function run() public {
Expand All @@ -241,35 +241,35 @@ contract DeployCirculatingZKC is BaseDeployment {

bytes32 salt = vm.envOr("SALT", bytes32(0));

// Deploy CirculatingZKC implementation
address circulatingZKCImpl = address(new CirculatingZKC{salt: salt}());
console2.log("Deployed CirculatingZKC implementation to: ", circulatingZKCImpl);
// Deploy SupplyCalculator implementation
address supplyCalculatorImpl = address(new SupplyCalculator{salt: salt}());
console2.log("Deployed SupplyCalculator implementation to: ", supplyCalculatorImpl);

// Deploy proxy with initialization
ERC1967Proxy proxy = new ERC1967Proxy{salt: salt}(
circulatingZKCImpl, abi.encodeCall(CirculatingZKC.initialize, (config.zkc, initialUnlockedRaw, admin))
supplyCalculatorImpl, abi.encodeCall(SupplyCalculator.initialize, (config.zkc, initialUnlockedRaw, admin))
);
address circulatingZKCAddress = address(proxy);
address supplyCalculatorAddress = address(proxy);

vm.stopBroadcast();

// Update deployment.toml
_updateDeploymentConfig(deploymentKey, "circulating-zkc", circulatingZKCAddress);
_updateDeploymentConfig(deploymentKey, "circulating-zkc-impl", circulatingZKCImpl);
_updateDeploymentConfig(deploymentKey, "circulating-zkc-admin", admin);
_updateCirculatingZKCCommit(deploymentKey);
_updateDeploymentConfig(deploymentKey, "supply-calculator", supplyCalculatorAddress);
_updateDeploymentConfig(deploymentKey, "supply-calculator-impl", supplyCalculatorImpl);
_updateDeploymentConfig(deploymentKey, "supply-calculator-admin", admin);
_updateSupplyCalculatorCommit(deploymentKey);

// Sanity checks
CirculatingZKC circulatingContract = CirculatingZKC(circulatingZKCAddress);
IAccessControl accessControl = IAccessControl(circulatingZKCAddress);
SupplyCalculator supplyCalculator = SupplyCalculator(supplyCalculatorAddress);
IAccessControl accessControl = IAccessControl(supplyCalculatorAddress);
console2.log("Admin address: ", admin);
console2.log("Admin role assigned: ", accessControl.hasRole(circulatingContract.ADMIN_ROLE(), admin));
console2.log("ZKC token address: ", address(circulatingContract.zkc()));
console2.log("Initial unlocked amount: ", circulatingContract.unlocked());
console2.log("Initial unlocked amount (in tokens): ", circulatingContract.unlocked() / 10 ** 18);
console2.log("Current circulating supply: ", circulatingContract.circulatingSupply());
console2.log("Current circulating supply (in tokens): ", circulatingContract.circulatingSupply() / 10 ** 18);
console2.log("Admin role assigned: ", accessControl.hasRole(supplyCalculator.ADMIN_ROLE(), admin));
console2.log("ZKC token address: ", address(supplyCalculator.zkc()));
console2.log("Initial unlocked amount: ", supplyCalculator.unlocked());
console2.log("Initial unlocked amount (in tokens): ", supplyCalculator.unlocked() / 10 ** 18);
console2.log("Current circulating supply: ", supplyCalculator.circulatingSupply());
console2.log("Current circulating supply (in tokens): ", supplyCalculator.circulatingSupply() / 10 ** 18);
console2.log("================================================");
console2.log("Deployed CirculatingZKC to: ", circulatingZKCAddress);
console2.log("Deployed SupplyCalculator to: ", supplyCalculatorAddress);
}
}
63 changes: 63 additions & 0 deletions script/Rollback.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {BaseDeployment} from "./BaseDeployment.s.sol";
import {ZKC} from "../src/ZKC.sol";
import {veZKC} from "../src/veZKC.sol";
import {StakingRewards} from "../src/rewards/StakingRewards.sol";
import {SupplyCalculator} from "../src/calculators/SupplyCalculator.sol";
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";

/**
Expand Down Expand Up @@ -206,3 +207,65 @@ contract RollbackStakingRewards is BaseDeployment {
console2.log("Rolled back to implementation: ", rolledBackImpl);
}
}

/**
* Sample Usage for SupplyCalculator rollback:
*
* export CHAIN_KEY="anvil"
* forge script script/Rollback.s.sol:RollbackSupplyCalculator \
* --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
* --broadcast \
* --rpc-url http://127.0.0.1:8545
*/
contract RollbackSupplyCalculator is BaseDeployment {
function run() public {
(DeploymentConfig memory config, string memory deploymentKey) = ConfigLoader.loadDeploymentConfig(vm);
require(config.supplyCalculator != address(0), "SupplyCalculator not deployed");
require(
config.supplyCalculatorImplPrev != address(0),
"No previous SupplyCalculator implementation found for rollback"
);

vm.startBroadcast();

address currentImpl = _getImplementationAddress(config.supplyCalculator);
console2.log("Rolling back SupplyCalculator at: ", config.supplyCalculator);
console2.log("Current implementation: ", currentImpl);
console2.log("Previous implementation: ", config.supplyCalculatorImplPrev);

// Verify previous implementation has code
require(_getCodeSize(config.supplyCalculatorImplPrev) > 0, "Previous implementation has no code");

// Perform rollback by directly upgrading to previous implementation (unsafe)
(bool success,) = config.supplyCalculator.call(
abi.encodeWithSignature("upgradeToAndCall(address,bytes)", config.supplyCalculatorImplPrev, "")
);
require(success, "Failed to rollback SupplyCalculator implementation");

address rolledBackImpl = _getImplementationAddress(config.supplyCalculator);
console2.log("Rolled back SupplyCalculator implementation to: ", rolledBackImpl);
require(rolledBackImpl == config.supplyCalculatorImplPrev, "Rollback failed: implementation mismatch");

vm.stopBroadcast();

// Update deployment.toml: swap current and previous implementations
_updateDeploymentConfig(deploymentKey, "supply-calculator-impl", config.supplyCalculatorImplPrev);
_updateDeploymentConfig(deploymentKey, "supply-calculator-impl-prev", currentImpl);

// Verify rollback
SupplyCalculator supplyCalculatorContract = SupplyCalculator(config.supplyCalculator);
IAccessControl accessControl = IAccessControl(config.supplyCalculator);
console2.log(
"Proxy still points to SupplyCalculator: ", address(supplyCalculatorContract) == config.supplyCalculator
);
console2.log(
"Admin role still assigned: ",
accessControl.hasRole(supplyCalculatorContract.ADMIN_ROLE(), config.supplyCalculatorAdmin)
);
console2.log("ZKC token still configured: ", address(supplyCalculatorContract.zkc()) == config.zkc);
console2.log("Rollback verification successful");
console2.log("================================================");
console2.log("SupplyCalculator Rollback Complete");
console2.log("Rolled back to implementation: ", rolledBackImpl);
}
}
Loading
Loading