From 8321b10f5724b5cc694d494a2358fdaa93354478 Mon Sep 17 00:00:00 2001 From: Rayerleier <1045643889@qq.com> Date: Tue, 26 Nov 2024 18:26:26 +0800 Subject: [PATCH] still progressing --- lib/openzeppelin-contracts | 1 - src/iBTC_NetworkMiddleware.sol | 72 +++++++++++++++++++++++-------- src/iBTC_Vault.sol | 32 ++++++++++---- src/iBTC_VaultConfigurator.sol | 4 +- test/iBTC_NetworkMiddleware.t.sol | 61 ++++++++------------------ 5 files changed, 99 insertions(+), 71 deletions(-) delete mode 160000 lib/openzeppelin-contracts diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts deleted file mode 160000 index 2f0bc58..0000000 --- a/lib/openzeppelin-contracts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2f0bc58946db746c0d17a2b9d9a8e13f5a8edd7f diff --git a/src/iBTC_NetworkMiddleware.sol b/src/iBTC_NetworkMiddleware.sol index 3806df9..7e0cbbb 100644 --- a/src/iBTC_NetworkMiddleware.sol +++ b/src/iBTC_NetworkMiddleware.sol @@ -66,7 +66,9 @@ contract NetworkMiddleware is SimpleKeyRegistry32, Ownable { EnumerableMap.AddressToUintMap private operators; EnumerableMap.AddressToUintMap private vaults; - modifier updateStakeCache(uint48 epoch) { + modifier updateStakeCache( + uint48 epoch + ) { if (!totalStakeCached[epoch]) { calcAndCacheStakes(epoch); } @@ -96,28 +98,40 @@ contract NetworkMiddleware is SimpleKeyRegistry32, Ownable { SLASHING_WINDOW = _slashingWindow; } - function getEpochStartTs(uint48 epoch) public view returns (uint48 timestamp) { + function getEpochStartTs( + uint48 epoch + ) public view returns (uint48 timestamp) { return START_TIME + epoch * EPOCH_DURATION; } - function getEpochAtTs(uint48 timestamp) public view returns (uint48 epoch) { + function getEpochAtTs( + uint48 timestamp + ) public view returns (uint48 epoch) { return (timestamp - START_TIME) / EPOCH_DURATION; } - function isOperatorRegistered(address operator) public view returns (bool) { + function isOperatorRegistered( + address operator + ) public view returns (bool) { return operators.contains(operator); } - function getOperatorInfo(address operator) public view returns (uint48, uint48) { + function getOperatorInfo( + address operator + ) public view returns (uint48, uint48) { (uint48 enabledTime, uint48 disabledTime) = operators.getTimes(operator); return (enabledTime, disabledTime); } - function isVaultRegistered(address vault) public view returns (bool) { + function isVaultRegistered( + address vault + ) public view returns (bool) { return vaults.contains(vault); } - function getVaultInfo(address vault) public view returns (uint48, uint48) { + function getVaultInfo( + address vault + ) public view returns (uint48, uint48) { (uint48 enabledTime, uint48 disabledTime) = vaults.getTimes(vault); return (enabledTime, disabledTime); } @@ -153,15 +167,21 @@ contract NetworkMiddleware is SimpleKeyRegistry32, Ownable { updateKey(operator, key); } - function pauseOperator(address operator) external onlyOwner { + function pauseOperator( + address operator + ) external onlyOwner { operators.disable(operator); } - function unpauseOperator(address operator) external onlyOwner { + function unpauseOperator( + address operator + ) external onlyOwner { operators.enable(operator); } - function unregisterOperator(address operator) external onlyOwner { + function unregisterOperator( + address operator + ) external onlyOwner { (, uint48 disabledTime) = operators.getTimes(operator); if (disabledTime == 0 || disabledTime + SLASHING_WINDOW > Time.timestamp()) { @@ -171,7 +191,9 @@ contract NetworkMiddleware is SimpleKeyRegistry32, Ownable { operators.remove(operator); } - function registerVault(address vault) external onlyOwner { + function registerVault( + address vault + ) external onlyOwner { if (vaults.contains(vault)) { revert VaultAlreadyRegistred(); } @@ -195,15 +217,21 @@ contract NetworkMiddleware is SimpleKeyRegistry32, Ownable { vaults.enable(vault); } - function pauseVault(address vault) external onlyOwner { + function pauseVault( + address vault + ) external onlyOwner { vaults.disable(vault); } - function unpauseVault(address vault) external onlyOwner { + function unpauseVault( + address vault + ) external onlyOwner { vaults.enable(vault); } - function unregisterVault(address vault) external onlyOwner { + function unregisterVault( + address vault + ) external onlyOwner { (, uint48 disabledTime) = vaults.getTimes(vault); if (disabledTime == 0 || disabledTime + SLASHING_WINDOW > Time.timestamp()) { @@ -235,14 +263,18 @@ contract NetworkMiddleware is SimpleKeyRegistry32, Ownable { return stake; } - function getTotalStake(uint48 epoch) public view returns (uint256) { + function getTotalStake( + uint48 epoch + ) public view returns (uint256) { if (totalStakeCached[epoch]) { return totalStakeCache[epoch]; } return _calcTotalStake(epoch); } - function getValidatorSet(uint48 epoch) public view returns (ValidatorData[] memory validatorsData) { + function getValidatorSet( + uint48 epoch + ) public view returns (ValidatorData[] memory validatorsData) { uint48 epochStartTs = getEpochStartTs(epoch); validatorsData = new ValidatorData[](operators.length()); @@ -309,7 +341,9 @@ contract NetworkMiddleware is SimpleKeyRegistry32, Ownable { } } - function calcAndCacheStakes(uint48 epoch) public returns (uint256 totalStake) { + function calcAndCacheStakes( + uint48 epoch + ) public returns (uint256 totalStake) { uint48 epochStartTs = getEpochStartTs(epoch); // for epoch older than SLASHING_WINDOW total stake can be invalidated (use cache) @@ -339,7 +373,9 @@ contract NetworkMiddleware is SimpleKeyRegistry32, Ownable { totalStakeCache[epoch] = totalStake; } - function _calcTotalStake(uint48 epoch) private view returns (uint256 totalStake) { + function _calcTotalStake( + uint48 epoch + ) private view returns (uint256 totalStake) { uint48 epochStartTs = getEpochStartTs(epoch); // for epoch older than SLASHING_WINDOW total stake can be invalidated (use cache) diff --git a/src/iBTC_Vault.sol b/src/iBTC_Vault.sol index 19e7f6e..5d58e47 100644 --- a/src/iBTC_Vault.sol +++ b/src/iBTC_Vault.sol @@ -62,7 +62,9 @@ contract iBTC_Vault is VaultStorage, MigratableEntity, AccessControlUpgradeable, /** * @inheritdoc IVault */ - function activeBalanceOf(address account) public view returns (uint256) { + function activeBalanceOf( + address account + ) public view returns (uint256) { return ERC4626Math.previewRedeem(activeSharesOf(account), activeStake(), activeShares()); } @@ -77,7 +79,9 @@ contract iBTC_Vault is VaultStorage, MigratableEntity, AccessControlUpgradeable, /** * @inheritdoc IVault */ - function slashableBalanceOf(address account) external view returns (uint256) { + function slashableBalanceOf( + address account + ) external view returns (uint256) { uint256 epoch = currentEpoch(); return activeBalanceOf(account) + withdrawalsOf(epoch, account) + withdrawalsOf(epoch + 1, account); } @@ -262,7 +266,9 @@ contract iBTC_Vault is VaultStorage, MigratableEntity, AccessControlUpgradeable, /** * @inheritdoc IVault */ - function setDepositWhitelist(bool status) external nonReentrant onlyRole(DEPOSIT_WHITELIST_SET_ROLE) { + function setDepositWhitelist( + bool status + ) external nonReentrant onlyRole(DEPOSIT_WHITELIST_SET_ROLE) { if (depositWhitelist == status) { revert AlreadySet(); } @@ -295,7 +301,9 @@ contract iBTC_Vault is VaultStorage, MigratableEntity, AccessControlUpgradeable, /** * @inheritdoc IVault */ - function setIsDepositLimit(bool status) external nonReentrant onlyRole(IS_DEPOSIT_LIMIT_SET_ROLE) { + function setIsDepositLimit( + bool status + ) external nonReentrant onlyRole(IS_DEPOSIT_LIMIT_SET_ROLE) { if (isDepositLimit == status) { revert AlreadySet(); } @@ -308,7 +316,9 @@ contract iBTC_Vault is VaultStorage, MigratableEntity, AccessControlUpgradeable, /** * @inheritdoc IVault */ - function setDepositLimit(uint256 limit) external nonReentrant onlyRole(DEPOSIT_LIMIT_SET_ROLE) { + function setDepositLimit( + uint256 limit + ) external nonReentrant onlyRole(DEPOSIT_LIMIT_SET_ROLE) { if (depositLimit == limit) { revert AlreadySet(); } @@ -318,7 +328,9 @@ contract iBTC_Vault is VaultStorage, MigratableEntity, AccessControlUpgradeable, emit SetDepositLimit(limit); } - function setDelegator(address delegator_) external nonReentrant { + function setDelegator( + address delegator_ + ) external nonReentrant { if (isDelegatorInitialized) { revert DelegatorAlreadyInitialized(); } @@ -338,7 +350,9 @@ contract iBTC_Vault is VaultStorage, MigratableEntity, AccessControlUpgradeable, emit SetDelegator(delegator_); } - function setSlasher(address slasher_) external nonReentrant { + function setSlasher( + address slasher_ + ) external nonReentrant { if (isSlasherInitialized) { revert SlasherAlreadyInitialized(); } @@ -382,7 +396,9 @@ contract iBTC_Vault is VaultStorage, MigratableEntity, AccessControlUpgradeable, emit Withdraw(msg.sender, claimer, withdrawnAssets, burnedShares, mintedShares); } - function _claim(uint256 epoch) internal returns (uint256 amount) { + function _claim( + uint256 epoch + ) internal returns (uint256 amount) { if (epoch >= currentEpoch()) { revert InvalidEpoch(); } diff --git a/src/iBTC_VaultConfigurator.sol b/src/iBTC_VaultConfigurator.sol index b87025e..9cd380e 100644 --- a/src/iBTC_VaultConfigurator.sol +++ b/src/iBTC_VaultConfigurator.sol @@ -34,7 +34,9 @@ contract VaultConfigurator is IVaultConfigurator { /** * @inheritdoc IVaultConfigurator */ - function create(InitParams memory params) public returns (address vault, address delegator, address slasher) { + function create( + InitParams memory params + ) public returns (address vault, address delegator, address slasher) { vault = VaultFactory(VAULT_FACTORY).create(params.version, params.owner, params.vaultParams); delegator = diff --git a/test/iBTC_NetworkMiddleware.t.sol b/test/iBTC_NetworkMiddleware.t.sol index 54295ff..72d6a7f 100644 --- a/test/iBTC_NetworkMiddleware.t.sol +++ b/test/iBTC_NetworkMiddleware.t.sol @@ -15,32 +15,30 @@ import {IBaseDelegator} from "core/src/interfaces/delegator/IBaseDelegator.sol"; import {IVetoSlasher} from "core/src/interfaces/slasher/IVetoSlasher.sol"; import {IBaseSlasher} from "core/src/interfaces/slasher/IBaseSlasher.sol"; import {IVaultConfigurator} from "core/src/interfaces/IVaultConfigurator.sol"; +import {IRegistry} from "core/src/interfaces/common/IRegistry.sol"; contract iBTC_NetworkMiddlewareTest is Test { - // sepolia address constant NETWORKMIDDLEWARESERVICE = 0x62a1ddfD86b4c1636759d9286D3A0EC722D086e3; address constant NETWORKREGISTRY = 0x7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9; address constant OPERATOR_REGISTRY = 0x6F75a4ffF97326A00e52662d82EA4FdE86a2C548; address constant NETWORK_REGISTRY = 0x7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9; address constant NETWORK_OPTIN = 0x58973d16FFA900D11fC22e5e2B6840d9f7e13401; - address constant COLLATTERAL = 0xeb762Ed11a09E4A394C9c8101f8aeeaf5382ED74; // iBTC on sepolia + address constant COLLATTERAL = 0xeb762Ed11a09E4A394C9c8101f8aeeaf5382ED74; address constant VAULT_FACTORY = 0x407A039D94948484D356eFB765b3c74382A050B4; address constant DELEGATOR_FACTORY = 0x890CA3f95E0f40a79885B7400926544B2214B03f; address constant SLASHER_FACTORY = 0xbf34bf75bb779c383267736c53a4ae86ac7bB299; - uint256 constant MAX_WITHDRAW_AMOUNT = 1e9; // 10 iBTC + uint256 constant MAX_WITHDRAW_AMOUNT = 1e9; uint256 constant MIN_WITHDRAW_AMOUNT = 1e4; - // Using anvil's default addresses - address constant NETWORK = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; // first address - address constant OWNER = 0x70997970C51812dc3A010C7d01b50e0d17dc79C8; // second address + address constant NETWORK = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; + address constant OWNER = 0x70997970C51812dc3A010C7d01b50e0d17dc79C8; uint48 constant EPOCH_DURATION = 7 days; - uint48 constant SLASHING_WINDOW = 8 days; + uint48 constant SLASHING_WINDOW = 7 days; + uint48 vetoDuration = 0 days; - // Initial operators and their keys (if any) address[] operators; bytes32[] keys; - // Initial vaults (if any) address[] vaults; NetworkMiddleware public iBTC_middleware; @@ -51,14 +49,13 @@ contract iBTC_NetworkMiddlewareTest is Test { function setUp() public { address[] memory whitelistedDepositors; - uint256 depositLimit = 1e10; // 100iBTC + uint256 depositLimit = 1e10; address hook = 0x0000000000000000000000000000000000000000; - uint64 delegatorIndex = 0; // NetworkRestakeDelegator - uint64 slasherIndex = 1; // vetoSlasher + uint64 delegatorIndex = 0; + uint64 slasherIndex = 1; bool withSlasher = true; - uint48 vetoDuration = 86_400; // 1 day vm.startPrank(OWNER); - // iBTC_vault deployment Starts + vaultConfigurator = new VaultConfigurator(VAULT_FACTORY, DELEGATOR_FACTORY, SLASHER_FACTORY); burner = new BurnerRouter(); (,, address deployer) = vm.readCallers(); @@ -88,7 +85,6 @@ contract iBTC_NetworkMiddlewareTest is Test { operatorNetworkLimitSetRoleHolders[0] = OWNER; operatorNetworkSharesSetRoleHolders[0] = OWNER; bytes memory delegatorParams; - // delegator = 0,NetworkRestakeDelegator delegatorParams = abi.encode( INetworkRestakeDelegator.InitParams({ baseParams: IBaseDelegator.BaseParams({defaultAdminRoleHolder: OWNER, hook: hook, hookSetRoleHolder: OWNER}), @@ -97,7 +93,6 @@ contract iBTC_NetworkMiddlewareTest is Test { }) ); bytes memory slasherParams; - // slasherIndex =1, VetoSlash slasherParams = abi.encode( IVetoSlasher.InitParams({ baseParams: IBaseSlasher.BaseParams({isBurnerHook: address(burner) != address(0)}), @@ -129,9 +124,13 @@ contract iBTC_NetworkMiddlewareTest is Test { iBTC_Vault(vault_).renounceRole(iBTC_Vault(vault_).DEPOSITOR_WHITELIST_ROLE(), deployer); iBTC_Vault(vault_).renounceRole(iBTC_Vault(vault_).DEFAULT_ADMIN_ROLE(), deployer); } - // vault delpoymend ends + vm.stopPrank(); + vm.startPrank(vault_); + NetworkRegistry(NETWORK_REGISTRY).registerNetwork(); + vm.stopPrank(); vaults.push(vault_); + vm.startPrank(OWNER); iBTC_middleware = new NetworkMiddleware( NETWORK, OPERATOR_REGISTRY, NETWORK_REGISTRY, NETWORK_OPTIN, OWNER, EPOCH_DURATION, SLASHING_WINDOW ); @@ -159,13 +158,10 @@ contract iBTC_NetworkMiddlewareTest is Test { address operator = address(0x1234); bytes32 key = keccak256(abi.encodePacked("operator_key")); - // 注册操作员 iBTC_middleware.registerOperator(operator, key); - // 获取启用时间和禁用时间 (uint48 enabledTime, uint48 disabledTime) = iBTC_middleware.getOperatorInfo(operator); - // 验证操作员已经注册 assertTrue(enabledTime > 0, "Enabled time should be greater than 0"); assertTrue(disabledTime == 0, "Disabled time should be 0"); @@ -175,21 +171,16 @@ contract iBTC_NetworkMiddlewareTest is Test { function testUnregisterOperator() public { vm.startPrank(OWNER); - // 假设有一个操作员 address operator = address(0x1234); bytes32 key = keccak256(abi.encodePacked("operator_key")); - // 注册操作员 iBTC_middleware.registerOperator(operator, key); - // 暂停操作员 iBTC_middleware.pauseOperator(operator); - // 尝试取消注册操作员 - vm.warp(block.timestamp + SLASHING_WINDOW + 1); // 模拟时间推进 + vm.warp(block.timestamp + SLASHING_WINDOW + 1); iBTC_middleware.unregisterOperator(operator); - // 验证操作员已被移除 bool isOperatorRegistered = iBTC_middleware.isOperatorRegistered(operator); assertFalse(isOperatorRegistered, "Operator should be unregistered"); @@ -199,13 +190,10 @@ contract iBTC_NetworkMiddlewareTest is Test { function testRegisterVault() public { vm.startPrank(OWNER); - // 假设有一个Vault地址 address vault = address(0x7890); - // 注册Vault iBTC_middleware.registerVault(vault); - // 验证Vault已经注册 bool isVaultRegistered = iBTC_middleware.isVaultRegistered(vault); assertTrue(isVaultRegistered, "Vault should be registered"); @@ -215,25 +203,19 @@ contract iBTC_NetworkMiddlewareTest is Test { function testPauseAndUnpauseVault() public { vm.startPrank(OWNER); - // 假设有一个Vault地址 address vault = address(0x7890); - // 注册Vault iBTC_middleware.registerVault(vault); - // 暂停Vault iBTC_middleware.pauseVault(vault); - // 验证Vault已暂停 (uint48 enabledTime, uint48 disabledTime) = iBTC_middleware.getVaultInfo(vault); bool isVaultPaused = enabledTime == 0 || (disabledTime > 0 && disabledTime <= block.timestamp); assertTrue(isVaultPaused, "Vault should be paused"); - // 恢复Vault iBTC_middleware.unpauseVault(vault); - // 验证Vault已恢复 (enabledTime, disabledTime) = iBTC_middleware.getVaultInfo(vault); isVaultPaused = enabledTime == 0 || (disabledTime > 0 && disabledTime <= block.timestamp); assertFalse(isVaultPaused, "Vault should be active"); @@ -244,33 +226,26 @@ contract iBTC_NetworkMiddlewareTest is Test { function testSlashOperator() public { vm.startPrank(OWNER); - // 假设有一个操作员和一个Vault address operator = address(0x1234); bytes32 key = keccak256(abi.encodePacked("operator_key")); address vault = address(0x7890); - // 注册操作员和Vault iBTC_middleware.registerOperator(operator, key); iBTC_middleware.registerVault(vault); - // 假设某个epoch中stake为1000 uint48 epoch = iBTC_middleware.getCurrentEpoch(); uint256 initialStake = 1000; - // 模拟缓存 Stake 值,通过合约方法完成 - vm.startPrank(address(iBTC_middleware)); // 以合约身份操作缓存更新 + vm.startPrank(address(iBTC_middleware)); iBTC_middleware.calcAndCacheStakes(epoch); vm.stopPrank(); - // 查询缓存的Stake值 uint256 cachedStake = iBTC_middleware.operatorStakeCache(epoch, operator); assertEq(cachedStake, initialStake, "Cached stake should match the initial stake"); - // Slash 操作员 100 uint256 slashAmount = 100; iBTC_middleware.slash(epoch, operator, slashAmount); - // 验证 Stake 减少了 uint256 updatedStake = iBTC_middleware.getOperatorStake(operator, epoch); assertEq(updatedStake, initialStake - slashAmount, "Stake should be reduced by slashed amount");