From 7c8d9f58b8590ce15182e8be5e3d157e5c716582 Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Wed, 5 Jun 2024 13:00:22 +0300 Subject: [PATCH 1/6] Add MigrateAccounting.s.sol --- script/scripts/MigrateAccounting.s.sol | 167 +++++++++++++++++++++++++ src/zkbob/ZkBobPool.sol | 2 +- 2 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 script/scripts/MigrateAccounting.s.sol diff --git a/script/scripts/MigrateAccounting.s.sol b/script/scripts/MigrateAccounting.s.sol new file mode 100644 index 0000000..fd84bd5 --- /dev/null +++ b/script/scripts/MigrateAccounting.s.sol @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: CC0-1.0 + +pragma solidity 0.8.15; + +import {Script} from "forge-std/Script.sol"; +import {Test} from "forge-std/Test.sol"; +import {ZkBobPool, ZkBobPoolUSDC} from "../../src/zkbob/ZkBobPoolUSDC.sol"; +import {IZkBobAccounting, IKycProvidersManager, ZkBobAccounting} from "../../src/zkbob/utils/ZkBobAccounting.sol"; +import {EIP1967Proxy} from "../../src/proxy/EIP1967Proxy.sol"; + +/** + * @dev OP-USDC pool proxy address. + */ +address constant zkBobPool = 0x1CA8C2B9B20E18e86d5b9a72370fC6c91814c97C; + +/** + * @dev This address will become an owner of the the new ZkBobAccounting contract. + */ +address constant accountingOwner = 0x14fc6a1a996A2EB889cF86e5c8cD17323bC85290; + +// Used to check that the relayer fee is correctly migrated +address constant relayer = 0xb9CD01c0b417b4e9095f620aE2f849A84a9B1690; + +contract UpgradeTest is Test { + struct PoolSnapshot { + address owner; + bytes32 slot0; + bytes32 slot1; + uint256 poolIndex; + uint256 oneNullifier; + uint256 lastRoot; + bytes32 all_messages_hash; + uint256 relayerFee; + address tokenSeller; + address kycManager; + } + + function makeSnapshot(ZkBobPoolUSDC _pool) internal view returns (PoolSnapshot memory) { + return PoolSnapshot({ + owner: _pool.owner(), + slot0: vm.load(address(_pool), bytes32(uint256(1))), + slot1: vm.load(address(_pool), bytes32(uint256(2))), + poolIndex: _pool.pool_index(), + oneNullifier: _pool.nullifiers(0x39a833a5c374a0a3328f65ae9a9bf883945694cca613a8415c3a555bda388cd), + lastRoot: _pool.roots(_pool.pool_index()), + all_messages_hash: _pool.all_messages_hash(), + relayerFee: _pool.accumulatedFee(relayer), + tokenSeller: address(_pool.tokenSeller()), + kycManager: address(ZkBobAccounting(address(_pool)).kycProvidersManager()) + }); + } + + function postCheck(ZkBobPoolUSDC _pool, PoolSnapshot memory _snapshot) internal { + assertEq(_snapshot.owner, _pool.owner()); + assertEq(address(_pool.redeemer()), address(0)); // redeemer is not set by script + assertNotEq(address(_pool.accounting()), address(0)); + assertEq(_snapshot.poolIndex, uint256(_pool.pool_index())); + assertEq( + _snapshot.oneNullifier, _pool.nullifiers(0x39a833a5c374a0a3328f65ae9a9bf883945694cca613a8415c3a555bda388cd) + ); + assertEq(_snapshot.lastRoot, _pool.roots(_pool.pool_index())); + assertEq(_snapshot.all_messages_hash, _pool.all_messages_hash()); + assertEq(_snapshot.relayerFee, _pool.accumulatedFee(relayer)); + assertEq(_snapshot.tokenSeller, address(_pool.tokenSeller())); + assertEq(_snapshot.kycManager, address(ZkBobAccounting(address(_pool.accounting())).kycProvidersManager())); + assertEq(accountingOwner, ZkBobAccounting(address(_pool.accounting())).owner()); + + checkSlot0(uint256(_snapshot.slot0), ZkBobAccounting(address(_pool.accounting()))); + checkSlot1(uint256(_snapshot.slot1), ZkBobAccounting(address(_pool.accounting()))); + } + + function checkSlot0(uint256 slot0, ZkBobAccounting accounting) internal { + ( + uint56 maxWeeklyAvgTvl, + uint32 maxWeeklyTxCount, + uint24 tailSlot, + uint24 headSlot, + uint88 cumTvl, + uint32 txCount + ) = accounting.slot0(); + uint24 curSlot = uint24(block.timestamp / 1 hours); + + assertEq(uint56(slot0), maxWeeklyAvgTvl); + assertEq(uint32(slot0 >> 56), maxWeeklyTxCount); + assertEq(curSlot, tailSlot); + assertEq(curSlot, headSlot); + assertEq(uint88(slot0 >> (56 + 32 + 24 + 24)), cumTvl); + assertEq(uint32(slot0 >> (56 + 32 + 24 + 24 + 88)), txCount); + } + + function checkSlot1(uint256 slot1, ZkBobAccounting accounting) internal { + (uint72 tvl) = accounting.slot1(); + assertEq(uint72(slot1), tvl); + } +} + +contract MigrateAccounting is Script, UpgradeTest { + function run() external { + ZkBobPoolUSDC pool = ZkBobPoolUSDC(address(zkBobPool)); + PoolSnapshot memory snapshot = makeSnapshot(pool); + + vm.startBroadcast(); + + // 1. Deploy new ZkBobPoolUSDC implementation + ZkBobPoolUSDC newImpl = new ZkBobPoolUSDC( + pool.pool_id(), + pool.token(), + pool.transfer_verifier(), + pool.tree_verifier(), + pool.batch_deposit_verifier(), + address(pool.direct_deposit_queue()) + ); + + // 2. Upgrade proxy to new implementation + EIP1967Proxy(payable(address(pool))).upgradeTo(address(newImpl)); + + migrateAccounting(address(pool), address(snapshot.kycManager)); + + vm.stopBroadcast(); + + postCheck(ZkBobPoolUSDC(address(pool)), snapshot); + } + + // TODO: Check limits + function migrateAccounting(address _pool, address _kycManager) internal { + // 3. Deploy new ZkBobAccounting implementation + ZkBobAccounting accounting = new ZkBobAccounting(address(_pool), 1_000_000_000); + + bytes memory dump = ZkBobPool(_pool).extsload(bytes32(uint256(1)), 2); + uint32 txCount = uint32(_load(dump, 0, 4)); + uint88 cumTvl = uint88(_load(dump, 4, 11)); + uint32 maxWeeklyTxCount = uint32(_load(dump, 21, 4)); + uint56 maxWeeklyAvgTvl = uint56(_load(dump, 25, 7)); + uint72 tvl = uint72(_load(dump, 55, 9)); + + // 4. Initialize pool index + ZkBobPool(_pool).initializePoolIndex(txCount * 128); + // 5. Set accounting + ZkBobPool(_pool).setAccounting(IZkBobAccounting(accounting)); + + // 6. Initialize accounting + ZkBobAccounting(accounting).initialize(txCount, tvl, cumTvl, maxWeeklyTxCount, maxWeeklyAvgTvl); + // 7. Set kyc providers manager + ZkBobAccounting(accounting).setKycProvidersManager(IKycProvidersManager(_kycManager)); + // 8. Set limits for tier 0 + ZkBobAccounting(accounting).setLimits( + 0, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 10_000 gwei, 10_000 gwei, 10_000 gwei, 1_000 gwei + ); + // 9. Set limits for tier 1 + ZkBobAccounting(accounting).setLimits( + 1, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 100_000 gwei, 100_000 gwei, 10_000 gwei, 1_000 gwei + ); + // 10. Set limits for tier 254 + ZkBobAccounting(accounting).setLimits( + 254, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 20_000 gwei, 20_000 gwei, 10_000 gwei, 1_000 gwei + ); + + // 11. Transfer accounting accounting ownership to the owner + accounting.transferOwnership(accountingOwner); + } + + function _load(bytes memory _dump, uint256 _from, uint256 _len) internal pure returns (uint256 res) { + assembly { + res := shr(sub(256, shl(3, _len)), mload(add(_dump, add(32, _from)))) + } + } +} \ No newline at end of file diff --git a/src/zkbob/ZkBobPool.sol b/src/zkbob/ZkBobPool.sol index fb89938..6f79da1 100644 --- a/src/zkbob/ZkBobPool.sol +++ b/src/zkbob/ZkBobPool.sol @@ -38,7 +38,7 @@ abstract contract ZkBobPool is IZkBobPool, EIP1967Admin, Ownable, Parameters, Ex uint256 internal constant FORCED_EXIT_MAX_DELAY = 24 hours; uint256 internal immutable TOKEN_DENOMINATOR; - uint256 internal constant TOKEN_NUMERATOR = 1; + uint256 internal constant TOKEN_NUMERATOR = 1000; uint256 public immutable pool_id; ITransferVerifier public immutable transfer_verifier; From 6c43007c7fce26b37dbea30845a7a8897e994367 Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Thu, 6 Jun 2024 14:51:50 +0300 Subject: [PATCH 2/6] Fix formatting, set numerator back to 1 --- script/scripts/DeployZkBobPoolModules.s.sol | 85 --------------------- script/scripts/Local.s.sol | 7 +- script/scripts/MigrateAccounting.s.sol | 5 +- script/scripts/ZkBobPool.s.sol | 28 ++++--- src/interfaces/IZkBobDirectDeposits.sol | 1 + src/zkbob/ZkBobPool.sol | 2 +- test/zkbob/ZkBobPool.t.sol | 35 ++++++--- 7 files changed, 48 insertions(+), 115 deletions(-) delete mode 100644 script/scripts/DeployZkBobPoolModules.s.sol diff --git a/script/scripts/DeployZkBobPoolModules.s.sol b/script/scripts/DeployZkBobPoolModules.s.sol deleted file mode 100644 index 1715179..0000000 --- a/script/scripts/DeployZkBobPoolModules.s.sol +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 - -pragma solidity 0.8.15; - -import "forge-std/Script.sol"; -import "forge-std/Test.sol"; -import "./Env.s.sol"; -import "../../src/zkbob/ZkBobPool.sol"; -import "../../src/zkbob/utils/ZkBobAccounting.sol"; -import "../../src/proxy/EIP1967Proxy.sol"; -import "../../src/zkbob/ZkBobPoolUSDC.sol"; - -contract DummyDelegateCall { - function delegate(address to, bytes calldata data) external { - (bool status,) = address(to).delegatecall(data); - require(status); - } -} - -contract Migrator { - function migrate(address _target, address _newImpl, address _accounting) external { - address kycManager = address(ZkBobAccounting(_target).kycProvidersManager()); - - EIP1967Proxy(payable(_target)).upgradeTo(_newImpl); - - bytes memory dump = ZkBobPool(_target).extsload(bytes32(uint256(1)), 2); - uint32 txCount = uint32(_load(dump, 0, 4)); - uint88 cumTvl = uint88(_load(dump, 4, 11)); - uint32 maxWeeklyTxCount = uint32(_load(dump, 21, 4)); - uint56 maxWeeklyAvgTvl = uint56(_load(dump, 25, 7)); - uint72 tvl = uint72(_load(dump, 55, 9)); - - ZkBobPool(_target).initializePoolIndex(txCount * 128); - ZkBobPool(_target).setAccounting(IZkBobAccounting(_accounting)); - ZkBobAccounting(_accounting).initialize(txCount + 1, tvl, cumTvl, maxWeeklyTxCount, maxWeeklyAvgTvl); - ZkBobAccounting(_accounting).setKycProvidersManager(IKycProvidersManager(kycManager)); - ZkBobAccounting(_accounting).setLimits( - 0, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 10_000 gwei, 10_000 gwei, 10_000 gwei, 1_000 gwei - ); - ZkBobAccounting(_accounting).setLimits( - 1, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 100_000 gwei, 100_000 gwei, 10_000 gwei, 1_000 gwei - ); - ZkBobAccounting(_accounting).setLimits( - 254, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 20_000 gwei, 20_000 gwei, 10_000 gwei, 1_000 gwei - ); - } - - function _load(bytes memory _dump, uint256 _from, uint256 _len) internal returns (uint256 res) { - assembly { - res := shr(sub(256, shl(3, _len)), mload(add(_dump, add(32, _from)))) - } - } -} - -contract DeployZkBobPoolModules is Script, Test { - function run() external { - ZkBobPoolUSDC pool = ZkBobPoolUSDC(address(zkBobPool)); - address owner = pool.owner(); - vm.etch(owner, type(DummyDelegateCall).runtimeCode); - - address tokenSeller = address(pool.tokenSeller()); - uint256 poolIndex = uint256(pool.pool_index()); - - vm.startBroadcast(); - - ZkBobPoolUSDC impl = new ZkBobPoolUSDC( - pool.pool_id(), pool.token(), pool.transfer_verifier(), pool.tree_verifier(), - pool.batch_deposit_verifier(), address(pool.direct_deposit_queue()) - ); - Migrator mig = new Migrator(); - ZkBobAccounting acc = new ZkBobAccounting(address(pool), 1_000_000_000); - acc.transferOwnership(owner); - DummyDelegateCall(owner).delegate( - address(mig), abi.encodeWithSelector(Migrator.migrate.selector, address(pool), address(impl), address(acc)) - ); - - vm.stopBroadcast(); - - acc.slot0(); - acc.slot1(); - - assertEq(address(pool.tokenSeller()), tokenSeller); - assertEq(uint256(pool.pool_index()), poolIndex); - } -} diff --git a/script/scripts/Local.s.sol b/script/scripts/Local.s.sol index 7f33ba5..eac51bc 100644 --- a/script/scripts/Local.s.sol +++ b/script/scripts/Local.s.sol @@ -45,12 +45,7 @@ contract DeployLocal is Script { EIP1967Proxy queueProxy = new EIP1967Proxy(tx.origin, mockImpl, ""); ZkBobPoolBOB poolImpl = new ZkBobPoolBOB( - zkBobPoolId, - address(bob), - transferVerifier, - treeVerifier, - batchDepositVerifier, - address(queueProxy) + zkBobPoolId, address(bob), transferVerifier, treeVerifier, batchDepositVerifier, address(queueProxy) ); { bytes memory initData = abi.encodeWithSelector(ZkBobPool.initialize.selector, zkBobInitialRoot); diff --git a/script/scripts/MigrateAccounting.s.sol b/script/scripts/MigrateAccounting.s.sol index fd84bd5..ff2acd4 100644 --- a/script/scripts/MigrateAccounting.s.sol +++ b/script/scripts/MigrateAccounting.s.sol @@ -94,6 +94,9 @@ contract UpgradeTest is Test { } } +/** + * @dev Don't forget to set ZkBobPool.TOKEN_NUMERATOR to 1000 for USDC pools. + */ contract MigrateAccounting is Script, UpgradeTest { function run() external { ZkBobPoolUSDC pool = ZkBobPoolUSDC(address(zkBobPool)); @@ -164,4 +167,4 @@ contract MigrateAccounting is Script, UpgradeTest { res := shr(sub(256, shl(3, _len)), mload(add(_dump, add(32, _from)))) } } -} \ No newline at end of file +} diff --git a/script/scripts/ZkBobPool.s.sol b/script/scripts/ZkBobPool.s.sol index 337c156..037ea91 100644 --- a/script/scripts/ZkBobPool.s.sol +++ b/script/scripts/ZkBobPool.s.sol @@ -53,27 +53,31 @@ contract DeployZkBobPool is Script { if (zkBobPoolType == PoolType.ETH) { vars.poolImpl = new ZkBobPoolETH( - zkBobPoolId, zkBobToken, - transferVerifier, treeVerifier, batchDepositVerifier, - address(vars.queueProxy), permit2 + zkBobPoolId, + zkBobToken, + transferVerifier, + treeVerifier, + batchDepositVerifier, + address(vars.queueProxy), + permit2 ); } else if (zkBobPoolType == PoolType.BOB) { vars.poolImpl = new ZkBobPoolBOB( - zkBobPoolId, zkBobToken, - transferVerifier, treeVerifier, batchDepositVerifier, - address(vars.queueProxy) + zkBobPoolId, zkBobToken, transferVerifier, treeVerifier, batchDepositVerifier, address(vars.queueProxy) ); } else if (zkBobPoolType == PoolType.USDC) { vars.poolImpl = new ZkBobPoolUSDC( - zkBobPoolId, zkBobToken, - transferVerifier, treeVerifier, batchDepositVerifier, - address(vars.queueProxy) + zkBobPoolId, zkBobToken, transferVerifier, treeVerifier, batchDepositVerifier, address(vars.queueProxy) ); } else if (zkBobPoolType == PoolType.ERC20) { vars.poolImpl = new ZkBobPoolERC20( - zkBobPoolId, zkBobToken, - transferVerifier, treeVerifier, batchDepositVerifier, - address(vars.queueProxy), permit2, + zkBobPoolId, + zkBobToken, + transferVerifier, + treeVerifier, + batchDepositVerifier, + address(vars.queueProxy), + permit2, vars.denominator ); } else { diff --git a/src/interfaces/IZkBobDirectDeposits.sol b/src/interfaces/IZkBobDirectDeposits.sol index 51caf36..72eedab 100644 --- a/src/interfaces/IZkBobDirectDeposits.sol +++ b/src/interfaces/IZkBobDirectDeposits.sol @@ -8,6 +8,7 @@ interface IZkBobDirectDeposits { Pending, // requested deposit was submitted and is pending in the queue Completed, // requested deposit was successfully processed Refunded // requested deposit was refunded to the fallback receiver + } struct DirectDeposit { diff --git a/src/zkbob/ZkBobPool.sol b/src/zkbob/ZkBobPool.sol index 6f79da1..fb89938 100644 --- a/src/zkbob/ZkBobPool.sol +++ b/src/zkbob/ZkBobPool.sol @@ -38,7 +38,7 @@ abstract contract ZkBobPool is IZkBobPool, EIP1967Admin, Ownable, Parameters, Ex uint256 internal constant FORCED_EXIT_MAX_DELAY = 24 hours; uint256 internal immutable TOKEN_DENOMINATOR; - uint256 internal constant TOKEN_NUMERATOR = 1000; + uint256 internal constant TOKEN_NUMERATOR = 1; uint256 public immutable pool_id; ITransferVerifier public immutable transfer_verifier; diff --git a/test/zkbob/ZkBobPool.t.sol b/test/zkbob/ZkBobPool.t.sol index 8428f9b..ceecd01 100644 --- a/test/zkbob/ZkBobPool.t.sol +++ b/test/zkbob/ZkBobPool.t.sol @@ -95,27 +95,42 @@ abstract contract AbstractZkBobPoolTest is AbstractForkTest { ZkBobPool impl; if (poolType == PoolType.ETH) { impl = new ZkBobPoolETH( - 0, token, - new TransferVerifierMock(), new TreeUpdateVerifierMock(), new BatchDepositVerifierMock(), - address(queueProxy), permit2 + 0, + token, + new TransferVerifierMock(), + new TreeUpdateVerifierMock(), + new BatchDepositVerifierMock(), + address(queueProxy), + permit2 ); } else if (poolType == PoolType.BOB) { impl = new ZkBobPoolBOB( - 0, token, - new TransferVerifierMock(), new TreeUpdateVerifierMock(), new BatchDepositVerifierMock(), + 0, + token, + new TransferVerifierMock(), + new TreeUpdateVerifierMock(), + new BatchDepositVerifierMock(), address(queueProxy) ); } else if (poolType == PoolType.USDC) { impl = new ZkBobPoolUSDC( - 0, token, - new TransferVerifierMock(), new TreeUpdateVerifierMock(), new BatchDepositVerifierMock(), + 0, + token, + new TransferVerifierMock(), + new TreeUpdateVerifierMock(), + new BatchDepositVerifierMock(), address(queueProxy) ); } else if (poolType == PoolType.ERC20) { impl = new ZkBobPoolERC20( - 0, token, - new TransferVerifierMock(), new TreeUpdateVerifierMock(), new BatchDepositVerifierMock(), - address(queueProxy), permit2, 1_000_000_000 + 0, + token, + new TransferVerifierMock(), + new TreeUpdateVerifierMock(), + new BatchDepositVerifierMock(), + address(queueProxy), + permit2, + 1_000_000_000 ); } From a91af4567edb0da43cd15da47997c3517201cc37 Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Wed, 19 Jun 2024 18:28:13 +0300 Subject: [PATCH 3/6] Refactor migration scripts --- script/scripts/MigrateAccounting.s.sol | 91 +++++-------------- script/scripts/PreMigrateAccounting.s.sol | 57 ++++++++++++ script/scripts/helpers/AccountingMigrator.sol | 55 +++++++++++ 3 files changed, 137 insertions(+), 66 deletions(-) create mode 100644 script/scripts/PreMigrateAccounting.s.sol create mode 100644 script/scripts/helpers/AccountingMigrator.sol diff --git a/script/scripts/MigrateAccounting.s.sol b/script/scripts/MigrateAccounting.s.sol index ff2acd4..47521a9 100644 --- a/script/scripts/MigrateAccounting.s.sol +++ b/script/scripts/MigrateAccounting.s.sol @@ -7,22 +7,25 @@ import {Test} from "forge-std/Test.sol"; import {ZkBobPool, ZkBobPoolUSDC} from "../../src/zkbob/ZkBobPoolUSDC.sol"; import {IZkBobAccounting, IKycProvidersManager, ZkBobAccounting} from "../../src/zkbob/utils/ZkBobAccounting.sol"; import {EIP1967Proxy} from "../../src/proxy/EIP1967Proxy.sol"; +import {AccountingMigrator} from "./helpers/AccountingMigrator.sol"; + +// WARN: Update this values before running the script +address constant newZkBobPoolImpl = 0xD217AEf4aB37F7CeE7462d25cbD91f46c1E688a9; +address constant zkBobAccounting = 0xFd5a6a67D768d5BF1A8c7724387CA8786Bd4DD91; +address constant accountingMigrator = 0x0114Bf30d9f5A7f503D3DFC65534F2B5AC302c85; +address constant accountingOwner = 0x14fc6a1a996A2EB889cF86e5c8cD17323bC85290; /** * @dev OP-USDC pool proxy address. */ address constant zkBobPool = 0x1CA8C2B9B20E18e86d5b9a72370fC6c91814c97C; -/** - * @dev This address will become an owner of the the new ZkBobAccounting contract. - */ -address constant accountingOwner = 0x14fc6a1a996A2EB889cF86e5c8cD17323bC85290; - // Used to check that the relayer fee is correctly migrated address constant relayer = 0xb9CD01c0b417b4e9095f620aE2f849A84a9B1690; contract UpgradeTest is Test { struct PoolSnapshot { + address proxyAdmin; address owner; bytes32 slot0; bytes32 slot1; @@ -37,6 +40,7 @@ contract UpgradeTest is Test { function makeSnapshot(ZkBobPoolUSDC _pool) internal view returns (PoolSnapshot memory) { return PoolSnapshot({ + proxyAdmin: EIP1967Proxy(payable(address(_pool))).admin(), owner: _pool.owner(), slot0: vm.load(address(_pool), bytes32(uint256(1))), slot1: vm.load(address(_pool), bytes32(uint256(2))), @@ -51,6 +55,7 @@ contract UpgradeTest is Test { } function postCheck(ZkBobPoolUSDC _pool, PoolSnapshot memory _snapshot) internal { + assertEq(_snapshot.proxyAdmin, EIP1967Proxy(payable(address(_pool))).admin()); assertEq(_snapshot.owner, _pool.owner()); assertEq(address(_pool.redeemer()), address(0)); // redeemer is not set by script assertNotEq(address(_pool.accounting()), address(0)); @@ -94,77 +99,31 @@ contract UpgradeTest is Test { } } -/** - * @dev Don't forget to set ZkBobPool.TOKEN_NUMERATOR to 1000 for USDC pools. - */ contract MigrateAccounting is Script, UpgradeTest { function run() external { ZkBobPoolUSDC pool = ZkBobPoolUSDC(address(zkBobPool)); + AccountingMigrator migrator = AccountingMigrator(accountingMigrator); PoolSnapshot memory snapshot = makeSnapshot(pool); vm.startBroadcast(); - - // 1. Deploy new ZkBobPoolUSDC implementation - ZkBobPoolUSDC newImpl = new ZkBobPoolUSDC( - pool.pool_id(), - pool.token(), - pool.transfer_verifier(), - pool.tree_verifier(), - pool.batch_deposit_verifier(), - address(pool.direct_deposit_queue()) + + EIP1967Proxy(payable(address(pool))).upgradeTo(address(newZkBobPoolImpl)); + + EIP1967Proxy(payable(address(pool))).setAdmin(accountingMigrator); + + ZkBobAccounting(zkBobAccounting).transferOwnership(accountingMigrator); + + migrator.migrate( + address(pool), + zkBobAccounting, + snapshot.kycManager, + accountingOwner, + snapshot.proxyAdmin ); - // 2. Upgrade proxy to new implementation - EIP1967Proxy(payable(address(pool))).upgradeTo(address(newImpl)); - - migrateAccounting(address(pool), address(snapshot.kycManager)); - vm.stopBroadcast(); postCheck(ZkBobPoolUSDC(address(pool)), snapshot); } - - // TODO: Check limits - function migrateAccounting(address _pool, address _kycManager) internal { - // 3. Deploy new ZkBobAccounting implementation - ZkBobAccounting accounting = new ZkBobAccounting(address(_pool), 1_000_000_000); - - bytes memory dump = ZkBobPool(_pool).extsload(bytes32(uint256(1)), 2); - uint32 txCount = uint32(_load(dump, 0, 4)); - uint88 cumTvl = uint88(_load(dump, 4, 11)); - uint32 maxWeeklyTxCount = uint32(_load(dump, 21, 4)); - uint56 maxWeeklyAvgTvl = uint56(_load(dump, 25, 7)); - uint72 tvl = uint72(_load(dump, 55, 9)); - - // 4. Initialize pool index - ZkBobPool(_pool).initializePoolIndex(txCount * 128); - // 5. Set accounting - ZkBobPool(_pool).setAccounting(IZkBobAccounting(accounting)); - - // 6. Initialize accounting - ZkBobAccounting(accounting).initialize(txCount, tvl, cumTvl, maxWeeklyTxCount, maxWeeklyAvgTvl); - // 7. Set kyc providers manager - ZkBobAccounting(accounting).setKycProvidersManager(IKycProvidersManager(_kycManager)); - // 8. Set limits for tier 0 - ZkBobAccounting(accounting).setLimits( - 0, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 10_000 gwei, 10_000 gwei, 10_000 gwei, 1_000 gwei - ); - // 9. Set limits for tier 1 - ZkBobAccounting(accounting).setLimits( - 1, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 100_000 gwei, 100_000 gwei, 10_000 gwei, 1_000 gwei - ); - // 10. Set limits for tier 254 - ZkBobAccounting(accounting).setLimits( - 254, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 20_000 gwei, 20_000 gwei, 10_000 gwei, 1_000 gwei - ); - - // 11. Transfer accounting accounting ownership to the owner - accounting.transferOwnership(accountingOwner); - } - - function _load(bytes memory _dump, uint256 _from, uint256 _len) internal pure returns (uint256 res) { - assembly { - res := shr(sub(256, shl(3, _len)), mload(add(_dump, add(32, _from)))) - } - } } + diff --git a/script/scripts/PreMigrateAccounting.s.sol b/script/scripts/PreMigrateAccounting.s.sol new file mode 100644 index 0000000..6af239a --- /dev/null +++ b/script/scripts/PreMigrateAccounting.s.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: CC0-1.0 + +pragma solidity 0.8.15; + +import {console, Script} from "forge-std/Script.sol"; +import {ZkBobPoolUSDC} from "../../src/zkbob/ZkBobPoolUSDC.sol"; +import {ZkBobAccounting} from "../../src/zkbob/utils/ZkBobAccounting.sol"; +import {EIP1967Proxy} from "../../src/proxy/EIP1967Proxy.sol"; +import {AccountingMigrator} from "./helpers/AccountingMigrator.sol"; + +/** + * @dev OP-USDC pool proxy address. + */ +address constant zkBobPool = 0x1CA8C2B9B20E18e86d5b9a72370fC6c91814c97C; + +/** + * @dev The address of the timelock + */ +address constant zkBobTimelock = 0xbe7D4E55D80fC3e67D80ebf988eB0E551cCA4eB7; + +/** + * @dev Don't forget to set ZkBobPool.TOKEN_NUMERATOR to 1000 for USDC pools. + */ +contract PreMigrateAccounting is Script { + function run() external { + ZkBobPoolUSDC pool = ZkBobPoolUSDC(address(zkBobPool)); + + vm.startBroadcast(); + + // 1. Deploy new ZkBobPoolUSDC implementation + ZkBobPoolUSDC newImpl = new ZkBobPoolUSDC( + pool.pool_id(), + pool.token(), + pool.transfer_verifier(), + pool.tree_verifier(), + pool.batch_deposit_verifier(), + address(pool.direct_deposit_queue()) + ); + + // 2. Deploy new ZkBobAccounting implementation + ZkBobAccounting accounting = new ZkBobAccounting(address(pool), 1_000_000_000); + + // 3. Set timelock as the owner of the accounting + accounting.transferOwnership(zkBobTimelock); + + // 4. Deploy one-time Migrator + AccountingMigrator migrator = new AccountingMigrator(); + + vm.stopBroadcast(); + + assert(accounting.owner() == zkBobTimelock); + + console.log("ZkBobPool implementation:", address(newImpl)); + console.log("ZkBobAccounting: ", address(accounting)); + console.log("AccountingMigrator: ", address(migrator)); + } +} diff --git a/script/scripts/helpers/AccountingMigrator.sol b/script/scripts/helpers/AccountingMigrator.sol new file mode 100644 index 0000000..024b152 --- /dev/null +++ b/script/scripts/helpers/AccountingMigrator.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: CC0-1.0 + +pragma solidity 0.8.15; + +import {ZkBobPool} from "../../../src/zkbob/ZkBobPoolUSDC.sol"; +import {IZkBobAccounting, IKycProvidersManager, ZkBobAccounting} from "../../../src/zkbob/utils/ZkBobAccounting.sol"; +import {EIP1967Proxy} from "../../../src/proxy/EIP1967Proxy.sol"; + +contract AccountingMigrator { + constructor() {} + + // TODO: Check limits + function migrate( + address _pool, + address _accounting, + address _kycManager, + address _accountingOwner, + address _proxyAdmin + ) + external + { + ZkBobAccounting accounting = ZkBobAccounting(_accounting); + + bytes memory dump = ZkBobPool(_pool).extsload(bytes32(uint256(1)), 2); + uint32 txCount = uint32(_load(dump, 0, 4)); + uint88 cumTvl = uint88(_load(dump, 4, 11)); + uint32 maxWeeklyTxCount = uint32(_load(dump, 21, 4)); + uint56 maxWeeklyAvgTvl = uint56(_load(dump, 25, 7)); + uint72 tvl = uint72(_load(dump, 55, 9)); + + ZkBobPool(_pool).initializePoolIndex(txCount * 128); + ZkBobPool(_pool).setAccounting(IZkBobAccounting(accounting)); + + accounting.initialize(txCount, tvl, cumTvl, maxWeeklyTxCount, maxWeeklyAvgTvl); + accounting.setKycProvidersManager(IKycProvidersManager(_kycManager)); + accounting.setLimits( + 0, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 10_000 gwei, 10_000 gwei, 10_000 gwei, 1_000 gwei + ); + accounting.setLimits( + 1, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 100_000 gwei, 100_000 gwei, 10_000 gwei, 1_000 gwei + ); + accounting.setLimits( + 254, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 20_000 gwei, 20_000 gwei, 10_000 gwei, 1_000 gwei + ); + + accounting.transferOwnership(_accountingOwner); + EIP1967Proxy(payable(address(_pool))).setAdmin(_proxyAdmin); + } + + function _load(bytes memory _dump, uint256 _from, uint256 _len) internal pure returns (uint256 res) { + assembly { + res := shr(sub(256, shl(3, _len)), mload(add(_dump, add(32, _from)))) + } + } +} From f2dfdcda07153b8835ec7cb8d35d366e23563cd6 Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Wed, 19 Jun 2024 18:29:28 +0300 Subject: [PATCH 4/6] Fix formatting --- script/scripts/MigrateAccounting.s.sol | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/script/scripts/MigrateAccounting.s.sol b/script/scripts/MigrateAccounting.s.sol index 47521a9..f60f79b 100644 --- a/script/scripts/MigrateAccounting.s.sol +++ b/script/scripts/MigrateAccounting.s.sol @@ -106,24 +106,17 @@ contract MigrateAccounting is Script, UpgradeTest { PoolSnapshot memory snapshot = makeSnapshot(pool); vm.startBroadcast(); - + EIP1967Proxy(payable(address(pool))).upgradeTo(address(newZkBobPoolImpl)); - + EIP1967Proxy(payable(address(pool))).setAdmin(accountingMigrator); - + ZkBobAccounting(zkBobAccounting).transferOwnership(accountingMigrator); - migrator.migrate( - address(pool), - zkBobAccounting, - snapshot.kycManager, - accountingOwner, - snapshot.proxyAdmin - ); + migrator.migrate(address(pool), zkBobAccounting, snapshot.kycManager, accountingOwner, snapshot.proxyAdmin); vm.stopBroadcast(); postCheck(ZkBobPoolUSDC(address(pool)), snapshot); } } - From 4514d209fc8b1e08ab105ac881f79918bae8aa83 Mon Sep 17 00:00:00 2001 From: Alexander Filippov Date: Wed, 19 Jun 2024 18:56:47 +0300 Subject: [PATCH 5/6] Refactor scripts --- ...rator.sol => DeployAccountingMigrator.s.sol} | 17 ++++++++++++++--- ...l => DeployZkBobPoolImplAndAccounting.s.sol} | 7 +------ script/scripts/MigrateAccounting.s.sol | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) rename script/scripts/{helpers/AccountingMigrator.sol => DeployAccountingMigrator.s.sol} (78%) rename script/scripts/{PreMigrateAccounting.s.sol => DeployZkBobPoolImplAndAccounting.s.sol} (85%) diff --git a/script/scripts/helpers/AccountingMigrator.sol b/script/scripts/DeployAccountingMigrator.s.sol similarity index 78% rename from script/scripts/helpers/AccountingMigrator.sol rename to script/scripts/DeployAccountingMigrator.s.sol index 024b152..7f31be3 100644 --- a/script/scripts/helpers/AccountingMigrator.sol +++ b/script/scripts/DeployAccountingMigrator.s.sol @@ -2,9 +2,10 @@ pragma solidity 0.8.15; -import {ZkBobPool} from "../../../src/zkbob/ZkBobPoolUSDC.sol"; -import {IZkBobAccounting, IKycProvidersManager, ZkBobAccounting} from "../../../src/zkbob/utils/ZkBobAccounting.sol"; -import {EIP1967Proxy} from "../../../src/proxy/EIP1967Proxy.sol"; +import {console, Script} from "forge-std/Script.sol"; +import {ZkBobPool, ZkBobPoolUSDC} from "../../src/zkbob/ZkBobPoolUSDC.sol"; +import {IZkBobAccounting, IKycProvidersManager, ZkBobAccounting} from "../../src/zkbob/utils/ZkBobAccounting.sol"; +import {EIP1967Proxy} from "../../src/proxy/EIP1967Proxy.sol"; contract AccountingMigrator { constructor() {} @@ -53,3 +54,13 @@ contract AccountingMigrator { } } } + +contract DeployAccountingMigrator is Script { + function run() external { + vm.startBroadcast(); + AccountingMigrator migrator = new AccountingMigrator(); + vm.stopBroadcast(); + + console.log("AccountingMigrator: ", address(migrator)); + } +} diff --git a/script/scripts/PreMigrateAccounting.s.sol b/script/scripts/DeployZkBobPoolImplAndAccounting.s.sol similarity index 85% rename from script/scripts/PreMigrateAccounting.s.sol rename to script/scripts/DeployZkBobPoolImplAndAccounting.s.sol index 6af239a..c123516 100644 --- a/script/scripts/PreMigrateAccounting.s.sol +++ b/script/scripts/DeployZkBobPoolImplAndAccounting.s.sol @@ -6,7 +6,6 @@ import {console, Script} from "forge-std/Script.sol"; import {ZkBobPoolUSDC} from "../../src/zkbob/ZkBobPoolUSDC.sol"; import {ZkBobAccounting} from "../../src/zkbob/utils/ZkBobAccounting.sol"; import {EIP1967Proxy} from "../../src/proxy/EIP1967Proxy.sol"; -import {AccountingMigrator} from "./helpers/AccountingMigrator.sol"; /** * @dev OP-USDC pool proxy address. @@ -21,7 +20,7 @@ address constant zkBobTimelock = 0xbe7D4E55D80fC3e67D80ebf988eB0E551cCA4eB7; /** * @dev Don't forget to set ZkBobPool.TOKEN_NUMERATOR to 1000 for USDC pools. */ -contract PreMigrateAccounting is Script { +contract DeployZkBobPoolImplAndAccounting is Script { function run() external { ZkBobPoolUSDC pool = ZkBobPoolUSDC(address(zkBobPool)); @@ -43,15 +42,11 @@ contract PreMigrateAccounting is Script { // 3. Set timelock as the owner of the accounting accounting.transferOwnership(zkBobTimelock); - // 4. Deploy one-time Migrator - AccountingMigrator migrator = new AccountingMigrator(); - vm.stopBroadcast(); assert(accounting.owner() == zkBobTimelock); console.log("ZkBobPool implementation:", address(newImpl)); console.log("ZkBobAccounting: ", address(accounting)); - console.log("AccountingMigrator: ", address(migrator)); } } diff --git a/script/scripts/MigrateAccounting.s.sol b/script/scripts/MigrateAccounting.s.sol index f60f79b..b70c072 100644 --- a/script/scripts/MigrateAccounting.s.sol +++ b/script/scripts/MigrateAccounting.s.sol @@ -7,7 +7,7 @@ import {Test} from "forge-std/Test.sol"; import {ZkBobPool, ZkBobPoolUSDC} from "../../src/zkbob/ZkBobPoolUSDC.sol"; import {IZkBobAccounting, IKycProvidersManager, ZkBobAccounting} from "../../src/zkbob/utils/ZkBobAccounting.sol"; import {EIP1967Proxy} from "../../src/proxy/EIP1967Proxy.sol"; -import {AccountingMigrator} from "./helpers/AccountingMigrator.sol"; +import {AccountingMigrator} from "./DeployAccountingMigrator.s.sol"; // WARN: Update this values before running the script address constant newZkBobPoolImpl = 0xD217AEf4aB37F7CeE7462d25cbD91f46c1E688a9; From f97e6989cffe9274a6df7471c1d676440da9fe97 Mon Sep 17 00:00:00 2001 From: Kirill Fedoseev Date: Mon, 1 Jul 2024 12:43:41 +0400 Subject: [PATCH 6/6] feat: deployed migrator --- script/scripts/DeployAccountingMigrator.s.sol | 19 +++---------------- script/scripts/MigrateAccounting.s.sol | 10 +++++----- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/script/scripts/DeployAccountingMigrator.s.sol b/script/scripts/DeployAccountingMigrator.s.sol index 7f31be3..4871042 100644 --- a/script/scripts/DeployAccountingMigrator.s.sol +++ b/script/scripts/DeployAccountingMigrator.s.sol @@ -10,16 +10,7 @@ import {EIP1967Proxy} from "../../src/proxy/EIP1967Proxy.sol"; contract AccountingMigrator { constructor() {} - // TODO: Check limits - function migrate( - address _pool, - address _accounting, - address _kycManager, - address _accountingOwner, - address _proxyAdmin - ) - external - { + function migrate(address _pool, address _accounting, address _accountingOwner, address _proxyAdmin) external { ZkBobAccounting accounting = ZkBobAccounting(_accounting); bytes memory dump = ZkBobPool(_pool).extsload(bytes32(uint256(1)), 2); @@ -33,15 +24,11 @@ contract AccountingMigrator { ZkBobPool(_pool).setAccounting(IZkBobAccounting(accounting)); accounting.initialize(txCount, tvl, cumTvl, maxWeeklyTxCount, maxWeeklyAvgTvl); - accounting.setKycProvidersManager(IKycProvidersManager(_kycManager)); accounting.setLimits( - 0, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 10_000 gwei, 10_000 gwei, 10_000 gwei, 1_000 gwei + 0, 10_000_000 gwei, 300_000 gwei, 300_000 gwei, 10_000 gwei, 10_000 gwei, 10_000 gwei, 1_000 gwei ); accounting.setLimits( - 1, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 100_000 gwei, 100_000 gwei, 10_000 gwei, 1_000 gwei - ); - accounting.setLimits( - 254, 2_000_000 gwei, 300_000 gwei, 300_000 gwei, 20_000 gwei, 20_000 gwei, 10_000 gwei, 1_000 gwei + 1, 10_000_000 gwei, 300_000 gwei, 300_000 gwei, 100_000 gwei, 100_000 gwei, 10_000 gwei, 1_000 gwei ); accounting.transferOwnership(_accountingOwner); diff --git a/script/scripts/MigrateAccounting.s.sol b/script/scripts/MigrateAccounting.s.sol index b70c072..239a916 100644 --- a/script/scripts/MigrateAccounting.s.sol +++ b/script/scripts/MigrateAccounting.s.sol @@ -10,9 +10,9 @@ import {EIP1967Proxy} from "../../src/proxy/EIP1967Proxy.sol"; import {AccountingMigrator} from "./DeployAccountingMigrator.s.sol"; // WARN: Update this values before running the script -address constant newZkBobPoolImpl = 0xD217AEf4aB37F7CeE7462d25cbD91f46c1E688a9; -address constant zkBobAccounting = 0xFd5a6a67D768d5BF1A8c7724387CA8786Bd4DD91; -address constant accountingMigrator = 0x0114Bf30d9f5A7f503D3DFC65534F2B5AC302c85; +address constant newZkBobPoolImpl = 0x84605eA206A1d5b39f13dC7add690dbD1e038525; +address constant zkBobAccounting = 0xbF3D58f026642951990C0421964179C83E2c9C1B; +address constant accountingMigrator = 0xbfF0020638011357315302727eD55C5193a95F7b; address constant accountingOwner = 0x14fc6a1a996A2EB889cF86e5c8cD17323bC85290; /** @@ -105,7 +105,7 @@ contract MigrateAccounting is Script, UpgradeTest { AccountingMigrator migrator = AccountingMigrator(accountingMigrator); PoolSnapshot memory snapshot = makeSnapshot(pool); - vm.startBroadcast(); + vm.startBroadcast(snapshot.proxyAdmin); EIP1967Proxy(payable(address(pool))).upgradeTo(address(newZkBobPoolImpl)); @@ -113,7 +113,7 @@ contract MigrateAccounting is Script, UpgradeTest { ZkBobAccounting(zkBobAccounting).transferOwnership(accountingMigrator); - migrator.migrate(address(pool), zkBobAccounting, snapshot.kycManager, accountingOwner, snapshot.proxyAdmin); + migrator.migrate(address(pool), zkBobAccounting, accountingOwner, snapshot.proxyAdmin); vm.stopBroadcast();