Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accounting migration #102

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
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
53 changes: 53 additions & 0 deletions script/scripts/DeployAccountingMigrator.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: CC0-1.0

pragma solidity 0.8.15;

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() {}

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);
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.setLimits(
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, 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);
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))))
}
}
}

contract DeployAccountingMigrator is Script {
function run() external {
vm.startBroadcast();
AccountingMigrator migrator = new AccountingMigrator();
vm.stopBroadcast();

console.log("AccountingMigrator: ", address(migrator));
}
}
52 changes: 52 additions & 0 deletions script/scripts/DeployZkBobPoolImplAndAccounting.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// 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";

/**
* @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 DeployZkBobPoolImplAndAccounting 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);

vm.stopBroadcast();

assert(accounting.owner() == zkBobTimelock);

console.log("ZkBobPool implementation:", address(newImpl));
console.log("ZkBobAccounting: ", address(accounting));
}
}
85 changes: 0 additions & 85 deletions script/scripts/DeployZkBobPoolModules.s.sol

This file was deleted.

7 changes: 1 addition & 6 deletions script/scripts/Local.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
122 changes: 122 additions & 0 deletions script/scripts/MigrateAccounting.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// 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";
import {AccountingMigrator} from "./DeployAccountingMigrator.s.sol";

// WARN: Update this values before running the script
address constant newZkBobPoolImpl = 0x84605eA206A1d5b39f13dC7add690dbD1e038525;
address constant zkBobAccounting = 0xbF3D58f026642951990C0421964179C83E2c9C1B;
address constant accountingMigrator = 0xbfF0020638011357315302727eD55C5193a95F7b;
address constant accountingOwner = 0x14fc6a1a996A2EB889cF86e5c8cD17323bC85290;

/**
* @dev OP-USDC pool proxy address.
*/
address constant zkBobPool = 0x1CA8C2B9B20E18e86d5b9a72370fC6c91814c97C;

// 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;
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({
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))),
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.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));
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));
AccountingMigrator migrator = AccountingMigrator(accountingMigrator);
PoolSnapshot memory snapshot = makeSnapshot(pool);

vm.startBroadcast(snapshot.proxyAdmin);

EIP1967Proxy(payable(address(pool))).upgradeTo(address(newZkBobPoolImpl));

EIP1967Proxy(payable(address(pool))).setAdmin(accountingMigrator);

ZkBobAccounting(zkBobAccounting).transferOwnership(accountingMigrator);

migrator.migrate(address(pool), zkBobAccounting, accountingOwner, snapshot.proxyAdmin);

vm.stopBroadcast();

postCheck(ZkBobPoolUSDC(address(pool)), snapshot);
}
}
28 changes: 16 additions & 12 deletions script/scripts/ZkBobPool.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/IZkBobDirectDeposits.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading
Loading