From 66520b89487fcb3e6d5b6594d92d4e6ab8589d12 Mon Sep 17 00:00:00 2001 From: Rayerleier <1045643889@qq.com> Date: Mon, 25 Nov 2024 16:05:26 +0800 Subject: [PATCH 1/7] iBTC_Vault_test --- lib/openzeppelin-contracts | 1 + src/iBTC_Vault.sol | 32 +- test/iBTC_Vault.t.sol | 2897 ++++++++++++++++++++++++++++++++++++ 3 files changed, 2906 insertions(+), 24 deletions(-) create mode 160000 lib/openzeppelin-contracts create mode 100644 test/iBTC_Vault.t.sol diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts new file mode 160000 index 0000000..2f0bc58 --- /dev/null +++ b/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit 2f0bc58946db746c0d17a2b9d9a8e13f5a8edd7f diff --git a/src/iBTC_Vault.sol b/src/iBTC_Vault.sol index 5d58e47..19e7f6e 100644 --- a/src/iBTC_Vault.sol +++ b/src/iBTC_Vault.sol @@ -62,9 +62,7 @@ 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()); } @@ -79,9 +77,7 @@ 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); } @@ -266,9 +262,7 @@ 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(); } @@ -301,9 +295,7 @@ 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(); } @@ -316,9 +308,7 @@ 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(); } @@ -328,9 +318,7 @@ 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(); } @@ -350,9 +338,7 @@ 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(); } @@ -396,9 +382,7 @@ 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/test/iBTC_Vault.t.sol b/test/iBTC_Vault.t.sol new file mode 100644 index 0000000..7087210 --- /dev/null +++ b/test/iBTC_Vault.t.sol @@ -0,0 +1,2897 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import {Test, console2} from "forge-std/Test.sol"; + +import {VaultFactory} from "core/src/contracts/VaultFactory.sol"; +import {DelegatorFactory} from "core/src/contracts/DelegatorFactory.sol"; +import {SlasherFactory} from "core/src/contracts/SlasherFactory.sol"; +import {NetworkRegistry} from "core/src/contracts/NetworkRegistry.sol"; +import {OperatorRegistry} from "core/src/contracts/OperatorRegistry.sol"; +import {MetadataService} from "core/src/contracts/service/MetadataService.sol"; +import {NetworkMiddlewareService} from "core/src/contracts/service/NetworkMiddlewareService.sol"; +import {OptInService} from "core/src/contracts/service/OptInService.sol"; + +import {iBTC_Vault} from "src/iBTC_Vault.sol"; +import {NetworkRestakeDelegator} from "core/src/contracts/delegator/NetworkRestakeDelegator.sol"; +import {FullRestakeDelegator} from "core/src/contracts/delegator/FullRestakeDelegator.sol"; +import {OperatorSpecificDelegator} from "core/src/contracts/delegator/OperatorSpecificDelegator.sol"; +import {Slasher} from "core/src/contracts/slasher/Slasher.sol"; +import {VetoSlasher} from "core/src/contracts/slasher/VetoSlasher.sol"; + +import {IVault} from "core/src/interfaces/vault/IVault.sol"; + +import {Token} from "core/test/mocks/Token.sol"; +import {FeeOnTransferToken} from "core/test/mocks/FeeOnTransferToken.sol"; +import {VaultConfigurator} from "core/src/contracts/VaultConfigurator.sol"; +import {IVaultConfigurator} from "core/src/interfaces/IVaultConfigurator.sol"; +import {INetworkRestakeDelegator} from "core/src/interfaces/delegator/INetworkRestakeDelegator.sol"; +import {IFullRestakeDelegator} from "core/src/interfaces/delegator/IFullRestakeDelegator.sol"; +import {IBaseDelegator} from "core/src/interfaces/delegator/IBaseDelegator.sol"; +import {ISlasher} from "core/src/interfaces/slasher/ISlasher.sol"; +import {IBaseSlasher} from "core/src/interfaces/slasher/IBaseSlasher.sol"; + +import {IVaultStorage} from "core/src/interfaces/vault/IVaultStorage.sol"; +import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; + +import {VaultHints} from "core/src/contracts/hints/VaultHints.sol"; +import {Subnetwork} from "core/src/contracts/libraries/Subnetwork.sol"; + +contract VaultTest is Test { + using Math for uint256; + using Subnetwork for bytes32; + using Subnetwork for address; + + address owner; + address alice; + uint256 alicePrivateKey; + address bob; + uint256 bobPrivateKey; + + VaultFactory vaultFactory; + DelegatorFactory delegatorFactory; + SlasherFactory slasherFactory; + NetworkRegistry networkRegistry; + OperatorRegistry operatorRegistry; + MetadataService operatorMetadataService; + MetadataService networkMetadataService; + NetworkMiddlewareService networkMiddlewareService; + OptInService operatorVaultOptInService; + OptInService operatorNetworkOptInService; + + Token collateral; + FeeOnTransferToken feeOnTransferCollateral; + VaultConfigurator vaultConfigurator; + + iBTC_Vault iBTCVault; + FullRestakeDelegator delegator; + Slasher slasher; + + function setUp() public { + owner = address(this); + (alice, alicePrivateKey) = makeAddrAndKey("alice"); + (bob, bobPrivateKey) = makeAddrAndKey("bob"); + + vaultFactory = new VaultFactory(owner); + delegatorFactory = new DelegatorFactory(owner); + slasherFactory = new SlasherFactory(owner); + networkRegistry = new NetworkRegistry(); + operatorRegistry = new OperatorRegistry(); + operatorMetadataService = new MetadataService(address(operatorRegistry)); + networkMetadataService = new MetadataService(address(networkRegistry)); + networkMiddlewareService = new NetworkMiddlewareService(address(networkRegistry)); + operatorVaultOptInService = + new OptInService(address(operatorRegistry), address(vaultFactory), "OperatorVaultOptInService"); + operatorNetworkOptInService = + new OptInService(address(operatorRegistry), address(networkRegistry), "OperatorNetworkOptInService"); + + address vaultImpl = + address(new iBTC_Vault(address(delegatorFactory), address(slasherFactory), address(vaultFactory))); + vaultFactory.whitelist(vaultImpl); + + address networkRestakeDelegatorImpl = address( + new NetworkRestakeDelegator( + address(networkRegistry), + address(vaultFactory), + address(operatorVaultOptInService), + address(operatorNetworkOptInService), + address(delegatorFactory), + delegatorFactory.totalTypes() + ) + ); + delegatorFactory.whitelist(networkRestakeDelegatorImpl); + + address fullRestakeDelegatorImpl = address( + new FullRestakeDelegator( + address(networkRegistry), + address(vaultFactory), + address(operatorVaultOptInService), + address(operatorNetworkOptInService), + address(delegatorFactory), + delegatorFactory.totalTypes() + ) + ); + delegatorFactory.whitelist(fullRestakeDelegatorImpl); + + address operatorSpecificDelegatorImpl = address( + new OperatorSpecificDelegator( + address(operatorRegistry), + address(networkRegistry), + address(vaultFactory), + address(operatorVaultOptInService), + address(operatorNetworkOptInService), + address(delegatorFactory), + delegatorFactory.totalTypes() + ) + ); + delegatorFactory.whitelist(operatorSpecificDelegatorImpl); + + address slasherImpl = address( + new Slasher( + address(vaultFactory), + address(networkMiddlewareService), + address(slasherFactory), + slasherFactory.totalTypes() + ) + ); + slasherFactory.whitelist(slasherImpl); + + address vetoSlasherImpl = address( + new VetoSlasher( + address(vaultFactory), + address(networkMiddlewareService), + address(networkRegistry), + address(slasherFactory), + slasherFactory.totalTypes() + ) + ); + slasherFactory.whitelist(vetoSlasherImpl); + + collateral = new Token("Token"); + feeOnTransferCollateral = new FeeOnTransferToken("FeeOnTransferToken"); + + vaultConfigurator = + new VaultConfigurator(address(vaultFactory), address(delegatorFactory), address(slasherFactory)); + } + + function test_Create2( + address burner, + uint48 epochDuration, + bool depositWhitelist, + bool isDepositLimit, + uint256 depositLimit + ) public { + epochDuration = uint48(bound(epochDuration, 1, 50 weeks)); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + address[] memory networkLimitSetRoleHolders = new address[](1); + networkLimitSetRoleHolders[0] = alice; + address[] memory operatorNetworkSharesSetRoleHolders = new address[](1); + operatorNetworkSharesSetRoleHolders[0] = alice; + (address vault_, address delegator_,) = vaultConfigurator.create( + IVaultConfigurator.InitParams({ + version: vaultFactory.lastVersion(), + owner: address(0), + vaultParams: abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: burner, + epochDuration: epochDuration, + depositWhitelist: depositWhitelist, + isDepositLimit: isDepositLimit, + depositLimit: depositLimit, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ), + delegatorIndex: 0, + delegatorParams: abi.encode( + INetworkRestakeDelegator.InitParams({ + baseParams: IBaseDelegator.BaseParams({ + defaultAdminRoleHolder: alice, + hook: address(0), + hookSetRoleHolder: alice + }), + networkLimitSetRoleHolders: networkLimitSetRoleHolders, + operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders + }) + ), + withSlasher: false, + slasherIndex: 0, + slasherParams: abi.encode(ISlasher.InitParams({baseParams: IBaseSlasher.BaseParams({isBurnerHook: false})})) + }) + ); + + iBTCVault = iBTC_Vault(vault_); + + assertEq(iBTCVault.DEPOSIT_WHITELIST_SET_ROLE(), keccak256("DEPOSIT_WHITELIST_SET_ROLE")); + assertEq(iBTCVault.DEPOSITOR_WHITELIST_ROLE(), keccak256("DEPOSITOR_WHITELIST_ROLE")); + assertEq(iBTCVault.DELEGATOR_FACTORY(), address(delegatorFactory)); + assertEq(iBTCVault.SLASHER_FACTORY(), address(slasherFactory)); + + assertEq(iBTCVault.owner(), address(0)); + assertEq(iBTCVault.collateral(), address(collateral)); + assertEq(iBTCVault.delegator(), delegator_); + assertEq(iBTCVault.slasher(), address(0)); + assertEq(iBTCVault.burner(), burner); + assertEq(iBTCVault.epochDuration(), epochDuration); + assertEq(iBTCVault.depositWhitelist(), depositWhitelist); + assertEq(iBTCVault.hasRole(iBTCVault.DEFAULT_ADMIN_ROLE(), alice), true); + assertEq(iBTCVault.hasRole(iBTCVault.DEPOSITOR_WHITELIST_ROLE(), alice), true); + assertEq(iBTCVault.epochDurationInit(), blockTimestamp); + assertEq(iBTCVault.epochDuration(), epochDuration); + vm.expectRevert(IVaultStorage.InvalidTimestamp.selector); + assertEq(iBTCVault.epochAt(0), 0); + assertEq(iBTCVault.epochAt(uint48(blockTimestamp)), 0); + assertEq(iBTCVault.currentEpoch(), 0); + assertEq(iBTCVault.currentEpochStart(), blockTimestamp); + vm.expectRevert(IVaultStorage.NoPreviousEpoch.selector); + iBTCVault.previousEpochStart(); + assertEq(iBTCVault.nextEpochStart(), blockTimestamp + epochDuration); + assertEq(iBTCVault.totalStake(), 0); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp), ""), 0); + assertEq(iBTCVault.activeShares(), 0); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), ""), 0); + assertEq(iBTCVault.activeStake(), 0); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp), ""), 0); + assertEq(iBTCVault.activeSharesOf(alice), 0); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp), ""), 0); + assertEq(iBTCVault.activeBalanceOf(alice), 0); + assertEq(iBTCVault.withdrawals(0), 0); + assertEq(iBTCVault.withdrawalShares(0), 0); + assertEq(iBTCVault.isWithdrawalsClaimed(0, alice), false); + assertEq(iBTCVault.depositWhitelist(), depositWhitelist); + assertEq(iBTCVault.isDepositorWhitelisted(alice), false); + assertEq(iBTCVault.slashableBalanceOf(alice), 0); + assertEq(iBTCVault.isDelegatorInitialized(), true); + assertEq(iBTCVault.isSlasherInitialized(), true); + assertEq(iBTCVault.isInitialized(), true); + + blockTimestamp = blockTimestamp + iBTCVault.epochDuration() - 1; + vm.warp(blockTimestamp); + + assertEq(iBTCVault.epochAt(uint48(blockTimestamp)), 0); + assertEq(iBTCVault.epochAt(uint48(blockTimestamp + 1)), 1); + assertEq(iBTCVault.currentEpoch(), 0); + assertEq(iBTCVault.currentEpochStart(), blockTimestamp - (iBTCVault.epochDuration() - 1)); + vm.expectRevert(IVaultStorage.NoPreviousEpoch.selector); + iBTCVault.previousEpochStart(); + assertEq(iBTCVault.nextEpochStart(), blockTimestamp + 1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + assertEq(iBTCVault.epochAt(uint48(blockTimestamp)), 1); + assertEq(iBTCVault.epochAt(uint48(blockTimestamp + 2 * iBTCVault.epochDuration())), 3); + assertEq(iBTCVault.currentEpoch(), 1); + assertEq(iBTCVault.currentEpochStart(), blockTimestamp); + assertEq(iBTCVault.previousEpochStart(), blockTimestamp - iBTCVault.epochDuration()); + assertEq(iBTCVault.nextEpochStart(), blockTimestamp + iBTCVault.epochDuration()); + + blockTimestamp = blockTimestamp + iBTCVault.epochDuration() - 1; + vm.warp(blockTimestamp); + + assertEq(iBTCVault.epochAt(uint48(blockTimestamp)), 1); + assertEq(iBTCVault.epochAt(uint48(blockTimestamp + 1)), 2); + assertEq(iBTCVault.currentEpoch(), 1); + assertEq(iBTCVault.currentEpochStart(), blockTimestamp - (iBTCVault.epochDuration() - 1)); + assertEq( + iBTCVault.previousEpochStart(), blockTimestamp - (iBTCVault.epochDuration() - 1) - iBTCVault.epochDuration() + ); + assertEq(iBTCVault.nextEpochStart(), blockTimestamp + 1); + } + + function test_CreateRevertInvalidEpochDuration() public { + uint48 epochDuration = 0; + + address[] memory networkLimitSetRoleHolders = new address[](1); + networkLimitSetRoleHolders[0] = alice; + address[] memory operatorNetworkSharesSetRoleHolders = new address[](1); + operatorNetworkSharesSetRoleHolders[0] = alice; + uint64 lastVersion = vaultFactory.lastVersion(); + vm.expectRevert(IVault.InvalidEpochDuration.selector); + vaultConfigurator.create( + IVaultConfigurator.InitParams({ + version: lastVersion, + owner: alice, + vaultParams: abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: epochDuration, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ), + delegatorIndex: 0, + delegatorParams: abi.encode( + INetworkRestakeDelegator.InitParams({ + baseParams: IBaseDelegator.BaseParams({ + defaultAdminRoleHolder: alice, + hook: address(0), + hookSetRoleHolder: alice + }), + networkLimitSetRoleHolders: networkLimitSetRoleHolders, + operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders + }) + ), + withSlasher: false, + slasherIndex: 0, + slasherParams: abi.encode(ISlasher.InitParams({baseParams: IBaseSlasher.BaseParams({isBurnerHook: false})})) + }) + ); + } + + function test_CreateRevertInvalidCollateral(uint48 epochDuration) public { + epochDuration = uint48(bound(epochDuration, 1, 50 weeks)); + + address[] memory networkLimitSetRoleHolders = new address[](1); + networkLimitSetRoleHolders[0] = alice; + address[] memory operatorNetworkSharesSetRoleHolders = new address[](1); + operatorNetworkSharesSetRoleHolders[0] = alice; + uint64 lastVersion = vaultFactory.lastVersion(); + vm.expectRevert(IVault.InvalidCollateral.selector); + vaultConfigurator.create( + IVaultConfigurator.InitParams({ + version: lastVersion, + owner: alice, + vaultParams: abi.encode( + IVault.InitParams({ + collateral: address(0), + burner: address(0xdEaD), + epochDuration: epochDuration, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ), + delegatorIndex: 0, + delegatorParams: abi.encode( + INetworkRestakeDelegator.InitParams({ + baseParams: IBaseDelegator.BaseParams({ + defaultAdminRoleHolder: alice, + hook: address(0), + hookSetRoleHolder: alice + }), + networkLimitSetRoleHolders: networkLimitSetRoleHolders, + operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders + }) + ), + withSlasher: false, + slasherIndex: 0, + slasherParams: abi.encode(ISlasher.InitParams({baseParams: IBaseSlasher.BaseParams({isBurnerHook: false})})) + }) + ); + } + + function test_CreateRevertMissingRoles1(uint48 epochDuration) public { + epochDuration = uint48(bound(epochDuration, 1, 50 weeks)); + + uint64 lastVersion = vaultFactory.lastVersion(); + + vm.expectRevert(IVault.MissingRoles.selector); + iBTCVault = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: epochDuration, + depositWhitelist: true, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: address(0), + depositWhitelistSetRoleHolder: address(0), + depositorWhitelistRoleHolder: address(0), + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: address(0) + }) + ) + ) + ); + } + + function test_CreateRevertMissingRoles2(uint48 epochDuration) public { + epochDuration = uint48(bound(epochDuration, 1, 50 weeks)); + + uint64 lastVersion = vaultFactory.lastVersion(); + + vm.expectRevert(IVault.MissingRoles.selector); + iBTCVault = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: epochDuration, + depositWhitelist: false, + isDepositLimit: true, + depositLimit: 0, + defaultAdminRoleHolder: address(0), + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: address(0), + isDepositLimitSetRoleHolder: address(0), + depositLimitSetRoleHolder: address(0) + }) + ) + ) + ); + } + + function test_CreateRevertMissingRoles3(uint48 epochDuration) public { + epochDuration = uint48(bound(epochDuration, 1, 50 weeks)); + + uint64 lastVersion = vaultFactory.lastVersion(); + + vm.expectRevert(IVault.MissingRoles.selector); + iBTCVault = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: epochDuration, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: address(0), + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: address(0), + isDepositLimitSetRoleHolder: address(0), + depositLimitSetRoleHolder: alice + }) + ) + ) + ); + } + + function test_CreateRevertMissingRoles4(uint48 epochDuration) public { + epochDuration = uint48(bound(epochDuration, 1, 50 weeks)); + + uint64 lastVersion = vaultFactory.lastVersion(); + + vm.expectRevert(IVault.MissingRoles.selector); + iBTCVault = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: epochDuration, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 1, + defaultAdminRoleHolder: address(0), + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: address(0), + isDepositLimitSetRoleHolder: address(0), + depositLimitSetRoleHolder: address(0) + }) + ) + ) + ); + } + + function test_CreateRevertMissingRoles5(uint48 epochDuration) public { + epochDuration = uint48(bound(epochDuration, 1, 50 weeks)); + + uint64 lastVersion = vaultFactory.lastVersion(); + + vm.expectRevert(IVault.MissingRoles.selector); + iBTCVault = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: epochDuration, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: address(0), + depositWhitelistSetRoleHolder: address(0), + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: address(0) + }) + ) + ) + ); + } + + function test_SetDelegator() public { + uint64 lastVersion = vaultFactory.lastVersion(); + + iBTCVault = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: 7 days, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ) + ) + ); + + assertEq(iBTCVault.isDelegatorInitialized(), false); + + address[] memory networkLimitSetRoleHolders = new address[](1); + networkLimitSetRoleHolders[0] = alice; + address[] memory operatorNetworkLimitSetRoleHolders = new address[](1); + operatorNetworkLimitSetRoleHolders[0] = alice; + delegator = FullRestakeDelegator( + delegatorFactory.create( + 1, + abi.encode( + address(iBTCVault), + abi.encode( + IFullRestakeDelegator.InitParams({ + baseParams: IBaseDelegator.BaseParams({ + defaultAdminRoleHolder: alice, + hook: address(0), + hookSetRoleHolder: alice + }), + networkLimitSetRoleHolders: networkLimitSetRoleHolders, + operatorNetworkLimitSetRoleHolders: operatorNetworkLimitSetRoleHolders + }) + ) + ) + ) + ); + + iBTCVault.setDelegator(address(delegator)); + + assertEq(iBTCVault.delegator(), address(delegator)); + assertEq(iBTCVault.isDelegatorInitialized(), true); + assertEq(iBTCVault.isInitialized(), false); + } + + function test_SetDelegatorRevertDelegatorAlreadyInitialized() public { + uint64 lastVersion = vaultFactory.lastVersion(); + + iBTCVault = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: 7 days, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ) + ) + ); + + address[] memory networkLimitSetRoleHolders = new address[](1); + networkLimitSetRoleHolders[0] = alice; + address[] memory operatorNetworkLimitSetRoleHolders = new address[](1); + operatorNetworkLimitSetRoleHolders[0] = alice; + delegator = FullRestakeDelegator( + delegatorFactory.create( + 1, + abi.encode( + address(iBTCVault), + abi.encode( + IFullRestakeDelegator.InitParams({ + baseParams: IBaseDelegator.BaseParams({ + defaultAdminRoleHolder: alice, + hook: address(0), + hookSetRoleHolder: alice + }), + networkLimitSetRoleHolders: networkLimitSetRoleHolders, + operatorNetworkLimitSetRoleHolders: operatorNetworkLimitSetRoleHolders + }) + ) + ) + ) + ); + + iBTCVault.setDelegator(address(delegator)); + + vm.expectRevert(IVault.DelegatorAlreadyInitialized.selector); + iBTCVault.setDelegator(address(delegator)); + } + + function test_SetDelegatorRevertNotDelegator() public { + uint64 lastVersion = vaultFactory.lastVersion(); + + iBTCVault = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: 7 days, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ) + ) + ); + + vm.expectRevert(IVault.NotDelegator.selector); + iBTCVault.setDelegator(address(1)); + } + + function test_SetDelegatorRevertInvalidDelegator() public { + uint64 lastVersion = vaultFactory.lastVersion(); + + iBTCVault = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: 7 days, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ) + ) + ); + + iBTC_Vault iBTC_Vault2 = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: 7 days, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ) + ) + ); + + address[] memory networkLimitSetRoleHolders = new address[](1); + networkLimitSetRoleHolders[0] = alice; + address[] memory operatorNetworkLimitSetRoleHolders = new address[](1); + operatorNetworkLimitSetRoleHolders[0] = alice; + delegator = FullRestakeDelegator( + delegatorFactory.create( + 1, + abi.encode( + address(iBTC_Vault2), + abi.encode( + IFullRestakeDelegator.InitParams({ + baseParams: IBaseDelegator.BaseParams({ + defaultAdminRoleHolder: alice, + hook: address(0), + hookSetRoleHolder: alice + }), + networkLimitSetRoleHolders: networkLimitSetRoleHolders, + operatorNetworkLimitSetRoleHolders: operatorNetworkLimitSetRoleHolders + }) + ) + ) + ) + ); + + vm.expectRevert(IVault.InvalidDelegator.selector); + iBTCVault.setDelegator(address(delegator)); + } + + function test_SetSlasher() public { + uint64 lastVersion = vaultFactory.lastVersion(); + + iBTCVault = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: 7 days, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ) + ) + ); + + assertEq(iBTCVault.isSlasherInitialized(), false); + + slasher = Slasher( + slasherFactory.create( + 0, + abi.encode( + address(iBTCVault), + abi.encode(ISlasher.InitParams({baseParams: IBaseSlasher.BaseParams({isBurnerHook: false})})) + ) + ) + ); + + iBTCVault.setSlasher(address(slasher)); + + assertEq(iBTCVault.slasher(), address(slasher)); + assertEq(iBTCVault.isSlasherInitialized(), true); + assertEq(iBTCVault.isInitialized(), false); + } + + function test_SetSlasherRevertSlasherAlreadyInitialized() public { + uint64 lastVersion = vaultFactory.lastVersion(); + + iBTCVault = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: 7 days, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ) + ) + ); + + slasher = Slasher( + slasherFactory.create( + 0, + abi.encode( + address(iBTCVault), + abi.encode(ISlasher.InitParams({baseParams: IBaseSlasher.BaseParams({isBurnerHook: false})})) + ) + ) + ); + + iBTCVault.setSlasher(address(slasher)); + + vm.expectRevert(IVault.SlasherAlreadyInitialized.selector); + iBTCVault.setSlasher(address(slasher)); + } + + function test_SetSlasherRevertNotSlasher() public { + uint64 lastVersion = vaultFactory.lastVersion(); + + iBTCVault = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: 7 days, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ) + ) + ); + + slasher = Slasher( + slasherFactory.create( + 0, + abi.encode( + address(iBTCVault), + abi.encode(ISlasher.InitParams({baseParams: IBaseSlasher.BaseParams({isBurnerHook: false})})) + ) + ) + ); + + vm.expectRevert(IVault.NotSlasher.selector); + iBTCVault.setSlasher(address(1)); + } + + function test_SetSlasherRevertInvalidSlasher() public { + uint64 lastVersion = vaultFactory.lastVersion(); + + iBTCVault = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: 7 days, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ) + ) + ); + + iBTC_Vault iBTCVault2 = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: 7 days, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ) + ) + ); + + slasher = Slasher( + slasherFactory.create( + 0, + abi.encode( + address(iBTCVault2), + abi.encode(ISlasher.InitParams({baseParams: IBaseSlasher.BaseParams({isBurnerHook: false})})) + ) + ) + ); + + vm.expectRevert(IVault.InvalidSlasher.selector); + iBTCVault.setSlasher(address(slasher)); + } + + function test_SetSlasherZeroAddress() public { + uint64 lastVersion = vaultFactory.lastVersion(); + + iBTCVault = iBTC_Vault( + vaultFactory.create( + lastVersion, + alice, + abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: 7 days, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ) + ) + ); + + iBTCVault.setSlasher(address(0)); + } + + function test_DepositTwice(uint256 amount1, uint256 amount2) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + uint256 tokensBefore = collateral.balanceOf(address(iBTCVault)); + uint256 shares1 = amount1 * 10 ** 0; + { + (uint256 depositedAmount, uint256 mintedShares) = _deposit(alice, amount1); + assertEq(depositedAmount, amount1); + assertEq(mintedShares, shares1); + } + assertEq(collateral.balanceOf(address(iBTCVault)) - tokensBefore, amount1); + + assertEq(iBTCVault.totalStake(), amount1); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp - 1), ""), 0); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp), ""), shares1); + assertEq(iBTCVault.activeShares(), shares1); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), ""), 0); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), ""), amount1); + assertEq(iBTCVault.activeStake(), amount1); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp - 1), ""), 0); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp), ""), shares1); + assertEq(iBTCVault.activeSharesOf(alice), shares1); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp - 1), ""), 0); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp), ""), amount1); + assertEq(iBTCVault.activeBalanceOf(alice), amount1); + assertEq(iBTCVault.slashableBalanceOf(alice), amount1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + uint256 shares2 = amount2 * (shares1 + 10 ** 0) / (amount1 + 1); + { + (uint256 depositedAmount, uint256 mintedShares) = _deposit(alice, amount2); + assertEq(depositedAmount, amount2); + assertEq(mintedShares, shares2); + } + + assertEq(iBTCVault.totalStake(), amount1 + amount2); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp - 1), ""), shares1); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp), ""), shares1 + shares2); + assertEq(iBTCVault.activeShares(), shares1 + shares2); + uint256 gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp - 1), abi.encode(1)), shares1); + uint256 gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp - 1), abi.encode(0)), shares1); + assertGt(gasSpent, gasLeft - gasleft()); + gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp), abi.encode(0)), shares1 + shares2); + gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp), abi.encode(1)), shares1 + shares2); + assertGt(gasSpent, gasLeft - gasleft()); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), ""), amount1); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), ""), amount1 + amount2); + assertEq(iBTCVault.activeStake(), amount1 + amount2); + gasLeft = gasleft(); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), abi.encode(1)), amount1); + gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), abi.encode(0)), amount1); + assertGt(gasSpent, gasLeft - gasleft()); + gasLeft = gasleft(); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), abi.encode(0)), amount1 + amount2); + gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), abi.encode(1)), amount1 + amount2); + assertGt(gasSpent, gasLeft - gasleft()); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), ""), shares1); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), ""), shares1 + shares2); + assertEq(iBTCVault.activeSharesOf(alice), shares1 + shares2); + gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp - 1), abi.encode(1)), shares1); + gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp - 1), abi.encode(0)), shares1); + assertGt(gasSpent, gasLeft - gasleft()); + gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp), abi.encode(0)), shares1 + shares2); + gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp), abi.encode(1)), shares1 + shares2); + assertGt(gasSpent, gasLeft - gasleft()); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp - 1), ""), amount1); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp), ""), amount1 + amount2); + assertEq(iBTCVault.activeBalanceOf(alice), amount1 + amount2); + assertEq(iBTCVault.slashableBalanceOf(alice), amount1 + amount2); + gasLeft = gasleft(); + assertEq( + iBTCVault.activeBalanceOfAt( + alice, + uint48(blockTimestamp - 1), + abi.encode( + IVault.ActiveBalanceOfHints({ + activeSharesOfHint: abi.encode(1), + activeStakeHint: abi.encode(1), + activeSharesHint: abi.encode(1) + }) + ) + ), + amount1 + ); + gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq( + iBTCVault.activeBalanceOfAt( + alice, + uint48(blockTimestamp - 1), + abi.encode( + IVault.ActiveBalanceOfHints({ + activeSharesOfHint: abi.encode(0), + activeStakeHint: abi.encode(0), + activeSharesHint: abi.encode(0) + }) + ) + ), + amount1 + ); + assertGt(gasSpent, gasLeft - gasleft()); + gasLeft = gasleft(); + assertEq( + iBTCVault.activeBalanceOfAt( + alice, + uint48(blockTimestamp), + abi.encode( + IVault.ActiveBalanceOfHints({ + activeSharesOfHint: abi.encode(0), + activeStakeHint: abi.encode(0), + activeSharesHint: abi.encode(0) + }) + ) + ), + amount1 + amount2 + ); + gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq( + iBTCVault.activeBalanceOfAt( + alice, + uint48(blockTimestamp), + abi.encode( + IVault.ActiveBalanceOfHints({ + activeSharesOfHint: abi.encode(1), + activeStakeHint: abi.encode(1), + activeSharesHint: abi.encode(1) + }) + ) + ), + amount1 + amount2 + ); + assertGt(gasSpent, gasLeft - gasleft()); + } + + function test_DepositTwiceFeeOnTransferCollateral(uint256 amount1, uint256 amount2) public { + amount1 = bound(amount1, 2, 100 * 10 ** 18); + amount2 = bound(amount2, 2, 100 * 10 ** 18); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + uint48 epochDuration = 1; + { + address[] memory networkLimitSetRoleHolders = new address[](1); + networkLimitSetRoleHolders[0] = alice; + address[] memory operatorNetworkSharesSetRoleHolders = new address[](1); + operatorNetworkSharesSetRoleHolders[0] = alice; + (address vault_,,) = vaultConfigurator.create( + IVaultConfigurator.InitParams({ + version: vaultFactory.lastVersion(), + owner: alice, + vaultParams: abi.encode( + IVault.InitParams({ + collateral: address(feeOnTransferCollateral), + burner: address(0xdEaD), + epochDuration: epochDuration, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ), + delegatorIndex: 0, + delegatorParams: abi.encode( + INetworkRestakeDelegator.InitParams({ + baseParams: IBaseDelegator.BaseParams({ + defaultAdminRoleHolder: alice, + hook: address(0), + hookSetRoleHolder: alice + }), + networkLimitSetRoleHolders: networkLimitSetRoleHolders, + operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders + }) + ), + withSlasher: false, + slasherIndex: 0, + slasherParams: "" + }) + ); + + iBTCVault = iBTC_Vault(vault_); + } + + uint256 tokensBefore = feeOnTransferCollateral.balanceOf(address(iBTCVault)); + uint256 shares1 = (amount1 - 1) * 10 ** 0; + feeOnTransferCollateral.transfer(alice, amount1 + 1); + vm.startPrank(alice); + feeOnTransferCollateral.approve(address(iBTCVault), amount1); + { + (uint256 depositedAmount, uint256 mintedShares) = iBTCVault.deposit(alice, amount1); + assertEq(depositedAmount, amount1 - 1); + assertEq(mintedShares, shares1); + } + vm.stopPrank(); + assertEq(feeOnTransferCollateral.balanceOf(address(iBTCVault)) - tokensBefore, amount1 - 1); + + assertEq(iBTCVault.totalStake(), amount1 - 1); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp - 1), ""), 0); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp), ""), shares1); + assertEq(iBTCVault.activeShares(), shares1); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), ""), 0); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), ""), amount1 - 1); + assertEq(iBTCVault.activeStake(), amount1 - 1); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp - 1), ""), 0); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp), ""), shares1); + assertEq(iBTCVault.activeSharesOf(alice), shares1); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp - 1), ""), 0); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp), ""), amount1 - 1); + assertEq(iBTCVault.activeBalanceOf(alice), amount1 - 1); + assertEq(iBTCVault.slashableBalanceOf(alice), amount1 - 1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + uint256 shares2 = (amount2 - 1) * (shares1 + 10 ** 0) / (amount1 - 1 + 1); + feeOnTransferCollateral.transfer(alice, amount2 + 1); + vm.startPrank(alice); + feeOnTransferCollateral.approve(address(iBTCVault), amount2); + { + (uint256 depositedAmount, uint256 mintedShares) = iBTCVault.deposit(alice, amount2); + assertEq(depositedAmount, amount2 - 1); + assertEq(mintedShares, shares2); + } + vm.stopPrank(); + + assertEq(iBTCVault.totalStake(), amount1 - 1 + amount2 - 1); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp - 1), ""), shares1); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp), ""), shares1 + shares2); + assertEq(iBTCVault.activeShares(), shares1 + shares2); + uint256 gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp - 1), abi.encode(1)), shares1); + uint256 gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp - 1), abi.encode(0)), shares1); + assertGt(gasSpent, gasLeft - gasleft()); + gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp), abi.encode(0)), shares1 + shares2); + gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp), abi.encode(1)), shares1 + shares2); + assertGt(gasSpent, gasLeft - gasleft()); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), ""), amount1 - 1); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), ""), amount1 - 1 + amount2 - 1); + assertEq(iBTCVault.activeStake(), amount1 - 1 + amount2 - 1); + gasLeft = gasleft(); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), abi.encode(1)), amount1 - 1); + gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), abi.encode(0)), amount1 - 1); + assertGt(gasSpent, gasLeft - gasleft()); + gasLeft = gasleft(); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), abi.encode(0)), amount1 - 1 + amount2 - 1); + gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), abi.encode(1)), amount1 - 1 + amount2 - 1); + assertGt(gasSpent, gasLeft - gasleft()); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), ""), shares1); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), ""), shares1 + shares2); + assertEq(iBTCVault.activeSharesOf(alice), shares1 + shares2); + gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp - 1), abi.encode(1)), shares1); + gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp - 1), abi.encode(0)), shares1); + assertGt(gasSpent, gasLeft - gasleft()); + gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp), abi.encode(0)), shares1 + shares2); + gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp), abi.encode(1)), shares1 + shares2); + assertGt(gasSpent, gasLeft - gasleft()); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp - 1), ""), amount1 - 1); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp), ""), amount1 - 1 + amount2 - 1); + assertEq(iBTCVault.activeBalanceOf(alice), amount1 - 1 + amount2 - 1); + assertEq(iBTCVault.slashableBalanceOf(alice), amount1 - 1 + amount2 - 1); + gasLeft = gasleft(); + assertEq( + iBTCVault.activeBalanceOfAt( + alice, + uint48(blockTimestamp - 1), + abi.encode( + IVault.ActiveBalanceOfHints({ + activeSharesOfHint: abi.encode(1), + activeStakeHint: abi.encode(1), + activeSharesHint: abi.encode(1) + }) + ) + ), + amount1 - 1 + ); + gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq( + iBTCVault.activeBalanceOfAt( + alice, + uint48(blockTimestamp - 1), + abi.encode( + IVault.ActiveBalanceOfHints({ + activeSharesOfHint: abi.encode(0), + activeStakeHint: abi.encode(0), + activeSharesHint: abi.encode(0) + }) + ) + ), + amount1 - 1 + ); + assertGt(gasSpent, gasLeft - gasleft()); + gasLeft = gasleft(); + assertEq( + iBTCVault.activeBalanceOfAt( + alice, + uint48(blockTimestamp), + abi.encode( + IVault.ActiveBalanceOfHints({ + activeSharesOfHint: abi.encode(0), + activeStakeHint: abi.encode(0), + activeSharesHint: abi.encode(0) + }) + ) + ), + amount1 - 1 + amount2 - 1 + ); + gasSpent = gasLeft - gasleft(); + gasLeft = gasleft(); + assertEq( + iBTCVault.activeBalanceOfAt( + alice, + uint48(blockTimestamp), + abi.encode( + IVault.ActiveBalanceOfHints({ + activeSharesOfHint: abi.encode(1), + activeStakeHint: abi.encode(1), + activeSharesHint: abi.encode(1) + }) + ) + ), + amount1 - 1 + amount2 - 1 + ); + assertGt(gasSpent, gasLeft - gasleft()); + } + + function test_DepositBoth(uint256 amount1, uint256 amount2) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + uint256 shares1 = amount1 * 10 ** 0; + { + (uint256 depositedAmount, uint256 mintedShares) = _deposit(alice, amount1); + assertEq(depositedAmount, amount1); + assertEq(mintedShares, shares1); + } + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + uint256 shares2 = amount2 * (shares1 + 10 ** 0) / (amount1 + 1); + { + (uint256 depositedAmount, uint256 mintedShares) = _deposit(bob, amount2); + assertEq(depositedAmount, amount2); + assertEq(mintedShares, shares2); + } + + assertEq(iBTCVault.totalStake(), amount1 + amount2); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp - 1), ""), shares1); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp), ""), shares1 + shares2); + assertEq(iBTCVault.activeShares(), shares1 + shares2); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), ""), amount1); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), ""), amount1 + amount2); + assertEq(iBTCVault.activeStake(), amount1 + amount2); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp - 1), ""), shares1); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp), ""), shares1); + assertEq(iBTCVault.activeSharesOf(alice), shares1); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp - 1), ""), amount1); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp), ""), amount1); + assertEq(iBTCVault.activeBalanceOf(alice), amount1); + assertEq(iBTCVault.slashableBalanceOf(alice), amount1); + assertEq(iBTCVault.activeSharesOfAt(bob, uint48(blockTimestamp - 1), ""), 0); + assertEq(iBTCVault.activeSharesOfAt(bob, uint48(blockTimestamp), ""), shares2); + assertEq(iBTCVault.activeSharesOf(bob), shares2); + assertEq(iBTCVault.activeBalanceOfAt(bob, uint48(blockTimestamp - 1), ""), 0); + assertEq(iBTCVault.activeBalanceOfAt(bob, uint48(blockTimestamp), ""), amount2); + assertEq(iBTCVault.activeBalanceOf(bob), amount2); + assertEq(iBTCVault.slashableBalanceOf(bob), amount2); + } + + function test_DepositRevertInvalidOnBehalfOf(uint256 amount1) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + vm.startPrank(alice); + vm.expectRevert(IVault.InvalidOnBehalfOf.selector); + iBTCVault.deposit(address(0), amount1); + vm.stopPrank(); + } + + function test_DepositRevertInsufficientDeposit() public { + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + vm.startPrank(alice); + vm.expectRevert(IVault.InsufficientDeposit.selector); + iBTCVault.deposit(alice, 0); + vm.stopPrank(); + } + + function test_WithdrawTwice(uint256 amount1, uint256 amount2, uint256 amount3) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + amount3 = bound(amount3, 1, 100 * 10 ** 18); + vm.assume(amount1 >= amount2 + amount3); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + // uint48 epochDuration = 1; + iBTCVault = _getVault(1); + + (, uint256 shares) = _deposit(alice, amount1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + uint256 burnedShares = amount2 * (shares + 10 ** 0) / (amount1 + 1); + uint256 mintedShares = amount2 * 10 ** 0; + (uint256 burnedShares_, uint256 mintedShares_) = _withdraw(alice, amount2); + assertEq(burnedShares_, burnedShares); + assertEq(mintedShares_, mintedShares); + + assertEq(iBTCVault.totalStake(), amount1); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp - 1), ""), shares); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp), ""), shares - burnedShares); + assertEq(iBTCVault.activeShares(), shares - burnedShares); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), ""), amount1); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), ""), amount1 - amount2); + assertEq(iBTCVault.activeStake(), amount1 - amount2); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp - 1), ""), shares); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp), ""), shares - burnedShares); + assertEq(iBTCVault.activeSharesOf(alice), shares - burnedShares); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp - 1), ""), amount1); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp), ""), amount1 - amount2); + assertEq(iBTCVault.activeBalanceOf(alice), amount1 - amount2); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch()), 0); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch() + 1), amount2); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch() + 2), 0); + assertEq(iBTCVault.withdrawalShares(iBTCVault.currentEpoch()), 0); + assertEq(iBTCVault.withdrawalShares(iBTCVault.currentEpoch() + 1), mintedShares); + assertEq(iBTCVault.withdrawalShares(iBTCVault.currentEpoch() + 2), 0); + assertEq(iBTCVault.withdrawalSharesOf(iBTCVault.currentEpoch(), alice), 0); + assertEq(iBTCVault.withdrawalSharesOf(iBTCVault.currentEpoch() + 1, alice), mintedShares); + assertEq(iBTCVault.withdrawalSharesOf(iBTCVault.currentEpoch() + 2, alice), 0); + assertEq(iBTCVault.slashableBalanceOf(alice), amount1); + + shares -= burnedShares; + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + burnedShares = amount3 * (shares + 10 ** 0) / (amount1 - amount2 + 1); + mintedShares = amount3 * 10 ** 0; + (burnedShares_, mintedShares_) = _withdraw(alice, amount3); + assertEq(burnedShares_, burnedShares); + assertEq(mintedShares_, mintedShares); + + assertEq(iBTCVault.totalStake(), amount1); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp - 1), ""), shares); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp), ""), shares - burnedShares); + assertEq(iBTCVault.activeShares(), shares - burnedShares); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), ""), amount1 - amount2); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), ""), amount1 - amount2 - amount3); + assertEq(iBTCVault.activeStake(), amount1 - amount2 - amount3); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp - 1), ""), shares); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp), ""), shares - burnedShares); + assertEq(iBTCVault.activeSharesOf(alice), shares - burnedShares); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp - 1), ""), amount1 - amount2); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp), ""), amount1 - amount2 - amount3); + assertEq(iBTCVault.activeBalanceOf(alice), amount1 - amount2 - amount3); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch() - 1), 0); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch()), amount2); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch() + 1), amount3); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch() + 2), 0); + assertEq(iBTCVault.withdrawalShares(iBTCVault.currentEpoch() - 1), 0); + assertEq(iBTCVault.withdrawalShares(iBTCVault.currentEpoch()), amount2 * 10 ** 0); + assertEq(iBTCVault.withdrawalShares(iBTCVault.currentEpoch() + 1), amount3 * 10 ** 0); + assertEq(iBTCVault.withdrawalShares(iBTCVault.currentEpoch() + 2), 0); + assertEq(iBTCVault.withdrawalSharesOf(iBTCVault.currentEpoch() - 1, alice), 0); + assertEq(iBTCVault.withdrawalSharesOf(iBTCVault.currentEpoch(), alice), amount2 * 10 ** 0); + assertEq(iBTCVault.withdrawalSharesOf(iBTCVault.currentEpoch() + 1, alice), amount3 * 10 ** 0); + assertEq(iBTCVault.withdrawalSharesOf(iBTCVault.currentEpoch() + 2, alice), 0); + assertEq(iBTCVault.slashableBalanceOf(alice), amount1); + + shares -= burnedShares; + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + assertEq(iBTCVault.totalStake(), amount1 - amount2); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + assertEq(iBTCVault.totalStake(), amount1 - amount2 - amount3); + } + + function test_WithdrawRevertInvalidClaimer(uint256 amount1) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + vm.expectRevert(IVault.InvalidClaimer.selector); + vm.startPrank(alice); + iBTCVault.withdraw(address(0), amount1); + vm.stopPrank(); + } + + function test_WithdrawRevertInsufficientWithdrawal(uint256 amount1) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + vm.expectRevert(IVault.InsufficientWithdrawal.selector); + _withdraw(alice, 0); + } + + function test_WithdrawRevertTooMuchWithdraw(uint256 amount1) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + vm.expectRevert(IVault.TooMuchWithdraw.selector); + _withdraw(alice, amount1 + 1); + } + + function test_RedeemTwice(uint256 amount1, uint256 amount2, uint256 amount3) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + amount3 = bound(amount3, 1, 100 * 10 ** 18); + vm.assume(amount1 >= amount2 + amount3); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + // uint48 epochDuration = 1; + iBTCVault = _getVault(1); + + (, uint256 shares) = _deposit(alice, amount1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + uint256 withdrawnAssets2 = amount2 * (amount1 + 1) / (shares + 10 ** 0); + uint256 mintedShares = amount2 * 10 ** 0; + (uint256 withdrawnAssets_, uint256 mintedShares_) = _redeem(alice, amount2); + assertEq(withdrawnAssets_, withdrawnAssets2); + assertEq(mintedShares_, mintedShares); + + assertEq(iBTCVault.totalStake(), amount1); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp - 1), ""), shares); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp), ""), shares - amount2); + assertEq(iBTCVault.activeShares(), shares - amount2); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), ""), amount1); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), ""), amount1 - withdrawnAssets2); + assertEq(iBTCVault.activeStake(), amount1 - withdrawnAssets2); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp - 1), ""), shares); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp), ""), shares - amount2); + assertEq(iBTCVault.activeSharesOf(alice), shares - amount2); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp - 1), ""), amount1); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp), ""), amount1 - withdrawnAssets2); + assertEq(iBTCVault.activeBalanceOf(alice), amount1 - withdrawnAssets2); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch()), 0); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch() + 1), withdrawnAssets2); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch() + 2), 0); + assertEq(iBTCVault.withdrawalShares(iBTCVault.currentEpoch()), 0); + assertEq(iBTCVault.withdrawalShares(iBTCVault.currentEpoch() + 1), mintedShares); + assertEq(iBTCVault.withdrawalShares(iBTCVault.currentEpoch() + 2), 0); + assertEq(iBTCVault.withdrawalSharesOf(iBTCVault.currentEpoch(), alice), 0); + assertEq(iBTCVault.withdrawalSharesOf(iBTCVault.currentEpoch() + 1, alice), mintedShares); + assertEq(iBTCVault.withdrawalSharesOf(iBTCVault.currentEpoch() + 2, alice), 0); + assertEq(iBTCVault.slashableBalanceOf(alice), amount1); + + shares -= amount2; + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + uint256 withdrawnAssets3 = amount3 * (amount1 - withdrawnAssets2 + 1) / (shares + 10 ** 0); + mintedShares = amount3 * 10 ** 0; + (withdrawnAssets_, mintedShares_) = _redeem(alice, amount3); + assertEq(withdrawnAssets_, withdrawnAssets3); + assertEq(mintedShares_, mintedShares); + + assertEq(iBTCVault.totalStake(), amount1); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp - 1), ""), shares); + assertEq(iBTCVault.activeSharesAt(uint48(blockTimestamp), ""), shares - amount3); + assertEq(iBTCVault.activeShares(), shares - amount3); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp - 1), ""), amount1 - withdrawnAssets2); + assertEq(iBTCVault.activeStakeAt(uint48(blockTimestamp), ""), amount1 - withdrawnAssets2 - withdrawnAssets3); + assertEq(iBTCVault.activeStake(), amount1 - withdrawnAssets2 - withdrawnAssets3); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp - 1), ""), shares); + assertEq(iBTCVault.activeSharesOfAt(alice, uint48(blockTimestamp), ""), shares - amount3); + assertEq(iBTCVault.activeSharesOf(alice), shares - amount3); + assertEq(iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp - 1), ""), amount1 - withdrawnAssets2); + assertEq( + iBTCVault.activeBalanceOfAt(alice, uint48(blockTimestamp), ""), + amount1 - withdrawnAssets2 - withdrawnAssets3 + ); + assertEq(iBTCVault.activeBalanceOf(alice), amount1 - withdrawnAssets2 - withdrawnAssets3); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch() - 1), 0); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch()), withdrawnAssets2); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch() + 1), withdrawnAssets3); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch() + 2), 0); + assertEq(iBTCVault.withdrawalShares(iBTCVault.currentEpoch() - 1), 0); + assertEq(iBTCVault.withdrawalShares(iBTCVault.currentEpoch()), withdrawnAssets2 * 10 ** 0); + assertEq(iBTCVault.withdrawalShares(iBTCVault.currentEpoch() + 1), withdrawnAssets3 * 10 ** 0); + assertEq(iBTCVault.withdrawalShares(iBTCVault.currentEpoch() + 2), 0); + assertEq(iBTCVault.withdrawalSharesOf(iBTCVault.currentEpoch() - 1, alice), 0); + assertEq(iBTCVault.withdrawalSharesOf(iBTCVault.currentEpoch(), alice), withdrawnAssets2 * 10 ** 0); + assertEq(iBTCVault.withdrawalSharesOf(iBTCVault.currentEpoch() + 1, alice), withdrawnAssets3 * 10 ** 0); + assertEq(iBTCVault.withdrawalSharesOf(iBTCVault.currentEpoch() + 2, alice), 0); + assertEq(iBTCVault.slashableBalanceOf(alice), amount1); + + shares -= amount3; + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + assertEq(iBTCVault.totalStake(), amount1 - withdrawnAssets2); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + assertEq(iBTCVault.totalStake(), amount1 - withdrawnAssets2 - withdrawnAssets3); + } + + function test_RedeemRevertInvalidClaimer(uint256 amount1) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + vm.expectRevert(IVault.InvalidClaimer.selector); + vm.startPrank(alice); + iBTCVault.redeem(address(0), amount1); + vm.stopPrank(); + } + + function test_RedeemRevertInsufficientRedeemption(uint256 amount1) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + vm.expectRevert(IVault.InsufficientRedemption.selector); + _redeem(alice, 0); + } + + function test_RedeemRevertTooMuchRedeem(uint256 amount1) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + vm.expectRevert(IVault.TooMuchRedeem.selector); + _redeem(alice, amount1 + 1); + } + + function test_Claim(uint256 amount1, uint256 amount2) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + vm.assume(amount1 >= amount2); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount2); + + blockTimestamp = blockTimestamp + 2; + vm.warp(blockTimestamp); + + uint256 tokensBefore = collateral.balanceOf(address(iBTCVault)); + uint256 tokensBeforeAlice = collateral.balanceOf(alice); + assertEq(_claim(alice, iBTCVault.currentEpoch() - 1), amount2); + assertEq(tokensBefore - collateral.balanceOf(address(iBTCVault)), amount2); + assertEq(collateral.balanceOf(alice) - tokensBeforeAlice, amount2); + + assertEq(iBTCVault.isWithdrawalsClaimed(iBTCVault.currentEpoch() - 1, alice), true); + } + + function test_ClaimRevertInvalidRecipient(uint256 amount1, uint256 amount2) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + vm.assume(amount1 >= amount2); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount2); + + blockTimestamp = blockTimestamp + 2; + vm.warp(blockTimestamp); + + vm.startPrank(alice); + uint256 currentEpoch = iBTCVault.currentEpoch(); + vm.expectRevert(IVault.InvalidRecipient.selector); + iBTCVault.claim(address(0), currentEpoch - 1); + vm.stopPrank(); + } + + function test_ClaimRevertInvalidEpoch(uint256 amount1, uint256 amount2) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + vm.assume(amount1 >= amount2); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount2); + + blockTimestamp = blockTimestamp + 2; + vm.warp(blockTimestamp); + + uint256 currentEpoch = iBTCVault.currentEpoch(); + vm.expectRevert(IVault.InvalidEpoch.selector); + _claim(alice, currentEpoch); + } + + function test_ClaimRevertAlreadyClaimed(uint256 amount1, uint256 amount2) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + vm.assume(amount1 >= amount2); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount2); + + blockTimestamp = blockTimestamp + 2; + vm.warp(blockTimestamp); + + uint256 currentEpoch = iBTCVault.currentEpoch(); + _claim(alice, currentEpoch - 1); + + vm.expectRevert(IVault.AlreadyClaimed.selector); + _claim(alice, currentEpoch - 1); + } + + function test_ClaimRevertInsufficientClaim(uint256 amount1, uint256 amount2) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + vm.assume(amount1 >= amount2); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount2); + + blockTimestamp = blockTimestamp + 2; + vm.warp(blockTimestamp); + + uint256 currentEpoch = iBTCVault.currentEpoch(); + vm.expectRevert(IVault.InsufficientClaim.selector); + _claim(alice, currentEpoch - 2); + } + + function test_ClaimBatch(uint256 amount1, uint256 amount2, uint256 amount3) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + amount3 = bound(amount3, 1, 100 * 10 ** 18); + vm.assume(amount1 >= amount2 + amount3); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount2); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount3); + + blockTimestamp = blockTimestamp + 2; + vm.warp(blockTimestamp); + + uint256[] memory epochs = new uint256[](2); + epochs[0] = iBTCVault.currentEpoch() - 1; + epochs[1] = iBTCVault.currentEpoch() - 2; + + uint256 tokensBefore = collateral.balanceOf(address(iBTCVault)); + uint256 tokensBeforeAlice = collateral.balanceOf(alice); + assertEq(_claimBatch(alice, epochs), amount2 + amount3); + assertEq(tokensBefore - collateral.balanceOf(address(iBTCVault)), amount2 + amount3); + assertEq(collateral.balanceOf(alice) - tokensBeforeAlice, amount2 + amount3); + + assertEq(iBTCVault.isWithdrawalsClaimed(iBTCVault.currentEpoch() - 1, alice), true); + } + + function test_ClaimBatchRevertInvalidRecipient(uint256 amount1, uint256 amount2, uint256 amount3) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + amount3 = bound(amount3, 1, 100 * 10 ** 18); + vm.assume(amount1 >= amount2 + amount3); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount2); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount3); + + blockTimestamp = blockTimestamp + 2; + vm.warp(blockTimestamp); + + uint256[] memory epochs = new uint256[](2); + epochs[0] = iBTCVault.currentEpoch() - 1; + epochs[1] = iBTCVault.currentEpoch() - 2; + + vm.expectRevert(IVault.InvalidRecipient.selector); + vm.startPrank(alice); + iBTCVault.claimBatch(address(0), epochs); + vm.stopPrank(); + } + + function test_ClaimBatchRevertInvalidLengthEpochs(uint256 amount1, uint256 amount2, uint256 amount3) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + amount3 = bound(amount3, 1, 100 * 10 ** 18); + vm.assume(amount1 >= amount2 + amount3); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount2); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount3); + + blockTimestamp = blockTimestamp + 2; + vm.warp(blockTimestamp); + + uint256[] memory epochs = new uint256[](0); + vm.expectRevert(IVault.InvalidLengthEpochs.selector); + _claimBatch(alice, epochs); + } + + function test_ClaimBatchRevertInvalidEpoch(uint256 amount1, uint256 amount2, uint256 amount3) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + amount3 = bound(amount3, 1, 100 * 10 ** 18); + vm.assume(amount1 >= amount2 + amount3); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount2); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount3); + + blockTimestamp = blockTimestamp + 2; + vm.warp(blockTimestamp); + + uint256[] memory epochs = new uint256[](2); + epochs[0] = iBTCVault.currentEpoch() - 1; + epochs[1] = iBTCVault.currentEpoch(); + + vm.expectRevert(IVault.InvalidEpoch.selector); + _claimBatch(alice, epochs); + } + + function test_ClaimBatchRevertAlreadyClaimed(uint256 amount1, uint256 amount2, uint256 amount3) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + amount3 = bound(amount3, 1, 100 * 10 ** 18); + vm.assume(amount1 >= amount2 + amount3); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount2); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount3); + + blockTimestamp = blockTimestamp + 2; + vm.warp(blockTimestamp); + + uint256[] memory epochs = new uint256[](2); + epochs[0] = iBTCVault.currentEpoch() - 1; + epochs[1] = iBTCVault.currentEpoch() - 1; + + vm.expectRevert(IVault.AlreadyClaimed.selector); + _claimBatch(alice, epochs); + } + + function test_ClaimBatchRevertInsufficientClaim(uint256 amount1, uint256 amount2, uint256 amount3) public { + amount1 = bound(amount1, 1, 100 * 10 ** 18); + amount2 = bound(amount2, 1, 100 * 10 ** 18); + amount3 = bound(amount3, 1, 100 * 10 ** 18); + vm.assume(amount1 >= amount2 + amount3); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + uint48 epochDuration = 1; + iBTCVault = _getVault(epochDuration); + + _deposit(alice, amount1); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount2); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + _withdraw(alice, amount3); + + blockTimestamp = blockTimestamp + 2; + vm.warp(blockTimestamp); + + uint256[] memory epochs = new uint256[](2); + epochs[0] = iBTCVault.currentEpoch() - 1; + epochs[1] = iBTCVault.currentEpoch() - 3; + + vm.expectRevert(IVault.InsufficientClaim.selector); + _claimBatch(alice, epochs); + } + + function test_SetDepositWhitelist() public { + uint48 epochDuration = 1; + + iBTCVault = _getVault(epochDuration); + + _grantDepositWhitelistSetRole(alice, alice); + _setDepositWhitelist(alice, true); + assertEq(iBTCVault.depositWhitelist(), true); + + _setDepositWhitelist(alice, false); + assertEq(iBTCVault.depositWhitelist(), false); + } + + function test_SetDepositWhitelistRevertNotWhitelistedDepositor() public { + uint48 epochDuration = 1; + + iBTCVault = _getVault(epochDuration); + + _deposit(alice, 1); + + _grantDepositWhitelistSetRole(alice, alice); + _setDepositWhitelist(alice, true); + + vm.startPrank(alice); + vm.expectRevert(IVault.NotWhitelistedDepositor.selector); + iBTCVault.deposit(alice, 1); + vm.stopPrank(); + } + + function test_SetDepositWhitelistRevertAlreadySet() public { + uint48 epochDuration = 1; + + iBTCVault = _getVault(epochDuration); + + _grantDepositWhitelistSetRole(alice, alice); + _setDepositWhitelist(alice, true); + + vm.expectRevert(IVault.AlreadySet.selector); + _setDepositWhitelist(alice, true); + } + + function test_SetDepositorWhitelistStatus() public { + uint48 epochDuration = 1; + + iBTCVault = _getVault(epochDuration); + + _grantDepositWhitelistSetRole(alice, alice); + _setDepositWhitelist(alice, true); + + _grantDepositorWhitelistRole(alice, alice); + + _setDepositorWhitelistStatus(alice, bob, true); + assertEq(iBTCVault.isDepositorWhitelisted(bob), true); + + _deposit(bob, 1); + + _setDepositWhitelist(alice, false); + + _deposit(bob, 1); + } + + function test_SetDepositorWhitelistStatusRevertInvalidAccount() public { + uint48 epochDuration = 1; + + iBTCVault = _getVault(epochDuration); + + _grantDepositWhitelistSetRole(alice, alice); + _setDepositWhitelist(alice, true); + + _grantDepositorWhitelistRole(alice, alice); + + vm.expectRevert(IVault.InvalidAccount.selector); + _setDepositorWhitelistStatus(alice, address(0), true); + } + + function test_SetDepositorWhitelistStatusRevertAlreadySet() public { + uint48 epochDuration = 1; + + iBTCVault = _getVault(epochDuration); + + _grantDepositWhitelistSetRole(alice, alice); + _setDepositWhitelist(alice, true); + + _grantDepositorWhitelistRole(alice, alice); + + _setDepositorWhitelistStatus(alice, bob, true); + + vm.expectRevert(IVault.AlreadySet.selector); + _setDepositorWhitelistStatus(alice, bob, true); + } + + function test_SetIsDepositLimit() public { + uint48 epochDuration = 1; + + iBTCVault = _getVault(epochDuration); + + _grantIsDepositLimitSetRole(alice, alice); + _setIsDepositLimit(alice, true); + assertEq(iBTCVault.isDepositLimit(), true); + + _setIsDepositLimit(alice, false); + assertEq(iBTCVault.isDepositLimit(), false); + } + + function test_SetIsDepositLimitRevertAlreadySet() public { + uint48 epochDuration = 1; + + iBTCVault = _getVault(epochDuration); + + _grantIsDepositLimitSetRole(alice, alice); + _setIsDepositLimit(alice, true); + + vm.expectRevert(IVault.AlreadySet.selector); + _setIsDepositLimit(alice, true); + } + + function test_SetDepositLimit(uint256 limit1, uint256 limit2, uint256 depositAmount) public { + uint48 epochDuration = 1; + + iBTCVault = _getVault(epochDuration); + + _grantIsDepositLimitSetRole(alice, alice); + _setIsDepositLimit(alice, true); + assertEq(iBTCVault.depositLimit(), 0); + + limit1 = bound(limit1, 1, type(uint256).max); + _grantDepositLimitSetRole(alice, alice); + _setDepositLimit(alice, limit1); + assertEq(iBTCVault.depositLimit(), limit1); + + limit2 = bound(limit2, 1, 1000 ether); + vm.assume(limit2 != limit1); + _setDepositLimit(alice, limit2); + assertEq(iBTCVault.depositLimit(), limit2); + + depositAmount = bound(depositAmount, 1, limit2); + _deposit(alice, depositAmount); + } + + function test_SetDepositLimitToNull(uint256 limit1) public { + uint48 epochDuration = 1; + + iBTCVault = _getVault(epochDuration); + + limit1 = bound(limit1, 1, type(uint256).max); + _grantIsDepositLimitSetRole(alice, alice); + _setIsDepositLimit(alice, true); + _grantDepositLimitSetRole(alice, alice); + _setDepositLimit(alice, limit1); + + _setIsDepositLimit(alice, false); + + _setDepositLimit(alice, 0); + + assertEq(iBTCVault.depositLimit(), 0); + } + + function test_SetDepositLimitRevertDepositLimitReached(uint256 depositAmount, uint256 limit) public { + uint48 epochDuration = 1; + + iBTCVault = _getVault(epochDuration); + + _deposit(alice, 1); + + limit = bound(limit, 2, 1000 ether); + _grantIsDepositLimitSetRole(alice, alice); + _setIsDepositLimit(alice, true); + _grantDepositLimitSetRole(alice, alice); + _setDepositLimit(alice, limit); + + depositAmount = bound(depositAmount, limit, 2000 ether); + + collateral.transfer(alice, depositAmount); + vm.startPrank(alice); + collateral.approve(address(iBTCVault), depositAmount); + vm.expectRevert(IVault.DepositLimitReached.selector); + iBTCVault.deposit(alice, depositAmount); + vm.stopPrank(); + } + + function test_SetDepositLimitRevertAlreadySet(uint256 limit) public { + uint48 epochDuration = 1; + + iBTCVault = _getVault(epochDuration); + + limit = bound(limit, 1, type(uint256).max); + _grantIsDepositLimitSetRole(alice, alice); + _setIsDepositLimit(alice, true); + _grantDepositLimitSetRole(alice, alice); + _setDepositLimit(alice, limit); + + vm.expectRevert(IVault.AlreadySet.selector); + _setDepositLimit(alice, limit); + } + + function test_OnSlashRevertNotSlasher() public { + uint48 epochDuration = 1; + + iBTCVault = _getVault(epochDuration); + + vm.startPrank(alice); + vm.expectRevert(IVault.NotSlasher.selector); + iBTCVault.onSlash(0, 0); + vm.stopPrank(); + } + + struct Test_SlashStruct { + uint256 slashAmountReal1; + uint256 tokensBeforeBurner; + uint256 activeStake1; + uint256 withdrawals1; + uint256 nextWithdrawals1; + uint256 slashAmountSlashed2; + } + + function test_Slash( + // uint48 epochDuration, + uint256 depositAmount, + uint256 withdrawAmount1, + uint256 withdrawAmount2, + uint256 slashAmount1, + uint256 slashAmount2, + uint256 captureAgo + ) public { + // epochDuration = uint48(bound(epochDuration, 2, 10 days)); + depositAmount = bound(depositAmount, 1, 100 * 10 ** 18); + withdrawAmount1 = bound(withdrawAmount1, 1, 100 * 10 ** 18); + withdrawAmount2 = bound(withdrawAmount2, 1, 100 * 10 ** 18); + slashAmount1 = bound(slashAmount1, 1, type(uint256).max / 2); + slashAmount2 = bound(slashAmount2, 1, type(uint256).max / 2); + captureAgo = bound(captureAgo, 1, 10 days); + vm.assume(depositAmount > withdrawAmount1 + withdrawAmount2); + vm.assume(depositAmount > slashAmount1); + vm.assume(captureAgo <= 7 days); + + uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + blockTimestamp = blockTimestamp + 1_720_700_948; + vm.warp(blockTimestamp); + + (iBTCVault, delegator, slasher) = _getVaultAndDelegatorAndSlasher(7 days); + + // address network = alice; + _registerNetwork(alice, alice); + _setMaxNetworkLimit(alice, 0, type(uint256).max); + + _registerOperator(alice); + _registerOperator(bob); + + _optInOperatorVault(alice); + _optInOperatorVault(bob); + + _optInOperatorNetwork(alice, address(alice)); + _optInOperatorNetwork(bob, address(alice)); + + _setNetworkLimit(alice, alice, type(uint256).max); + + _setOperatorNetworkLimit(alice, alice, alice, type(uint256).max / 2); + _setOperatorNetworkLimit(alice, alice, bob, type(uint256).max / 2); + + _deposit(alice, depositAmount); + _withdraw(alice, withdrawAmount1); + + blockTimestamp = blockTimestamp + iBTCVault.epochDuration(); + vm.warp(blockTimestamp); + + _withdraw(alice, withdrawAmount2); + + assertEq(iBTCVault.totalStake(), depositAmount); + assertEq(iBTCVault.activeStake(), depositAmount - withdrawAmount1 - withdrawAmount2); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch()), withdrawAmount1); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch() + 1), withdrawAmount2); + + blockTimestamp = blockTimestamp + 1; + vm.warp(blockTimestamp); + + Test_SlashStruct memory test_SlashStruct; + + if (iBTCVault.epochAt(uint48(blockTimestamp - captureAgo)) != iBTCVault.currentEpoch()) { + test_SlashStruct.slashAmountReal1 = Math.min(slashAmount1, depositAmount - withdrawAmount1); + test_SlashStruct.tokensBeforeBurner = collateral.balanceOf(address(iBTCVault.burner())); + assertEq( + _slash(alice, alice, alice, slashAmount1, uint48(blockTimestamp - captureAgo), ""), + test_SlashStruct.slashAmountReal1 + ); + assertEq( + collateral.balanceOf(address(iBTCVault.burner())) - test_SlashStruct.tokensBeforeBurner, + test_SlashStruct.slashAmountReal1 + ); + + test_SlashStruct.activeStake1 = depositAmount - withdrawAmount1 - withdrawAmount2 + - (depositAmount - withdrawAmount1 - withdrawAmount2).mulDiv( + test_SlashStruct.slashAmountReal1, depositAmount + ); + test_SlashStruct.withdrawals1 = + withdrawAmount1 - withdrawAmount1.mulDiv(test_SlashStruct.slashAmountReal1, depositAmount); + test_SlashStruct.nextWithdrawals1 = + withdrawAmount2 - withdrawAmount2.mulDiv(test_SlashStruct.slashAmountReal1, depositAmount); + assertEq(iBTCVault.totalStake(), depositAmount - test_SlashStruct.slashAmountReal1); + assertTrue(test_SlashStruct.withdrawals1 - iBTCVault.withdrawals(iBTCVault.currentEpoch()) <= 2); + assertTrue(test_SlashStruct.nextWithdrawals1 - iBTCVault.withdrawals(iBTCVault.currentEpoch() + 1) <= 1); + assertEq(iBTCVault.activeStake(), test_SlashStruct.activeStake1); + + test_SlashStruct.slashAmountSlashed2 = Math.min( + depositAmount - test_SlashStruct.slashAmountReal1, + Math.min(slashAmount2, depositAmount - withdrawAmount1) + ); + test_SlashStruct.tokensBeforeBurner = collateral.balanceOf(address(iBTCVault.burner())); + assertEq( + _slash(alice, alice, bob, slashAmount2, uint48(blockTimestamp - captureAgo), ""), + Math.min(slashAmount2, depositAmount - withdrawAmount1) + ); + assertEq( + collateral.balanceOf(address(iBTCVault.burner())) - test_SlashStruct.tokensBeforeBurner, + test_SlashStruct.slashAmountSlashed2 + ); + + assertEq( + iBTCVault.totalStake(), + depositAmount - test_SlashStruct.slashAmountReal1 - test_SlashStruct.slashAmountSlashed2 + ); + assertTrue( + ( + test_SlashStruct.withdrawals1 + - test_SlashStruct.withdrawals1.mulDiv( + test_SlashStruct.slashAmountSlashed2, depositAmount - test_SlashStruct.slashAmountReal1 + ) + ) - iBTCVault.withdrawals(iBTCVault.currentEpoch()) <= 4 + ); + assertTrue( + ( + test_SlashStruct.nextWithdrawals1 + - test_SlashStruct.nextWithdrawals1.mulDiv( + test_SlashStruct.slashAmountSlashed2, depositAmount - test_SlashStruct.slashAmountReal1 + ) + ) - iBTCVault.withdrawals(iBTCVault.currentEpoch() + 1) <= 2 + ); + assertEq( + iBTCVault.activeStake(), + test_SlashStruct.activeStake1 + - test_SlashStruct.activeStake1.mulDiv( + test_SlashStruct.slashAmountSlashed2, depositAmount - test_SlashStruct.slashAmountReal1 + ) + ); + } else { + test_SlashStruct.slashAmountReal1 = + Math.min(slashAmount1, depositAmount - withdrawAmount1 - withdrawAmount2); + test_SlashStruct.tokensBeforeBurner = collateral.balanceOf(address(iBTCVault.burner())); + assertEq( + _slash(alice, alice, alice, slashAmount1, uint48(blockTimestamp - captureAgo), ""), + test_SlashStruct.slashAmountReal1 + ); + assertEq( + collateral.balanceOf(address(iBTCVault.burner())) - test_SlashStruct.tokensBeforeBurner, + test_SlashStruct.slashAmountReal1 + ); + + test_SlashStruct.activeStake1 = depositAmount - withdrawAmount1 - withdrawAmount2 + - (depositAmount - withdrawAmount1 - withdrawAmount2).mulDiv( + test_SlashStruct.slashAmountReal1, depositAmount - withdrawAmount1 + ); + test_SlashStruct.withdrawals1 = withdrawAmount1; + test_SlashStruct.nextWithdrawals1 = withdrawAmount2 + - withdrawAmount2.mulDiv(test_SlashStruct.slashAmountReal1, depositAmount - withdrawAmount1); + assertEq(iBTCVault.totalStake(), depositAmount - test_SlashStruct.slashAmountReal1); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch()), test_SlashStruct.withdrawals1); + assertTrue(test_SlashStruct.nextWithdrawals1 - iBTCVault.withdrawals(iBTCVault.currentEpoch() + 1) <= 1); + assertEq(iBTCVault.activeStake(), test_SlashStruct.activeStake1); + + test_SlashStruct.slashAmountSlashed2 = Math.min( + depositAmount - withdrawAmount1 - test_SlashStruct.slashAmountReal1, + Math.min(slashAmount2, depositAmount - withdrawAmount1 - withdrawAmount2) + ); + test_SlashStruct.tokensBeforeBurner = collateral.balanceOf(address(iBTCVault.burner())); + assertEq( + _slash(alice, alice, bob, slashAmount2, uint48(blockTimestamp - captureAgo), ""), + Math.min(slashAmount2, depositAmount - withdrawAmount1 - withdrawAmount2) + ); + assertEq( + collateral.balanceOf(address(iBTCVault.burner())) - test_SlashStruct.tokensBeforeBurner, + test_SlashStruct.slashAmountSlashed2 + ); + + assertEq( + iBTCVault.totalStake(), + depositAmount - test_SlashStruct.slashAmountReal1 - test_SlashStruct.slashAmountSlashed2 + ); + assertEq(iBTCVault.withdrawals(iBTCVault.currentEpoch()), test_SlashStruct.withdrawals1); + assertTrue( + ( + test_SlashStruct.nextWithdrawals1 + - test_SlashStruct.nextWithdrawals1.mulDiv( + test_SlashStruct.slashAmountSlashed2, + depositAmount - withdrawAmount1 - test_SlashStruct.slashAmountReal1 + ) + ) - iBTCVault.withdrawals(iBTCVault.currentEpoch() + 1) <= 2 + ); + assertEq( + iBTCVault.activeStake(), + test_SlashStruct.activeStake1 + - test_SlashStruct.activeStake1.mulDiv( + test_SlashStruct.slashAmountSlashed2, + depositAmount - withdrawAmount1 - test_SlashStruct.slashAmountReal1 + ) + ); + } + } + + // struct GasStruct { + // uint256 gasSpent1; + // uint256 gasSpent2; + // } + + // struct HintStruct { + // uint256 num; + // bool back; + // uint256 secondsAgo; + // } + + // function test_ActiveSharesHint(uint256 amount1, uint48 epochDuration, HintStruct memory hintStruct) public { + // amount1 = bound(amount1, 1, 100 * 10 ** 18); + // epochDuration = uint48(bound(epochDuration, 1, 7 days)); + // hintStruct.num = bound(hintStruct.num, 0, 25); + // hintStruct.secondsAgo = bound(hintStruct.secondsAgo, 0, 1_720_700_948); + + // uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + // blockTimestamp = blockTimestamp + 1_720_700_948; + // vm.warp(blockTimestamp); + + // vault = _getVault(epochDuration); + + // for (uint256 i; i < hintStruct.num; ++i) { + // _deposit(alice, amount1); + + // blockTimestamp = blockTimestamp + epochDuration; + // vm.warp(blockTimestamp); + // } + + // uint48 timestamp = + // uint48(hintStruct.back ? blockTimestamp - hintStruct.secondsAgo : blockTimestamp + hintStruct.secondsAgo); + + // VaultHints vaultHints = new VaultHints(); + // bytes memory hint = vaultHints.activeSharesHint(address(vault), timestamp); + + // GasStruct memory gasStruct = GasStruct({gasSpent1: 1, gasSpent2: 1}); + // vault.activeSharesAt(timestamp, new bytes(0)); + // gasStruct.gasSpent1 = vm.lastCallGas().gasTotalUsed; + // vault.activeSharesAt(timestamp, hint); + // gasStruct.gasSpent2 = vm.lastCallGas().gasTotalUsed; + // assertApproxEqRel(gasStruct.gasSpent1, gasStruct.gasSpent2, 0.05e18); + // } + + // function test_ActiveStakeHint(uint256 amount1, uint48 epochDuration, HintStruct memory hintStruct) public { + // amount1 = bound(amount1, 1, 100 * 10 ** 18); + // epochDuration = uint48(bound(epochDuration, 1, 7 days)); + // hintStruct.num = bound(hintStruct.num, 0, 25); + // hintStruct.secondsAgo = bound(hintStruct.secondsAgo, 0, 1_720_700_948); + + // uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + // blockTimestamp = blockTimestamp + 1_720_700_948; + // vm.warp(blockTimestamp); + + // vault = _getVault(epochDuration); + + // for (uint256 i; i < hintStruct.num; ++i) { + // _deposit(alice, amount1); + + // blockTimestamp = blockTimestamp + epochDuration; + // vm.warp(blockTimestamp); + // } + + // uint48 timestamp = + // uint48(hintStruct.back ? blockTimestamp - hintStruct.secondsAgo : blockTimestamp + hintStruct.secondsAgo); + + // VaultHints vaultHints = new VaultHints(); + // bytes memory hint = vaultHints.activeStakeHint(address(vault), timestamp); + + // GasStruct memory gasStruct = GasStruct({gasSpent1: 1, gasSpent2: 1}); + // vault.activeStakeAt(timestamp, new bytes(0)); + // gasStruct.gasSpent1 = vm.lastCallGas().gasTotalUsed; + // vault.activeStakeAt(timestamp, hint); + // gasStruct.gasSpent2 = vm.lastCallGas().gasTotalUsed; + // assertGe(gasStruct.gasSpent1, gasStruct.gasSpent2); + // } + + // function test_ActiveSharesOfHint(uint256 amount1, uint48 epochDuration, HintStruct memory hintStruct) public { + // amount1 = bound(amount1, 1, 100 * 10 ** 18); + // epochDuration = uint48(bound(epochDuration, 1, 7 days)); + // hintStruct.num = bound(hintStruct.num, 0, 25); + // hintStruct.secondsAgo = bound(hintStruct.secondsAgo, 0, 1_720_700_948); + + // uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + // blockTimestamp = blockTimestamp + 1_720_700_948; + // vm.warp(blockTimestamp); + + // vault = _getVault(epochDuration); + + // for (uint256 i; i < hintStruct.num; ++i) { + // _deposit(alice, amount1); + + // blockTimestamp = blockTimestamp + epochDuration; + // vm.warp(blockTimestamp); + // } + + // uint48 timestamp = + // uint48(hintStruct.back ? blockTimestamp - hintStruct.secondsAgo : blockTimestamp + hintStruct.secondsAgo); + + // VaultHints vaultHints = new VaultHints(); + // bytes memory hint = vaultHints.activeSharesOfHint(address(vault), alice, timestamp); + + // GasStruct memory gasStruct = GasStruct({gasSpent1: 1, gasSpent2: 1}); + // vault.activeSharesOfAt(alice, timestamp, new bytes(0)); + // gasStruct.gasSpent1 = vm.lastCallGas().gasTotalUsed; + // vault.activeSharesOfAt(alice, timestamp, hint); + // gasStruct.gasSpent2 = vm.lastCallGas().gasTotalUsed; + // assertGe(gasStruct.gasSpent1, gasStruct.gasSpent2); + // } + + // struct ActiveBalanceOfHintsUint32 { + // uint32 activeSharesOfHint; + // uint32 activeStakeHint; + // uint32 activeSharesHint; + // } + + // function test_ActiveBalanceOfHint( + // uint256 amount1, + // uint48 epochDuration, + // HintStruct memory hintStruct, + // ActiveBalanceOfHintsUint32 memory activeBalanceOfHintsUint32 + // ) public { + // amount1 = bound(amount1, 1, 100 * 10 ** 18); + // epochDuration = uint48(bound(epochDuration, 1, 7 days)); + // hintStruct.num = bound(hintStruct.num, 0, 25); + // hintStruct.secondsAgo = bound(hintStruct.secondsAgo, 0, 1_720_700_948); + + // uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + // blockTimestamp = blockTimestamp + 1_720_700_948; + // vm.warp(blockTimestamp); + + // vault = _getVault(epochDuration); + + // for (uint256 i; i < hintStruct.num; ++i) { + // _deposit(alice, amount1); + + // blockTimestamp = blockTimestamp + epochDuration; + // vm.warp(blockTimestamp); + // } + + // uint48 timestamp = + // uint48(hintStruct.back ? blockTimestamp - hintStruct.secondsAgo : blockTimestamp + hintStruct.secondsAgo); + + // VaultHints vaultHints = new VaultHints(); + // bytes memory hint = vaultHints.activeBalanceOfHints(address(vault), alice, timestamp); + + // GasStruct memory gasStruct = GasStruct({gasSpent1: 1, gasSpent2: 1}); + // bytes memory activeBalanceOfHints = abi.encode( + // IVault.ActiveBalanceOfHints({ + // activeSharesOfHint: abi.encode(activeBalanceOfHintsUint32.activeSharesOfHint), + // activeStakeHint: abi.encode(activeBalanceOfHintsUint32.activeStakeHint), + // activeSharesHint: abi.encode(activeBalanceOfHintsUint32.activeSharesHint) + // }) + // ); + // try vault.activeBalanceOfAt(alice, timestamp, activeBalanceOfHints) { + // gasStruct.gasSpent1 = vm.lastCallGas().gasTotalUsed; + // } catch { + // vault.activeBalanceOfAt(alice, timestamp, ""); + // gasStruct.gasSpent1 = vm.lastCallGas().gasTotalUsed; + // } + + // vault.activeBalanceOfAt(alice, timestamp, hint); + // gasStruct.gasSpent2 = vm.lastCallGas().gasTotalUsed; + // assertGe(gasStruct.gasSpent1, gasStruct.gasSpent2); + // } + + // function test_ActiveBalanceOfHintMany( + // uint256 amount1, + // uint48 epochDuration, + // HintStruct memory hintStruct + // ) public { + // amount1 = bound(amount1, 1, 1 * 10 ** 18); + // epochDuration = uint48(bound(epochDuration, 1, 7 days)); + // hintStruct.num = 500; + // hintStruct.secondsAgo = bound(hintStruct.secondsAgo, 0, 1_720_700_948); + + // uint256 blockTimestamp = block.timestamp * block.timestamp / block.timestamp * block.timestamp / block.timestamp; + // blockTimestamp = blockTimestamp + 1_720_700_948; + // vm.warp(blockTimestamp); + + // vault = _getVault(epochDuration); + + // for (uint256 i; i < hintStruct.num; ++i) { + // _deposit(alice, amount1); + + // blockTimestamp = blockTimestamp + epochDuration; + // vm.warp(blockTimestamp); + // } + + // uint48 timestamp = + // uint48(hintStruct.back ? blockTimestamp - hintStruct.secondsAgo : blockTimestamp + hintStruct.secondsAgo); + + // VaultHints vaultHints = new VaultHints(); + // bytes memory hint = vaultHints.activeBalanceOfHints(address(vault), alice, timestamp); + + // GasStruct memory gasStruct = GasStruct({gasSpent1: 1, gasSpent2: 1}); + // vault.activeBalanceOfAt(alice, timestamp, ""); + // gasStruct.gasSpent1 = vm.lastCallGas().gasTotalUsed; + // vault.activeBalanceOfAt(alice, timestamp, hint); + // gasStruct.gasSpent2 = vm.lastCallGas().gasTotalUsed; + // assertGe(gasStruct.gasSpent1, gasStruct.gasSpent2); + + // assertLt(gasStruct.gasSpent1 - gasStruct.gasSpent2, 10_000); + // } + + function _getVault(uint48 epochDuration) internal returns (iBTC_Vault) { + address[] memory networkLimitSetRoleHolders = new address[](1); + networkLimitSetRoleHolders[0] = alice; + address[] memory operatorNetworkSharesSetRoleHolders = new address[](1); + operatorNetworkSharesSetRoleHolders[0] = alice; + (address vault_,,) = vaultConfigurator.create( + IVaultConfigurator.InitParams({ + version: vaultFactory.lastVersion(), + owner: alice, + vaultParams: abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: epochDuration, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ), + delegatorIndex: 0, + delegatorParams: abi.encode( + INetworkRestakeDelegator.InitParams({ + baseParams: IBaseDelegator.BaseParams({ + defaultAdminRoleHolder: alice, + hook: address(0), + hookSetRoleHolder: alice + }), + networkLimitSetRoleHolders: networkLimitSetRoleHolders, + operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders + }) + ), + withSlasher: false, + slasherIndex: 0, + slasherParams: abi.encode(ISlasher.InitParams({baseParams: IBaseSlasher.BaseParams({isBurnerHook: false})})) + }) + ); + + return iBTC_Vault(vault_); + } + + function _getVaultAndDelegatorAndSlasher(uint48 epochDuration) + internal + returns (iBTC_Vault, FullRestakeDelegator, Slasher) + { + address[] memory networkLimitSetRoleHolders = new address[](1); + networkLimitSetRoleHolders[0] = alice; + address[] memory operatorNetworkLimitSetRoleHolders = new address[](1); + operatorNetworkLimitSetRoleHolders[0] = alice; + (address vault_, address delegator_, address slasher_) = vaultConfigurator.create( + IVaultConfigurator.InitParams({ + version: vaultFactory.lastVersion(), + owner: alice, + vaultParams: abi.encode( + IVault.InitParams({ + collateral: address(collateral), + burner: address(0xdEaD), + epochDuration: epochDuration, + depositWhitelist: false, + isDepositLimit: false, + depositLimit: 0, + defaultAdminRoleHolder: alice, + depositWhitelistSetRoleHolder: alice, + depositorWhitelistRoleHolder: alice, + isDepositLimitSetRoleHolder: alice, + depositLimitSetRoleHolder: alice + }) + ), + delegatorIndex: 1, + delegatorParams: abi.encode( + IFullRestakeDelegator.InitParams({ + baseParams: IBaseDelegator.BaseParams({ + defaultAdminRoleHolder: alice, + hook: address(0), + hookSetRoleHolder: alice + }), + networkLimitSetRoleHolders: networkLimitSetRoleHolders, + operatorNetworkLimitSetRoleHolders: operatorNetworkLimitSetRoleHolders + }) + ), + withSlasher: true, + slasherIndex: 0, + slasherParams: abi.encode(ISlasher.InitParams({baseParams: IBaseSlasher.BaseParams({isBurnerHook: false})})) + }) + ); + + return (iBTC_Vault(vault_), FullRestakeDelegator(delegator_), Slasher(slasher_)); + } + + function _registerOperator(address user) internal { + vm.startPrank(user); + operatorRegistry.registerOperator(); + vm.stopPrank(); + } + + function _registerNetwork(address user, address middleware) internal { + vm.startPrank(user); + networkRegistry.registerNetwork(); + networkMiddlewareService.setMiddleware(middleware); + vm.stopPrank(); + } + + function _grantDepositorWhitelistRole(address user, address account) internal { + vm.startPrank(user); + iBTC_Vault(address(iBTCVault)).grantRole(iBTCVault.DEPOSITOR_WHITELIST_ROLE(), account); + vm.stopPrank(); + } + + function _grantDepositWhitelistSetRole(address user, address account) internal { + vm.startPrank(user); + iBTC_Vault(address(iBTCVault)).grantRole(iBTCVault.DEPOSIT_WHITELIST_SET_ROLE(), account); + vm.stopPrank(); + } + + function _grantIsDepositLimitSetRole(address user, address account) internal { + vm.startPrank(user); + iBTC_Vault(address(iBTCVault)).grantRole(iBTCVault.IS_DEPOSIT_LIMIT_SET_ROLE(), account); + vm.stopPrank(); + } + + function _grantDepositLimitSetRole(address user, address account) internal { + vm.startPrank(user); + iBTC_Vault(address(iBTCVault)).grantRole(iBTCVault.DEPOSIT_LIMIT_SET_ROLE(), account); + vm.stopPrank(); + } + + function _deposit(address user, uint256 amount) internal returns (uint256 depositedAmount, uint256 mintedShares) { + collateral.transfer(user, amount); + vm.startPrank(user); + collateral.approve(address(iBTCVault), amount); + (depositedAmount, mintedShares) = iBTCVault.deposit(user, amount); + vm.stopPrank(); + } + + function _withdraw(address user, uint256 amount) internal returns (uint256 burnedShares, uint256 mintedShares) { + vm.startPrank(user); + (burnedShares, mintedShares) = iBTCVault.withdraw(user, amount); + vm.stopPrank(); + } + + function _redeem(address user, uint256 shares) internal returns (uint256 withdrawnAssets, uint256 mintedShares) { + vm.startPrank(user); + (withdrawnAssets, mintedShares) = iBTCVault.redeem(user, shares); + vm.stopPrank(); + } + + function _claim(address user, uint256 epoch) internal returns (uint256 amount) { + vm.startPrank(user); + amount = iBTCVault.claim(user, epoch); + vm.stopPrank(); + } + + function _claimBatch(address user, uint256[] memory epochs) internal returns (uint256 amount) { + vm.startPrank(user); + amount = iBTCVault.claimBatch(user, epochs); + vm.stopPrank(); + } + + function _optInOperatorVault(address user) internal { + vm.startPrank(user); + operatorVaultOptInService.optIn(address(iBTCVault)); + vm.stopPrank(); + } + + function _optOutOperatorVault(address user) internal { + vm.startPrank(user); + operatorVaultOptInService.optOut(address(iBTCVault)); + vm.stopPrank(); + } + + function _optInOperatorNetwork(address user, address network) internal { + vm.startPrank(user); + operatorNetworkOptInService.optIn(network); + vm.stopPrank(); + } + + function _optOutOperatorNetwork(address user, address network) internal { + vm.startPrank(user); + operatorNetworkOptInService.optOut(network); + vm.stopPrank(); + } + + function _setDepositWhitelist(address user, bool status) internal { + vm.startPrank(user); + iBTCVault.setDepositWhitelist(status); + vm.stopPrank(); + } + + function _setDepositorWhitelistStatus(address user, address depositor, bool status) internal { + vm.startPrank(user); + iBTCVault.setDepositorWhitelistStatus(depositor, status); + vm.stopPrank(); + } + + function _setIsDepositLimit(address user, bool status) internal { + vm.startPrank(user); + iBTCVault.setIsDepositLimit(status); + vm.stopPrank(); + } + + function _setDepositLimit(address user, uint256 amount) internal { + vm.startPrank(user); + iBTCVault.setDepositLimit(amount); + vm.stopPrank(); + } + + function _setNetworkLimit(address user, address network, uint256 amount) internal { + vm.startPrank(user); + delegator.setNetworkLimit(network.subnetwork(0), amount); + vm.stopPrank(); + } + + function _setOperatorNetworkLimit(address user, address network, address operator, uint256 amount) internal { + vm.startPrank(user); + delegator.setOperatorNetworkLimit(network.subnetwork(0), operator, amount); + vm.stopPrank(); + } + + function _slash( + address user, + address network, + address operator, + uint256 amount, + uint48 captureTimestamp, + bytes memory hints + ) internal returns (uint256 slashAmount) { + vm.startPrank(user); + slashAmount = slasher.slash(network.subnetwork(0), operator, amount, captureTimestamp, hints); + vm.stopPrank(); + } + + function _setMaxNetworkLimit(address user, uint96 identifier, uint256 amount) internal { + vm.startPrank(user); + delegator.setMaxNetworkLimit(identifier, amount); + vm.stopPrank(); + } +} From 860e1bd8d20f59fb1d9b1858a92f367183641c39 Mon Sep 17 00:00:00 2001 From: Rayerleier <1045643889@qq.com> Date: Mon, 25 Nov 2024 21:49:31 +0800 Subject: [PATCH 2/7] added: test networkmiddleware still progressing... --- foundry.toml | 14 +-- src/iBTC_VaultConfigurator.sol | 6 +- test/iBTC_NetworkMiddleware.t.sol | 161 ++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 10 deletions(-) create mode 100644 test/iBTC_NetworkMiddleware.t.sol diff --git a/foundry.toml b/foundry.toml index 36686ca..0a71ad2 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,13 +1,13 @@ [profile.default] -solc = "0.8.25" -via_ir = true -src = "src" -out = "out" -libs = ["lib"] -ffi = true ast = true build_info = true extra_output = ["storageLayout"] +ffi = true +libs = ["lib"] +out = "out" +solc = "0.8.25" +src = "src" +via_ir = true [fmt] bracket_spacing = false @@ -18,4 +18,6 @@ number_underscore = "thousands" quote_style = "double" tab_width = 4 +[rpc_endpoints] # test on local anvil which forked sepolia +default = "http://127.0.0.1:8545" # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/src/iBTC_VaultConfigurator.sol b/src/iBTC_VaultConfigurator.sol index d021596..b87025e 100644 --- a/src/iBTC_VaultConfigurator.sol +++ b/src/iBTC_VaultConfigurator.sol @@ -6,7 +6,7 @@ import {DelegatorFactory} from "@symbiotic/contracts/DelegatorFactory.sol"; import {SlasherFactory} from "@symbiotic/contracts/SlasherFactory.sol"; import {VaultFactory} from "@symbiotic/contracts/VaultFactory.sol"; import {IVaultConfigurator} from "@symbiotic/interfaces/IVaultConfigurator.sol"; - +import {IVault} from "core/src/interfaces/vault/IVault.sol"; import {iBTC_Vault} from "./iBTC_Vault.sol"; contract VaultConfigurator is IVaultConfigurator { @@ -34,9 +34,7 @@ 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 new file mode 100644 index 0000000..5d3d034 --- /dev/null +++ b/test/iBTC_NetworkMiddleware.t.sol @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import "forge-std/Test.sol"; +import {console} from "forge-std/console.sol"; +import {NetworkMiddlewareService} from "core/src/contracts/service/NetworkMiddlewareService.sol"; +import {NetworkRegistry} from "core/src/contracts/NetworkRegistry.sol"; +import {NetworkMiddleware} from "src/iBTC_NetworkMiddleware.sol"; +import {iBTC_Vault} from "src/iBTC_Vault.sol"; +import {VaultConfigurator} from "src/iBTC_VaultConfigurator.sol"; +import {BurnerRouter} from "burners/src/contracts/router/BurnerRouter.sol"; +import {IVault} from "core/src/interfaces/vault/IVault.sol"; +import {INetworkRestakeDelegator} from "core/src/interfaces/delegator/INetworkRestakeDelegator.sol"; +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"; + +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 VAULT_FACTORY = 0x407A039D94948484D356eFB765b3c74382A050B4; + address constant DELEGATOR_FACTORY = 0x890CA3f95E0f40a79885B7400926544B2214B03f; + address constant SLASHER_FACTORY = 0xbf34bf75bb779c383267736c53a4ae86ac7bB299; + uint256 constant MAX_WITHDRAW_AMOUNT = 1e9; // 10 iBTC + uint256 constant MIN_WITHDRAW_AMOUNT = 1e4; + + // Using anvil's default addresses + address constant NETWORK = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; // first address + address constant OWNER = 0x70997970C51812dc3A010C7d01b50e0d17dc79C8; // second address + uint48 constant EPOCH_DURATION = 7 days; + uint48 constant SLASHING_WINDOW = 8 days; + + // Initial operators and their keys (if any) + address[] operators; + bytes32[] keys; + + // Initial vaults (if any) + address[] vaults; + + NetworkMiddleware public iBTC_middleware; + BurnerRouter public burner; + VaultConfigurator public vaultConfigurator; + iBTC_Vault public iBTC_vault; + + function setup() public { + address[] memory whitelistedDepositors; + + uint256 depositLimit = 1e10; // 100iBTC + address hook = 0x0000000000000000000000000000000000000000; + uint64 delegatorIndex = 0; // NetworkRestakeDelegator + uint64 slasherIndex = 1; // vetoSlasher + 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(); + + bool depositWhitelist = whitelistedDepositors.length != 0; + + bytes memory vaultParams = abi.encode( + IVault.InitParams({ + collateral: COLLATTERAL, + burner: address(burner), + epochDuration: EPOCH_DURATION, + depositWhitelist: depositWhitelist, + isDepositLimit: depositLimit != 0, + depositLimit: depositLimit, + defaultAdminRoleHolder: depositWhitelist ? deployer : OWNER, + depositWhitelistSetRoleHolder: OWNER, + depositorWhitelistRoleHolder: OWNER, + isDepositLimitSetRoleHolder: OWNER, + depositLimitSetRoleHolder: OWNER + }) + ); + uint256 roleHolders = 1; + address[] memory networkLimitSetRoleHolders = new address[](roleHolders); + address[] memory operatorNetworkLimitSetRoleHolders = new address[](roleHolders); + address[] memory operatorNetworkSharesSetRoleHolders = new address[](roleHolders); + networkLimitSetRoleHolders[0] = OWNER; + 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}), + networkLimitSetRoleHolders: networkLimitSetRoleHolders, + operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders + }) + ); + bytes memory slasherParams; + // slasherIndex =1, VetoSlash + slasherParams = abi.encode( + IVetoSlasher.InitParams({ + baseParams: IBaseSlasher.BaseParams({isBurnerHook: address(burner) != address(0)}), + vetoDuration: vetoDuration, + resolverSetEpochsDelay: 3 + }) + ); + (address vault_, address delegator_, address slasher_) = IVaultConfigurator(vaultConfigurator).create( + IVaultConfigurator.InitParams({ + version: 1, + owner: OWNER, + vaultParams: vaultParams, + delegatorIndex: delegatorIndex, + delegatorParams: delegatorParams, + withSlasher: withSlasher, + slasherIndex: slasherIndex, + slasherParams: slasherParams + }) + ); + + if (depositWhitelist) { + iBTC_Vault(vault_).grantRole(iBTC_Vault(vault_).DEFAULT_ADMIN_ROLE(), OWNER); + iBTC_Vault(vault_).grantRole(iBTC_Vault(vault_).DEPOSITOR_WHITELIST_ROLE(), deployer); + + for (uint256 i; i < whitelistedDepositors.length; ++i) { + iBTC_Vault(vault_).setDepositorWhitelistStatus(whitelistedDepositors[i], true); + } + + 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 + + vaults.push(vault_); + iBTC_middleware = new NetworkMiddleware( + NETWORK, OPERATOR_REGISTRY, NETWORK_REGISTRY, NETWORK_OPTIN, OWNER, EPOCH_DURATION, SLASHING_WINDOW + ); + for (uint256 i = 0; i < vaults.length; ++i) { + iBTC_middleware.registerVault(vaults[i]); + } + + for (uint256 i = 0; i < operators.length; ++i) { + iBTC_middleware.registerOperator(operators[i], keys[i]); + } + vm.stopPrank(); + console.log("Vault: ", vault_); + console.log("Delegator: ", delegator_); + console.log("Slasher: ", slasher_); + + vm.startPrank(address(iBTC_middleware)); + NetworkRegistry(0x7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9).registerNetwork(); + NetworkMiddlewareService(0x62a1ddfD86b4c1636759d9286D3A0EC722D086e3).setMiddleware(address(iBTC_middleware)); + vm.stopPrank(); + } + + function testRegisterOperator() public { + for operator in operators{ + + } + } +} From 8ce2bd7260684154c0c90ee25f4f184c08bd252f Mon Sep 17 00:00:00 2001 From: Rayer <52488361+Rayerleier@users.noreply.github.com> Date: Tue, 26 Nov 2024 16:52:53 +0800 Subject: [PATCH 3/7] Update iBTC_NetworkMiddleware.sol From 11614f28b04629750af927223528f2e4e811ba5c Mon Sep 17 00:00:00 2001 From: Rayer <52488361+Rayerleier@users.noreply.github.com> Date: Tue, 26 Nov 2024 16:53:07 +0800 Subject: [PATCH 4/7] Delete test/iBTC_NetworkMiddleware.t.sol --- test/iBTC_NetworkMiddleware.t.sol | 161 ------------------------------ 1 file changed, 161 deletions(-) delete mode 100644 test/iBTC_NetworkMiddleware.t.sol diff --git a/test/iBTC_NetworkMiddleware.t.sol b/test/iBTC_NetworkMiddleware.t.sol deleted file mode 100644 index 5d3d034..0000000 --- a/test/iBTC_NetworkMiddleware.t.sol +++ /dev/null @@ -1,161 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.25; - -import "forge-std/Test.sol"; -import {console} from "forge-std/console.sol"; -import {NetworkMiddlewareService} from "core/src/contracts/service/NetworkMiddlewareService.sol"; -import {NetworkRegistry} from "core/src/contracts/NetworkRegistry.sol"; -import {NetworkMiddleware} from "src/iBTC_NetworkMiddleware.sol"; -import {iBTC_Vault} from "src/iBTC_Vault.sol"; -import {VaultConfigurator} from "src/iBTC_VaultConfigurator.sol"; -import {BurnerRouter} from "burners/src/contracts/router/BurnerRouter.sol"; -import {IVault} from "core/src/interfaces/vault/IVault.sol"; -import {INetworkRestakeDelegator} from "core/src/interfaces/delegator/INetworkRestakeDelegator.sol"; -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"; - -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 VAULT_FACTORY = 0x407A039D94948484D356eFB765b3c74382A050B4; - address constant DELEGATOR_FACTORY = 0x890CA3f95E0f40a79885B7400926544B2214B03f; - address constant SLASHER_FACTORY = 0xbf34bf75bb779c383267736c53a4ae86ac7bB299; - uint256 constant MAX_WITHDRAW_AMOUNT = 1e9; // 10 iBTC - uint256 constant MIN_WITHDRAW_AMOUNT = 1e4; - - // Using anvil's default addresses - address constant NETWORK = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; // first address - address constant OWNER = 0x70997970C51812dc3A010C7d01b50e0d17dc79C8; // second address - uint48 constant EPOCH_DURATION = 7 days; - uint48 constant SLASHING_WINDOW = 8 days; - - // Initial operators and their keys (if any) - address[] operators; - bytes32[] keys; - - // Initial vaults (if any) - address[] vaults; - - NetworkMiddleware public iBTC_middleware; - BurnerRouter public burner; - VaultConfigurator public vaultConfigurator; - iBTC_Vault public iBTC_vault; - - function setup() public { - address[] memory whitelistedDepositors; - - uint256 depositLimit = 1e10; // 100iBTC - address hook = 0x0000000000000000000000000000000000000000; - uint64 delegatorIndex = 0; // NetworkRestakeDelegator - uint64 slasherIndex = 1; // vetoSlasher - 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(); - - bool depositWhitelist = whitelistedDepositors.length != 0; - - bytes memory vaultParams = abi.encode( - IVault.InitParams({ - collateral: COLLATTERAL, - burner: address(burner), - epochDuration: EPOCH_DURATION, - depositWhitelist: depositWhitelist, - isDepositLimit: depositLimit != 0, - depositLimit: depositLimit, - defaultAdminRoleHolder: depositWhitelist ? deployer : OWNER, - depositWhitelistSetRoleHolder: OWNER, - depositorWhitelistRoleHolder: OWNER, - isDepositLimitSetRoleHolder: OWNER, - depositLimitSetRoleHolder: OWNER - }) - ); - uint256 roleHolders = 1; - address[] memory networkLimitSetRoleHolders = new address[](roleHolders); - address[] memory operatorNetworkLimitSetRoleHolders = new address[](roleHolders); - address[] memory operatorNetworkSharesSetRoleHolders = new address[](roleHolders); - networkLimitSetRoleHolders[0] = OWNER; - 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}), - networkLimitSetRoleHolders: networkLimitSetRoleHolders, - operatorNetworkSharesSetRoleHolders: operatorNetworkSharesSetRoleHolders - }) - ); - bytes memory slasherParams; - // slasherIndex =1, VetoSlash - slasherParams = abi.encode( - IVetoSlasher.InitParams({ - baseParams: IBaseSlasher.BaseParams({isBurnerHook: address(burner) != address(0)}), - vetoDuration: vetoDuration, - resolverSetEpochsDelay: 3 - }) - ); - (address vault_, address delegator_, address slasher_) = IVaultConfigurator(vaultConfigurator).create( - IVaultConfigurator.InitParams({ - version: 1, - owner: OWNER, - vaultParams: vaultParams, - delegatorIndex: delegatorIndex, - delegatorParams: delegatorParams, - withSlasher: withSlasher, - slasherIndex: slasherIndex, - slasherParams: slasherParams - }) - ); - - if (depositWhitelist) { - iBTC_Vault(vault_).grantRole(iBTC_Vault(vault_).DEFAULT_ADMIN_ROLE(), OWNER); - iBTC_Vault(vault_).grantRole(iBTC_Vault(vault_).DEPOSITOR_WHITELIST_ROLE(), deployer); - - for (uint256 i; i < whitelistedDepositors.length; ++i) { - iBTC_Vault(vault_).setDepositorWhitelistStatus(whitelistedDepositors[i], true); - } - - 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 - - vaults.push(vault_); - iBTC_middleware = new NetworkMiddleware( - NETWORK, OPERATOR_REGISTRY, NETWORK_REGISTRY, NETWORK_OPTIN, OWNER, EPOCH_DURATION, SLASHING_WINDOW - ); - for (uint256 i = 0; i < vaults.length; ++i) { - iBTC_middleware.registerVault(vaults[i]); - } - - for (uint256 i = 0; i < operators.length; ++i) { - iBTC_middleware.registerOperator(operators[i], keys[i]); - } - vm.stopPrank(); - console.log("Vault: ", vault_); - console.log("Delegator: ", delegator_); - console.log("Slasher: ", slasher_); - - vm.startPrank(address(iBTC_middleware)); - NetworkRegistry(0x7d03b7343BF8d5cEC7C0C27ecE084a20113D15C9).registerNetwork(); - NetworkMiddlewareService(0x62a1ddfD86b4c1636759d9286D3A0EC722D086e3).setMiddleware(address(iBTC_middleware)); - vm.stopPrank(); - } - - function testRegisterOperator() public { - for operator in operators{ - - } - } -} From fa8fcd1118bc758b1fe393c2283c0c0fe29c97e7 Mon Sep 17 00:00:00 2001 From: Rayerleier <1045643889@qq.com> Date: Tue, 26 Nov 2024 17:51:46 +0800 Subject: [PATCH 5/7] fmt --- src/dlc-core/DLCManager.sol | 100 ++++++------------------ src/dlc-core/IBTC.sol | 12 +-- src/iBTC_Burner.sol | 4 +- src/iBTC_NetworkMiddleware.sol | 56 ++++--------- src/iBTC_Treasury.sol | 16 +--- src/iBTC_Vault.sol | 32 ++------ src/iBTC_VaultConfigurator.sol | 4 +- src/interfaces/IiBTC_Burner.sol | 4 +- src/interfaces/IiBTC_Treasury.sol | 12 +-- src/libraries/AggregatorV3Interface.sol | 4 +- src/libraries/Counter.sol | 16 +--- src/libraries/SimpleKeyRegistry32.sol | 8 +- test/mocks/MapWithTimeDataContract.sol | 20 ++--- 13 files changed, 72 insertions(+), 216 deletions(-) diff --git a/src/dlc-core/DLCManager.sol b/src/dlc-core/DLCManager.sol index 63d5477..c61d3b8 100644 --- a/src/dlc-core/DLCManager.sol +++ b/src/dlc-core/DLCManager.sol @@ -124,9 +124,7 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, _; } - modifier onlyVaultCreator( - bytes32 _uuid - ) { + modifier onlyVaultCreator(bytes32 _uuid) { if (dlcs[dlcIDsByUUID[_uuid]].creator != msg.sender) revert NotOwner(); _; } @@ -269,9 +267,7 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, * @param proposedTotalValueMinted proposed total minted value in all vaults on this chain. * @return bool whether the proposed total value minted is within bounds. */ - function _checkPoR( - uint256 proposedTotalValueMinted - ) internal view returns (bool) { + function _checkPoR(uint256 proposedTotalValueMinted) internal view returns (bool) { if (!porEnabled) { return true; } @@ -446,18 +442,14 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, // VIEW FUNCTIONS // //////////////////////////////////////////////////////////////// - function getDLC( - bytes32 uuid - ) public view returns (DLCLink.DLC memory) { + function getDLC(bytes32 uuid) public view returns (DLCLink.DLC memory) { DLCLink.DLC memory _dlc = dlcs[dlcIDsByUUID[uuid]]; if (_dlc.uuid == bytes32(0)) revert DLCNotFound(); if (_dlc.uuid != uuid) revert DLCNotFound(); return _dlc; } - function getDLCByIndex( - uint256 index - ) external view returns (DLCLink.DLC memory) { + function getDLCByIndex(uint256 index) external view returns (DLCLink.DLC memory) { return dlcs[index]; } @@ -480,21 +472,15 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, return dlcSubset; } - function getVault( - bytes32 uuid - ) public view returns (DLCLink.DLC memory) { + function getVault(bytes32 uuid) public view returns (DLCLink.DLC memory) { return getDLC(uuid); } - function getAllVaultUUIDsForAddress( - address owner - ) public view returns (bytes32[] memory) { + function getAllVaultUUIDsForAddress(address owner) public view returns (bytes32[] memory) { return userVaults[owner]; } - function getAllVaultsForAddress( - address owner - ) public view returns (DLCLink.DLC[] memory) { + function getAllVaultsForAddress(address owner) public view returns (DLCLink.DLC[] memory) { bytes32[] memory uuids = getAllVaultUUIDsForAddress(owner); DLCLink.DLC[] memory vaults = new DLCLink.DLC[](uuids.length); for (uint256 i = 0; i < uuids.length; i++) { @@ -503,9 +489,7 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, return vaults; } - function isWhitelisted( - address account - ) external view returns (bool) { + function isWhitelisted(address account) external view returns (bool) { return _whitelistedAddresses[account]; } @@ -525,9 +509,7 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, // ADMIN FUNCTIONS // //////////////////////////////////////////////////////////////// - function _hasAnyRole( - address account - ) internal view returns (bool) { + function _hasAnyRole(address account) internal view returns (bool) { return hasRole(DLC_ADMIN_ROLE, account) || hasRole(WHITELISTED_CONTRACT, account) || hasRole(APPROVED_SIGNER, account); } @@ -566,9 +548,7 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, _unpause(); } - function setThreshold( - uint16 newThreshold - ) external onlyAdmin { + function setThreshold(uint16 newThreshold) external onlyAdmin { if (newThreshold < _minimumThreshold) { revert ThresholdTooLow(_minimumThreshold); } @@ -576,49 +556,35 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, emit SetThreshold(newThreshold); } - function setTSSCommitment( - bytes32 commitment - ) external onlyAdmin { + function setTSSCommitment(bytes32 commitment) external onlyAdmin { tssCommitment = commitment; } - function setAttestorGroupPubKey( - string calldata pubKey - ) external onlyAdmin { + function setAttestorGroupPubKey(string calldata pubKey) external onlyAdmin { attestorGroupPubKey = pubKey; } - function whitelistAddress( - address addressToWhitelist - ) external onlyAdmin { + function whitelistAddress(address addressToWhitelist) external onlyAdmin { _whitelistedAddresses[addressToWhitelist] = true; emit WhitelistAddress(addressToWhitelist); } - function unwhitelistAddress( - address addressToUnWhitelist - ) external onlyAdmin { + function unwhitelistAddress(address addressToUnWhitelist) external onlyAdmin { _whitelistedAddresses[addressToUnWhitelist] = false; emit UnwhitelistAddress(addressToUnWhitelist); } - function setMinimumDeposit( - uint256 newMinimumDeposit - ) external onlyAdmin { + function setMinimumDeposit(uint256 newMinimumDeposit) external onlyAdmin { minimumDeposit = newMinimumDeposit; emit SetMinimumDeposit(newMinimumDeposit); } - function setMaximumDeposit( - uint256 newMaximumDeposit - ) external onlyAdmin { + function setMaximumDeposit(uint256 newMaximumDeposit) external onlyAdmin { maximumDeposit = newMaximumDeposit; emit SetMaximumDeposit(newMaximumDeposit); } - function setBtcMintFeeRate( - uint256 newBtcMintFeeRate - ) external onlyAdmin { + function setBtcMintFeeRate(uint256 newBtcMintFeeRate) external onlyAdmin { if (newBtcMintFeeRate > 10_000) { revert FeeRateOutOfBounds(newBtcMintFeeRate); } @@ -626,16 +592,12 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, emit SetBtcMintFeeRate(newBtcMintFeeRate); } - function setBtcRedeemFeeRate( - uint256 newBtcRedeemFeeRate - ) external onlyAdmin { + function setBtcRedeemFeeRate(uint256 newBtcRedeemFeeRate) external onlyAdmin { btcRedeemFeeRate = newBtcRedeemFeeRate; emit SetBtcRedeemFeeRate(newBtcRedeemFeeRate); } - function setBtcFeeRecipient( - string calldata btcFeeRecipientToSet - ) external onlyAdmin { + function setBtcFeeRecipient(string calldata btcFeeRecipientToSet) external onlyAdmin { btcFeeRecipient = btcFeeRecipientToSet; emit SetBtcFeeRecipient(btcFeeRecipient); } @@ -645,42 +607,30 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, dlc.btcFeeRecipient = btcFeeRecipientToSet; } - function setWhitelistingEnabled( - bool isWhitelistingEnabled - ) external onlyAdmin { + function setWhitelistingEnabled(bool isWhitelistingEnabled) external onlyAdmin { whitelistingEnabled = isWhitelistingEnabled; emit SetWhitelistingEnabled(isWhitelistingEnabled); } - function transferTokenContractOwnership( - address newOwner - ) external onlyAdmin { + function transferTokenContractOwnership(address newOwner) external onlyAdmin { dlcBTC.transferOwnership(newOwner); emit TransferTokenContractOwnership(newOwner); } - function setMinterOnTokenContract( - address minter - ) external onlyAdmin { + function setMinterOnTokenContract(address minter) external onlyAdmin { dlcBTC.setMinter(minter); } - function setBurnerOnTokenContract( - address burner - ) external onlyAdmin { + function setBurnerOnTokenContract(address burner) external onlyAdmin { dlcBTC.setBurner(burner); } - function setPorEnabled( - bool enabled - ) external onlyAdmin { + function setPorEnabled(bool enabled) external onlyAdmin { porEnabled = enabled; emit SetPorEnabled(enabled); } - function setDlcBTCPoRFeed( - AggregatorV3Interface feed - ) external onlyAdmin { + function setDlcBTCPoRFeed(AggregatorV3Interface feed) external onlyAdmin { dlcBTCPoRFeed = feed; emit SetDlcBTCPoRFeed(feed); } diff --git a/src/dlc-core/IBTC.sol b/src/dlc-core/IBTC.sol index 5066d6e..9871c5c 100644 --- a/src/dlc-core/IBTC.sol +++ b/src/dlc-core/IBTC.sol @@ -85,22 +85,16 @@ contract IBTC is Initializable, ERC20Upgradeable, ERC20PermitUpgradeable, Ownabl _burn(from, amount); } - function burn( - uint256 amount - ) external onlyCCIPBurner { + function burn(uint256 amount) external onlyCCIPBurner { _burn(msg.sender, amount); } - function setMinter( - address minter - ) external onlyOwner { + function setMinter(address minter) external onlyOwner { _minter = minter; emit MinterSet(minter); } - function setBurner( - address burner - ) external onlyOwner { + function setBurner(address burner) external onlyOwner { _burner = burner; emit BurnerSet(burner); } diff --git a/src/iBTC_Burner.sol b/src/iBTC_Burner.sol index 9107675..84d2c87 100644 --- a/src/iBTC_Burner.sol +++ b/src/iBTC_Burner.sol @@ -30,9 +30,7 @@ contract iBTC_Burner is UintRequests, IiBTC_Burner, IERC721Receiver { * This function triggers a withdrawal by creating one or more withdrawal requests. * It splits the total collateral balance into multiple requests based on the maximum withdrawal limit. */ - function triggerWithdrawal( - uint256 maxRequests - ) external returns (uint256 firstRequestId, uint256 lastRequestId) { + function triggerWithdrawal(uint256 maxRequests) external returns (uint256 firstRequestId, uint256 lastRequestId) { // Get the current balance of the COLLATERAL token held by this contract uint256 amount = IERC20(Collateral).balanceOf(address(this)); diff --git a/src/iBTC_NetworkMiddleware.sol b/src/iBTC_NetworkMiddleware.sol index 71c48d2..6826462 100644 --- a/src/iBTC_NetworkMiddleware.sol +++ b/src/iBTC_NetworkMiddleware.sol @@ -66,9 +66,7 @@ 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); } @@ -98,15 +96,11 @@ 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; } @@ -141,21 +135,15 @@ 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()) { @@ -165,9 +153,7 @@ 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(); } @@ -191,21 +177,15 @@ 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()) { @@ -237,18 +217,14 @@ 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()); @@ -315,9 +291,7 @@ 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) @@ -347,9 +321,7 @@ 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_Treasury.sol b/src/iBTC_Treasury.sol index 9b782c2..c3a2184 100644 --- a/src/iBTC_Treasury.sol +++ b/src/iBTC_Treasury.sol @@ -62,9 +62,7 @@ contract iBTC_Treasury is ERC721, Ownable { * @dev Allows users to create a withdrawal request. * Transfers collateral from the caller to the treasury and mints an ERC721 token. */ - function createWithdrawRequest( - uint256 amount - ) external { + function createWithdrawRequest(uint256 amount) external { require(amount >= minWithdrawAmount, "Amount below minimum limit"); require(amount <= maxWithdrawAmount, "Amount exceeds maximum limit"); @@ -88,9 +86,7 @@ contract iBTC_Treasury is ERC721, Ownable { * @dev Finalizes a withdrawal request and burns the corresponding token. * Transfers the collateral back to the token owner. */ - function finalizeWithdrawal( - uint256 requestId - ) external onlyOwner { + function finalizeWithdrawal(uint256 requestId) external onlyOwner { require(!finalizedWithdrawals[requestId], "Already finalized"); address requester = ownerOf(requestId); @@ -113,9 +109,7 @@ contract iBTC_Treasury is ERC721, Ownable { * @dev Batch process withdrawals up to a specified token ID. * Only callable by the contract owner. */ - function processWithdrawals( - uint256 _lastrequestIdToProcess - ) external onlyOwner { + function processWithdrawals(uint256 _lastrequestIdToProcess) external onlyOwner { for (uint256 requestId = 1; requestId <= _lastrequestIdToProcess; requestId++) { if (_exits(requestId) && !finalizedWithdrawals[requestId]) { address requester = ownerOf(requestId); @@ -139,9 +133,7 @@ contract iBTC_Treasury is ERC721, Ownable { return minWithdrawAmount; } - function _exits( - uint256 requestId - ) internal view returns (bool) { + function _exits(uint256 requestId) internal view returns (bool) { return ownerOf(requestId) != address(0); } } diff --git a/src/iBTC_Vault.sol b/src/iBTC_Vault.sol index 5d58e47..19e7f6e 100644 --- a/src/iBTC_Vault.sol +++ b/src/iBTC_Vault.sol @@ -62,9 +62,7 @@ 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()); } @@ -79,9 +77,7 @@ 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); } @@ -266,9 +262,7 @@ 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(); } @@ -301,9 +295,7 @@ 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(); } @@ -316,9 +308,7 @@ 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(); } @@ -328,9 +318,7 @@ 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(); } @@ -350,9 +338,7 @@ 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(); } @@ -396,9 +382,7 @@ 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 d021596..7c5787e 100644 --- a/src/iBTC_VaultConfigurator.sol +++ b/src/iBTC_VaultConfigurator.sol @@ -34,9 +34,7 @@ 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/src/interfaces/IiBTC_Burner.sol b/src/interfaces/IiBTC_Burner.sol index 30f930e..b024191 100644 --- a/src/interfaces/IiBTC_Burner.sol +++ b/src/interfaces/IiBTC_Burner.sol @@ -30,7 +30,5 @@ interface IiBTC_Burner is IUintRequests { * @return firstRequestId first request ID that was created * @return lastRequestId last request ID that was created */ - function triggerWithdrawal( - uint256 maxRequests - ) external returns (uint256 firstRequestId, uint256 lastRequestId); + function triggerWithdrawal(uint256 maxRequests) external returns (uint256 firstRequestId, uint256 lastRequestId); } diff --git a/src/interfaces/IiBTC_Treasury.sol b/src/interfaces/IiBTC_Treasury.sol index b17740e..06a8146 100644 --- a/src/interfaces/IiBTC_Treasury.sol +++ b/src/interfaces/IiBTC_Treasury.sol @@ -8,15 +8,9 @@ interface IiBTC_Treasury { function withdrawRequestMinimum() external view returns (uint256); - function processWithdrawals( - uint256 _lastTokenIdToProcess - ) external; + function processWithdrawals(uint256 _lastTokenIdToProcess) external; - function createWithdrawRequest( - uint256 amount - ) external; + function createWithdrawRequest(uint256 amount) external; - function finalizeWithdrawal( - uint256 tokenId - ) external; + function finalizeWithdrawal(uint256 tokenId) external; } diff --git a/src/libraries/AggregatorV3Interface.sol b/src/libraries/AggregatorV3Interface.sol index 2062677..81b2aff 100644 --- a/src/libraries/AggregatorV3Interface.sol +++ b/src/libraries/AggregatorV3Interface.sol @@ -9,9 +9,7 @@ interface AggregatorV3Interface { function version() external view returns (uint256); - function getRoundData( - uint80 _roundId - ) + function getRoundData(uint80 _roundId) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); diff --git a/src/libraries/Counter.sol b/src/libraries/Counter.sol index 3631f01..ece483e 100644 --- a/src/libraries/Counter.sol +++ b/src/libraries/Counter.sol @@ -6,23 +6,17 @@ library Counters { uint256 _value; // Default: 0 } - function current( - Counter storage counter - ) internal view returns (uint256) { + function current(Counter storage counter) internal view returns (uint256) { return counter._value; } - function increment( - Counter storage counter - ) internal { + function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } - function decrement( - Counter storage counter - ) internal { + function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { @@ -30,9 +24,7 @@ library Counters { } } - function reset( - Counter storage counter - ) internal { + function reset(Counter storage counter) internal { counter._value = 0; } } diff --git a/src/libraries/SimpleKeyRegistry32.sol b/src/libraries/SimpleKeyRegistry32.sol index 5255d8f..90f5de6 100644 --- a/src/libraries/SimpleKeyRegistry32.sol +++ b/src/libraries/SimpleKeyRegistry32.sol @@ -18,15 +18,11 @@ abstract contract SimpleKeyRegistry32 { uint208 internal constant EMPTY_KEY_IDX = 0; - function getOperatorByKey( - bytes32 key - ) public view returns (address) { + function getOperatorByKey(bytes32 key) public view returns (address) { return keyToOperator[key]; } - function getCurrentOperatorKey( - address operator - ) public view returns (bytes32) { + function getCurrentOperatorKey(address operator) public view returns (bytes32) { uint208 keyIdx = operatorToIdx[operator].latest(); if (keyIdx == EMPTY_KEY_IDX) { diff --git a/test/mocks/MapWithTimeDataContract.sol b/test/mocks/MapWithTimeDataContract.sol index 615d5ba..a53d8bf 100644 --- a/test/mocks/MapWithTimeDataContract.sol +++ b/test/mocks/MapWithTimeDataContract.sol @@ -11,33 +11,23 @@ contract MapWithTimeDataContract { EnumerableMap.AddressToUintMap internal elements; - function add( - address addr - ) public { + function add(address addr) public { elements.add(addr); } - function disable( - address addr - ) public { + function disable(address addr) public { elements.disable(addr); } - function enable( - address addr - ) public { + function enable(address addr) public { elements.enable(addr); } - function atWithTimes( - uint256 idx - ) public view returns (address key, uint48 enabledTime, uint48 disabledTime) { + function atWithTimes(uint256 idx) public view returns (address key, uint48 enabledTime, uint48 disabledTime) { return elements.atWithTimes(idx); } - function getTimes( - address addr - ) public view returns (uint48 enabledTime, uint48 disabledTime) { + function getTimes(address addr) public view returns (uint48 enabledTime, uint48 disabledTime) { return elements.getTimes(addr); } From 640125d39064e2cbc8eda1dec0ec6110819cadf4 Mon Sep 17 00:00:00 2001 From: Rayerleier <1045643889@qq.com> Date: Tue, 26 Nov 2024 18:29:15 +0800 Subject: [PATCH 6/7] fmt --- src/dlc-core/DLCManager.sol | 100 ++++++++++++++++++------ src/dlc-core/IBTC.sol | 12 ++- src/iBTC_Burner.sol | 4 +- src/iBTC_NetworkMiddleware.sol | 56 +++++++++---- src/iBTC_Treasury.sol | 16 +++- src/iBTC_Vault.sol | 32 ++++++-- src/iBTC_VaultConfigurator.sol | 4 +- src/interfaces/IiBTC_Burner.sol | 4 +- src/interfaces/IiBTC_Treasury.sol | 12 ++- src/libraries/AggregatorV3Interface.sol | 4 +- src/libraries/Counter.sol | 16 +++- src/libraries/SimpleKeyRegistry32.sol | 8 +- test/iBTC_Vault.t.sol | 83 ++++++++++++++------ test/mocks/MapWithTimeDataContract.sol | 20 +++-- 14 files changed, 276 insertions(+), 95 deletions(-) diff --git a/src/dlc-core/DLCManager.sol b/src/dlc-core/DLCManager.sol index c61d3b8..63d5477 100644 --- a/src/dlc-core/DLCManager.sol +++ b/src/dlc-core/DLCManager.sol @@ -124,7 +124,9 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, _; } - modifier onlyVaultCreator(bytes32 _uuid) { + modifier onlyVaultCreator( + bytes32 _uuid + ) { if (dlcs[dlcIDsByUUID[_uuid]].creator != msg.sender) revert NotOwner(); _; } @@ -267,7 +269,9 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, * @param proposedTotalValueMinted proposed total minted value in all vaults on this chain. * @return bool whether the proposed total value minted is within bounds. */ - function _checkPoR(uint256 proposedTotalValueMinted) internal view returns (bool) { + function _checkPoR( + uint256 proposedTotalValueMinted + ) internal view returns (bool) { if (!porEnabled) { return true; } @@ -442,14 +446,18 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, // VIEW FUNCTIONS // //////////////////////////////////////////////////////////////// - function getDLC(bytes32 uuid) public view returns (DLCLink.DLC memory) { + function getDLC( + bytes32 uuid + ) public view returns (DLCLink.DLC memory) { DLCLink.DLC memory _dlc = dlcs[dlcIDsByUUID[uuid]]; if (_dlc.uuid == bytes32(0)) revert DLCNotFound(); if (_dlc.uuid != uuid) revert DLCNotFound(); return _dlc; } - function getDLCByIndex(uint256 index) external view returns (DLCLink.DLC memory) { + function getDLCByIndex( + uint256 index + ) external view returns (DLCLink.DLC memory) { return dlcs[index]; } @@ -472,15 +480,21 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, return dlcSubset; } - function getVault(bytes32 uuid) public view returns (DLCLink.DLC memory) { + function getVault( + bytes32 uuid + ) public view returns (DLCLink.DLC memory) { return getDLC(uuid); } - function getAllVaultUUIDsForAddress(address owner) public view returns (bytes32[] memory) { + function getAllVaultUUIDsForAddress( + address owner + ) public view returns (bytes32[] memory) { return userVaults[owner]; } - function getAllVaultsForAddress(address owner) public view returns (DLCLink.DLC[] memory) { + function getAllVaultsForAddress( + address owner + ) public view returns (DLCLink.DLC[] memory) { bytes32[] memory uuids = getAllVaultUUIDsForAddress(owner); DLCLink.DLC[] memory vaults = new DLCLink.DLC[](uuids.length); for (uint256 i = 0; i < uuids.length; i++) { @@ -489,7 +503,9 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, return vaults; } - function isWhitelisted(address account) external view returns (bool) { + function isWhitelisted( + address account + ) external view returns (bool) { return _whitelistedAddresses[account]; } @@ -509,7 +525,9 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, // ADMIN FUNCTIONS // //////////////////////////////////////////////////////////////// - function _hasAnyRole(address account) internal view returns (bool) { + function _hasAnyRole( + address account + ) internal view returns (bool) { return hasRole(DLC_ADMIN_ROLE, account) || hasRole(WHITELISTED_CONTRACT, account) || hasRole(APPROVED_SIGNER, account); } @@ -548,7 +566,9 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, _unpause(); } - function setThreshold(uint16 newThreshold) external onlyAdmin { + function setThreshold( + uint16 newThreshold + ) external onlyAdmin { if (newThreshold < _minimumThreshold) { revert ThresholdTooLow(_minimumThreshold); } @@ -556,35 +576,49 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, emit SetThreshold(newThreshold); } - function setTSSCommitment(bytes32 commitment) external onlyAdmin { + function setTSSCommitment( + bytes32 commitment + ) external onlyAdmin { tssCommitment = commitment; } - function setAttestorGroupPubKey(string calldata pubKey) external onlyAdmin { + function setAttestorGroupPubKey( + string calldata pubKey + ) external onlyAdmin { attestorGroupPubKey = pubKey; } - function whitelistAddress(address addressToWhitelist) external onlyAdmin { + function whitelistAddress( + address addressToWhitelist + ) external onlyAdmin { _whitelistedAddresses[addressToWhitelist] = true; emit WhitelistAddress(addressToWhitelist); } - function unwhitelistAddress(address addressToUnWhitelist) external onlyAdmin { + function unwhitelistAddress( + address addressToUnWhitelist + ) external onlyAdmin { _whitelistedAddresses[addressToUnWhitelist] = false; emit UnwhitelistAddress(addressToUnWhitelist); } - function setMinimumDeposit(uint256 newMinimumDeposit) external onlyAdmin { + function setMinimumDeposit( + uint256 newMinimumDeposit + ) external onlyAdmin { minimumDeposit = newMinimumDeposit; emit SetMinimumDeposit(newMinimumDeposit); } - function setMaximumDeposit(uint256 newMaximumDeposit) external onlyAdmin { + function setMaximumDeposit( + uint256 newMaximumDeposit + ) external onlyAdmin { maximumDeposit = newMaximumDeposit; emit SetMaximumDeposit(newMaximumDeposit); } - function setBtcMintFeeRate(uint256 newBtcMintFeeRate) external onlyAdmin { + function setBtcMintFeeRate( + uint256 newBtcMintFeeRate + ) external onlyAdmin { if (newBtcMintFeeRate > 10_000) { revert FeeRateOutOfBounds(newBtcMintFeeRate); } @@ -592,12 +626,16 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, emit SetBtcMintFeeRate(newBtcMintFeeRate); } - function setBtcRedeemFeeRate(uint256 newBtcRedeemFeeRate) external onlyAdmin { + function setBtcRedeemFeeRate( + uint256 newBtcRedeemFeeRate + ) external onlyAdmin { btcRedeemFeeRate = newBtcRedeemFeeRate; emit SetBtcRedeemFeeRate(newBtcRedeemFeeRate); } - function setBtcFeeRecipient(string calldata btcFeeRecipientToSet) external onlyAdmin { + function setBtcFeeRecipient( + string calldata btcFeeRecipientToSet + ) external onlyAdmin { btcFeeRecipient = btcFeeRecipientToSet; emit SetBtcFeeRecipient(btcFeeRecipient); } @@ -607,30 +645,42 @@ contract DLCManager is Initializable, AccessControlDefaultAdminRulesUpgradeable, dlc.btcFeeRecipient = btcFeeRecipientToSet; } - function setWhitelistingEnabled(bool isWhitelistingEnabled) external onlyAdmin { + function setWhitelistingEnabled( + bool isWhitelistingEnabled + ) external onlyAdmin { whitelistingEnabled = isWhitelistingEnabled; emit SetWhitelistingEnabled(isWhitelistingEnabled); } - function transferTokenContractOwnership(address newOwner) external onlyAdmin { + function transferTokenContractOwnership( + address newOwner + ) external onlyAdmin { dlcBTC.transferOwnership(newOwner); emit TransferTokenContractOwnership(newOwner); } - function setMinterOnTokenContract(address minter) external onlyAdmin { + function setMinterOnTokenContract( + address minter + ) external onlyAdmin { dlcBTC.setMinter(minter); } - function setBurnerOnTokenContract(address burner) external onlyAdmin { + function setBurnerOnTokenContract( + address burner + ) external onlyAdmin { dlcBTC.setBurner(burner); } - function setPorEnabled(bool enabled) external onlyAdmin { + function setPorEnabled( + bool enabled + ) external onlyAdmin { porEnabled = enabled; emit SetPorEnabled(enabled); } - function setDlcBTCPoRFeed(AggregatorV3Interface feed) external onlyAdmin { + function setDlcBTCPoRFeed( + AggregatorV3Interface feed + ) external onlyAdmin { dlcBTCPoRFeed = feed; emit SetDlcBTCPoRFeed(feed); } diff --git a/src/dlc-core/IBTC.sol b/src/dlc-core/IBTC.sol index 9871c5c..5066d6e 100644 --- a/src/dlc-core/IBTC.sol +++ b/src/dlc-core/IBTC.sol @@ -85,16 +85,22 @@ contract IBTC is Initializable, ERC20Upgradeable, ERC20PermitUpgradeable, Ownabl _burn(from, amount); } - function burn(uint256 amount) external onlyCCIPBurner { + function burn( + uint256 amount + ) external onlyCCIPBurner { _burn(msg.sender, amount); } - function setMinter(address minter) external onlyOwner { + function setMinter( + address minter + ) external onlyOwner { _minter = minter; emit MinterSet(minter); } - function setBurner(address burner) external onlyOwner { + function setBurner( + address burner + ) external onlyOwner { _burner = burner; emit BurnerSet(burner); } diff --git a/src/iBTC_Burner.sol b/src/iBTC_Burner.sol index 84d2c87..9107675 100644 --- a/src/iBTC_Burner.sol +++ b/src/iBTC_Burner.sol @@ -30,7 +30,9 @@ contract iBTC_Burner is UintRequests, IiBTC_Burner, IERC721Receiver { * This function triggers a withdrawal by creating one or more withdrawal requests. * It splits the total collateral balance into multiple requests based on the maximum withdrawal limit. */ - function triggerWithdrawal(uint256 maxRequests) external returns (uint256 firstRequestId, uint256 lastRequestId) { + function triggerWithdrawal( + uint256 maxRequests + ) external returns (uint256 firstRequestId, uint256 lastRequestId) { // Get the current balance of the COLLATERAL token held by this contract uint256 amount = IERC20(Collateral).balanceOf(address(this)); diff --git a/src/iBTC_NetworkMiddleware.sol b/src/iBTC_NetworkMiddleware.sol index 6826462..71c48d2 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,11 +98,15 @@ 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; } @@ -135,15 +141,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()) { @@ -153,7 +165,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(); } @@ -177,15 +191,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()) { @@ -217,14 +237,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()); @@ -291,7 +315,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) @@ -321,7 +347,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_Treasury.sol b/src/iBTC_Treasury.sol index c3a2184..9b782c2 100644 --- a/src/iBTC_Treasury.sol +++ b/src/iBTC_Treasury.sol @@ -62,7 +62,9 @@ contract iBTC_Treasury is ERC721, Ownable { * @dev Allows users to create a withdrawal request. * Transfers collateral from the caller to the treasury and mints an ERC721 token. */ - function createWithdrawRequest(uint256 amount) external { + function createWithdrawRequest( + uint256 amount + ) external { require(amount >= minWithdrawAmount, "Amount below minimum limit"); require(amount <= maxWithdrawAmount, "Amount exceeds maximum limit"); @@ -86,7 +88,9 @@ contract iBTC_Treasury is ERC721, Ownable { * @dev Finalizes a withdrawal request and burns the corresponding token. * Transfers the collateral back to the token owner. */ - function finalizeWithdrawal(uint256 requestId) external onlyOwner { + function finalizeWithdrawal( + uint256 requestId + ) external onlyOwner { require(!finalizedWithdrawals[requestId], "Already finalized"); address requester = ownerOf(requestId); @@ -109,7 +113,9 @@ contract iBTC_Treasury is ERC721, Ownable { * @dev Batch process withdrawals up to a specified token ID. * Only callable by the contract owner. */ - function processWithdrawals(uint256 _lastrequestIdToProcess) external onlyOwner { + function processWithdrawals( + uint256 _lastrequestIdToProcess + ) external onlyOwner { for (uint256 requestId = 1; requestId <= _lastrequestIdToProcess; requestId++) { if (_exits(requestId) && !finalizedWithdrawals[requestId]) { address requester = ownerOf(requestId); @@ -133,7 +139,9 @@ contract iBTC_Treasury is ERC721, Ownable { return minWithdrawAmount; } - function _exits(uint256 requestId) internal view returns (bool) { + function _exits( + uint256 requestId + ) internal view returns (bool) { return ownerOf(requestId) != address(0); } } 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/src/interfaces/IiBTC_Burner.sol b/src/interfaces/IiBTC_Burner.sol index b024191..30f930e 100644 --- a/src/interfaces/IiBTC_Burner.sol +++ b/src/interfaces/IiBTC_Burner.sol @@ -30,5 +30,7 @@ interface IiBTC_Burner is IUintRequests { * @return firstRequestId first request ID that was created * @return lastRequestId last request ID that was created */ - function triggerWithdrawal(uint256 maxRequests) external returns (uint256 firstRequestId, uint256 lastRequestId); + function triggerWithdrawal( + uint256 maxRequests + ) external returns (uint256 firstRequestId, uint256 lastRequestId); } diff --git a/src/interfaces/IiBTC_Treasury.sol b/src/interfaces/IiBTC_Treasury.sol index 06a8146..b17740e 100644 --- a/src/interfaces/IiBTC_Treasury.sol +++ b/src/interfaces/IiBTC_Treasury.sol @@ -8,9 +8,15 @@ interface IiBTC_Treasury { function withdrawRequestMinimum() external view returns (uint256); - function processWithdrawals(uint256 _lastTokenIdToProcess) external; + function processWithdrawals( + uint256 _lastTokenIdToProcess + ) external; - function createWithdrawRequest(uint256 amount) external; + function createWithdrawRequest( + uint256 amount + ) external; - function finalizeWithdrawal(uint256 tokenId) external; + function finalizeWithdrawal( + uint256 tokenId + ) external; } diff --git a/src/libraries/AggregatorV3Interface.sol b/src/libraries/AggregatorV3Interface.sol index 81b2aff..2062677 100644 --- a/src/libraries/AggregatorV3Interface.sol +++ b/src/libraries/AggregatorV3Interface.sol @@ -9,7 +9,9 @@ interface AggregatorV3Interface { function version() external view returns (uint256); - function getRoundData(uint80 _roundId) + function getRoundData( + uint80 _roundId + ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); diff --git a/src/libraries/Counter.sol b/src/libraries/Counter.sol index ece483e..3631f01 100644 --- a/src/libraries/Counter.sol +++ b/src/libraries/Counter.sol @@ -6,17 +6,23 @@ library Counters { uint256 _value; // Default: 0 } - function current(Counter storage counter) internal view returns (uint256) { + function current( + Counter storage counter + ) internal view returns (uint256) { return counter._value; } - function increment(Counter storage counter) internal { + function increment( + Counter storage counter + ) internal { unchecked { counter._value += 1; } } - function decrement(Counter storage counter) internal { + function decrement( + Counter storage counter + ) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { @@ -24,7 +30,9 @@ library Counters { } } - function reset(Counter storage counter) internal { + function reset( + Counter storage counter + ) internal { counter._value = 0; } } diff --git a/src/libraries/SimpleKeyRegistry32.sol b/src/libraries/SimpleKeyRegistry32.sol index 90f5de6..5255d8f 100644 --- a/src/libraries/SimpleKeyRegistry32.sol +++ b/src/libraries/SimpleKeyRegistry32.sol @@ -18,11 +18,15 @@ abstract contract SimpleKeyRegistry32 { uint208 internal constant EMPTY_KEY_IDX = 0; - function getOperatorByKey(bytes32 key) public view returns (address) { + function getOperatorByKey( + bytes32 key + ) public view returns (address) { return keyToOperator[key]; } - function getCurrentOperatorKey(address operator) public view returns (bytes32) { + function getCurrentOperatorKey( + address operator + ) public view returns (bytes32) { uint208 keyIdx = operatorToIdx[operator].latest(); if (keyIdx == EMPTY_KEY_IDX) { diff --git a/test/iBTC_Vault.t.sol b/test/iBTC_Vault.t.sol index 7087210..54454a8 100644 --- a/test/iBTC_Vault.t.sol +++ b/test/iBTC_Vault.t.sol @@ -334,7 +334,9 @@ contract VaultTest is Test { ); } - function test_CreateRevertInvalidCollateral(uint48 epochDuration) public { + function test_CreateRevertInvalidCollateral( + uint48 epochDuration + ) public { epochDuration = uint48(bound(epochDuration, 1, 50 weeks)); address[] memory networkLimitSetRoleHolders = new address[](1); @@ -381,7 +383,9 @@ contract VaultTest is Test { ); } - function test_CreateRevertMissingRoles1(uint48 epochDuration) public { + function test_CreateRevertMissingRoles1( + uint48 epochDuration + ) public { epochDuration = uint48(bound(epochDuration, 1, 50 weeks)); uint64 lastVersion = vaultFactory.lastVersion(); @@ -410,7 +414,9 @@ contract VaultTest is Test { ); } - function test_CreateRevertMissingRoles2(uint48 epochDuration) public { + function test_CreateRevertMissingRoles2( + uint48 epochDuration + ) public { epochDuration = uint48(bound(epochDuration, 1, 50 weeks)); uint64 lastVersion = vaultFactory.lastVersion(); @@ -439,7 +445,9 @@ contract VaultTest is Test { ); } - function test_CreateRevertMissingRoles3(uint48 epochDuration) public { + function test_CreateRevertMissingRoles3( + uint48 epochDuration + ) public { epochDuration = uint48(bound(epochDuration, 1, 50 weeks)); uint64 lastVersion = vaultFactory.lastVersion(); @@ -468,7 +476,9 @@ contract VaultTest is Test { ); } - function test_CreateRevertMissingRoles4(uint48 epochDuration) public { + function test_CreateRevertMissingRoles4( + uint48 epochDuration + ) public { epochDuration = uint48(bound(epochDuration, 1, 50 weeks)); uint64 lastVersion = vaultFactory.lastVersion(); @@ -497,7 +507,9 @@ contract VaultTest is Test { ); } - function test_CreateRevertMissingRoles5(uint48 epochDuration) public { + function test_CreateRevertMissingRoles5( + uint48 epochDuration + ) public { epochDuration = uint48(bound(epochDuration, 1, 50 weeks)); uint64 lastVersion = vaultFactory.lastVersion(); @@ -1380,7 +1392,9 @@ contract VaultTest is Test { assertEq(iBTCVault.slashableBalanceOf(bob), amount2); } - function test_DepositRevertInvalidOnBehalfOf(uint256 amount1) public { + function test_DepositRevertInvalidOnBehalfOf( + uint256 amount1 + ) public { amount1 = bound(amount1, 1, 100 * 10 ** 18); uint48 epochDuration = 1; @@ -1501,7 +1515,9 @@ contract VaultTest is Test { assertEq(iBTCVault.totalStake(), amount1 - amount2 - amount3); } - function test_WithdrawRevertInvalidClaimer(uint256 amount1) public { + function test_WithdrawRevertInvalidClaimer( + uint256 amount1 + ) public { amount1 = bound(amount1, 1, 100 * 10 ** 18); uint48 epochDuration = 1; @@ -1515,7 +1531,9 @@ contract VaultTest is Test { vm.stopPrank(); } - function test_WithdrawRevertInsufficientWithdrawal(uint256 amount1) public { + function test_WithdrawRevertInsufficientWithdrawal( + uint256 amount1 + ) public { amount1 = bound(amount1, 1, 100 * 10 ** 18); uint48 epochDuration = 1; @@ -1527,7 +1545,9 @@ contract VaultTest is Test { _withdraw(alice, 0); } - function test_WithdrawRevertTooMuchWithdraw(uint256 amount1) public { + function test_WithdrawRevertTooMuchWithdraw( + uint256 amount1 + ) public { amount1 = bound(amount1, 1, 100 * 10 ** 18); uint48 epochDuration = 1; @@ -1641,7 +1661,9 @@ contract VaultTest is Test { assertEq(iBTCVault.totalStake(), amount1 - withdrawnAssets2 - withdrawnAssets3); } - function test_RedeemRevertInvalidClaimer(uint256 amount1) public { + function test_RedeemRevertInvalidClaimer( + uint256 amount1 + ) public { amount1 = bound(amount1, 1, 100 * 10 ** 18); uint48 epochDuration = 1; @@ -1655,7 +1677,9 @@ contract VaultTest is Test { vm.stopPrank(); } - function test_RedeemRevertInsufficientRedeemption(uint256 amount1) public { + function test_RedeemRevertInsufficientRedeemption( + uint256 amount1 + ) public { amount1 = bound(amount1, 1, 100 * 10 ** 18); uint48 epochDuration = 1; @@ -1667,7 +1691,9 @@ contract VaultTest is Test { _redeem(alice, 0); } - function test_RedeemRevertTooMuchRedeem(uint256 amount1) public { + function test_RedeemRevertTooMuchRedeem( + uint256 amount1 + ) public { amount1 = bound(amount1, 1, 100 * 10 ** 18); uint48 epochDuration = 1; @@ -2181,7 +2207,9 @@ contract VaultTest is Test { _deposit(alice, depositAmount); } - function test_SetDepositLimitToNull(uint256 limit1) public { + function test_SetDepositLimitToNull( + uint256 limit1 + ) public { uint48 epochDuration = 1; iBTCVault = _getVault(epochDuration); @@ -2222,7 +2250,9 @@ contract VaultTest is Test { vm.stopPrank(); } - function test_SetDepositLimitRevertAlreadySet(uint256 limit) public { + function test_SetDepositLimitRevertAlreadySet( + uint256 limit + ) public { uint48 epochDuration = 1; iBTCVault = _getVault(epochDuration); @@ -2654,7 +2684,9 @@ contract VaultTest is Test { // assertLt(gasStruct.gasSpent1 - gasStruct.gasSpent2, 10_000); // } - function _getVault(uint48 epochDuration) internal returns (iBTC_Vault) { + function _getVault( + uint48 epochDuration + ) internal returns (iBTC_Vault) { address[] memory networkLimitSetRoleHolders = new address[](1); networkLimitSetRoleHolders[0] = alice; address[] memory operatorNetworkSharesSetRoleHolders = new address[](1); @@ -2699,10 +2731,9 @@ contract VaultTest is Test { return iBTC_Vault(vault_); } - function _getVaultAndDelegatorAndSlasher(uint48 epochDuration) - internal - returns (iBTC_Vault, FullRestakeDelegator, Slasher) - { + function _getVaultAndDelegatorAndSlasher( + uint48 epochDuration + ) internal returns (iBTC_Vault, FullRestakeDelegator, Slasher) { address[] memory networkLimitSetRoleHolders = new address[](1); networkLimitSetRoleHolders[0] = alice; address[] memory operatorNetworkLimitSetRoleHolders = new address[](1); @@ -2747,7 +2778,9 @@ contract VaultTest is Test { return (iBTC_Vault(vault_), FullRestakeDelegator(delegator_), Slasher(slasher_)); } - function _registerOperator(address user) internal { + function _registerOperator( + address user + ) internal { vm.startPrank(user); operatorRegistry.registerOperator(); vm.stopPrank(); @@ -2816,13 +2849,17 @@ contract VaultTest is Test { vm.stopPrank(); } - function _optInOperatorVault(address user) internal { + function _optInOperatorVault( + address user + ) internal { vm.startPrank(user); operatorVaultOptInService.optIn(address(iBTCVault)); vm.stopPrank(); } - function _optOutOperatorVault(address user) internal { + function _optOutOperatorVault( + address user + ) internal { vm.startPrank(user); operatorVaultOptInService.optOut(address(iBTCVault)); vm.stopPrank(); diff --git a/test/mocks/MapWithTimeDataContract.sol b/test/mocks/MapWithTimeDataContract.sol index a53d8bf..615d5ba 100644 --- a/test/mocks/MapWithTimeDataContract.sol +++ b/test/mocks/MapWithTimeDataContract.sol @@ -11,23 +11,33 @@ contract MapWithTimeDataContract { EnumerableMap.AddressToUintMap internal elements; - function add(address addr) public { + function add( + address addr + ) public { elements.add(addr); } - function disable(address addr) public { + function disable( + address addr + ) public { elements.disable(addr); } - function enable(address addr) public { + function enable( + address addr + ) public { elements.enable(addr); } - function atWithTimes(uint256 idx) public view returns (address key, uint48 enabledTime, uint48 disabledTime) { + function atWithTimes( + uint256 idx + ) public view returns (address key, uint48 enabledTime, uint48 disabledTime) { return elements.atWithTimes(idx); } - function getTimes(address addr) public view returns (uint48 enabledTime, uint48 disabledTime) { + function getTimes( + address addr + ) public view returns (uint48 enabledTime, uint48 disabledTime) { return elements.getTimes(addr); } From 039630671bdaeaf20d738fc9fb7b4aa0f3f70881 Mon Sep 17 00:00:00 2001 From: scolear Date: Tue, 26 Nov 2024 13:11:12 +0100 Subject: [PATCH 7/7] chore: remove lib --- lib/openzeppelin-contracts | 1 - 1 file changed, 1 deletion(-) 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