diff --git a/script/DeployVault.s.sol b/script/DeployVault.s.sol new file mode 100644 index 00000000..30862129 --- /dev/null +++ b/script/DeployVault.s.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.25; + +import "./base/DeployVaultBase.sol"; + +contract DeployVaultScript is DeployVaultBase { + // Configurations - UPDATE THESE BEFORE DEPLOYMENT + + // Address of the owner of the vault who can migrate the vault to new versions whitelisted by Symbiotic + address OWNER = 0x0000000000000000000000000000000000000000; + // Address of the collateral token + address COLLATERAL = 0x0000000000000000000000000000000000000000; + // Vault's burner to send slashed funds to (e.g., 0xdEaD or some unwrapper contract; not used in case of no slasher) + address BURNER = 0x000000000000000000000000000000000000dEaD; + // Duration of the vault epoch (the withdrawal delay for staker varies from EPOCH_DURATION to 2 * EPOCH_DURATION depending on when the withdrawal is requested) + uint48 EPOCH_DURATION = 7 days; + // Type of the delegator: + // 0. NetworkRestakeDelegator (allows restaking across multiple networks and having multiple operators per network) + // 1. FullRestakeDelegator (do not use without knowing what you are doing) + // 2. OperatorSpecificDelegator (allows restaking across multiple networks with only a single operator) + // 3. OperatorNetworkSpecificDelegator (allocates the stake to a specific operator and network) + uint64 DELEGATOR_INDEX = 0; + // Setting depending on the delegator type: + // 0. NetworkLimitSetRoleHolders (adjust allocations for networks) + // 1. NetworkLimitSetRoleHolders (adjust allocations for networks) + // 2. NetworkLimitSetRoleHolders (adjust allocations for networks) + // 3. network (the only network that will receive the stake; should be an array with a single element) + address[] NETWORK_ALLOCATION_SETTERS_OR_NETWORK = [0x0000000000000000000000000000000000000000]; + // Setting depending on the delegator type: + // 0. OperatorNetworkSharesSetRoleHolders (adjust allocations for operators inside networks; in shares, resulting percentage is operatorShares / totalOperatorShares) + // 1. OperatorNetworkLimitSetRoleHolders (adjust allocations for operators inside networks; in shares, resulting percentage is operatorShares / totalOperatorShares) + // 2. operator (the only operator that will receive the stake; should be an array with a single element) + // 3. operator (the only operator that will receive the stake; should be an array with a single element) + address[] OPERATOR_ALLOCATION_SETTERS_OR_OPERATOR = [0x0000000000000000000000000000000000000000]; + // Whether to deploy a slasher + bool WITH_SLASHER = true; + // Type of the slasher: + // 0. Slasher (allows instant slashing) + // 1. VetoSlasher (allows having a veto period if the resolver is set) + uint64 SLASHER_INDEX = 1; + // Duration of a veto period (should be less than EPOCH_DURATION) + uint48 VETO_DURATION = 1 days; + + // Optional + + // Deposit limit (maximum amount of the active stake allowed in the vault) + uint256 DEPOSIT_LIMIT = 0; + // Addresses of the whitelisted depositors + address[] WHITELISTED_DEPOSITORS = new address[](0); + // Address of the hook contract which, e.g., can automatically adjust the allocations on slashing events (not used in case of no slasher) + address HOOK = 0x0000000000000000000000000000000000000000; + // Delay in epochs for a network to update a resolver + uint48 RESOLVER_SET_EPOCHS_DELAY = 3; + + function run() public { + run( + DeployVaultParams({ + owner: OWNER, + vaultParams: VaultParams({ + baseParams: IVault.InitParams({ + collateral: COLLATERAL, + burner: BURNER, + epochDuration: EPOCH_DURATION, + depositWhitelist: WHITELISTED_DEPOSITORS.length != 0, + isDepositLimit: DEPOSIT_LIMIT != 0, + depositLimit: DEPOSIT_LIMIT, + defaultAdminRoleHolder: OWNER, + depositWhitelistSetRoleHolder: OWNER, + depositorWhitelistRoleHolder: OWNER, + isDepositLimitSetRoleHolder: OWNER, + depositLimitSetRoleHolder: OWNER + }), + whitelistedDepositors: WHITELISTED_DEPOSITORS + }), + delegatorIndex: DELEGATOR_INDEX, + delegatorParams: DelegatorParams({ + baseParams: IBaseDelegator.BaseParams({defaultAdminRoleHolder: OWNER, hook: HOOK, hookSetRoleHolder: OWNER}), + networkAllocationSettersOrNetwork: NETWORK_ALLOCATION_SETTERS_OR_NETWORK, + operatorAllocationSettersOrOperator: OPERATOR_ALLOCATION_SETTERS_OR_OPERATOR + }), + withSlasher: WITH_SLASHER, + slasherIndex: SLASHER_INDEX, + slasherParams: SlasherParams({ + baseParams: IBaseSlasher.BaseParams({isBurnerHook: BURNER != address(0)}), + vetoDuration: VETO_DURATION, + resolverSetEpochsDelay: RESOLVER_SET_EPOCHS_DELAY + }) + }) + ); + } +} diff --git a/script/DeployVaultTokenized.s.sol b/script/DeployVaultTokenized.s.sol new file mode 100644 index 00000000..25e0a8bb --- /dev/null +++ b/script/DeployVaultTokenized.s.sol @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.25; + +import "./base/DeployVaultTokenizedBase.sol"; + +contract DeployVaultTokenizedScript is DeployVaultTokenizedBase { + // Configurations - UPDATE THESE BEFORE DEPLOYMENT + + // Name of the ERC20 representing shares of the active stake in the vault + string NAME = "SymVault"; + // Symbol of the ERC20 representing shares of the active stake in the vault + string SYMBOL = "SV"; + // Address of the owner of the vault who can migrate the vault to new versions whitelisted by Symbiotic + address OWNER = 0x0000000000000000000000000000000000000000; + // Address of the collateral token + address COLLATERAL = 0x0000000000000000000000000000000000000000; + // Vault's burner to send slashed funds to (e.g., 0xdEaD or some unwrapper contract; not used in case of no slasher) + address BURNER = 0x000000000000000000000000000000000000dEaD; + // Duration of the vault epoch (the withdrawal delay for staker varies from EPOCH_DURATION to 2 * EPOCH_DURATION depending on when the withdrawal is requested) + uint48 EPOCH_DURATION = 7 days; + // Type of the delegator: + // 0. NetworkRestakeDelegator (allows restaking across multiple networks and having multiple operators per network) + // 1. FullRestakeDelegator (do not use without knowing what you are doing) + // 2. OperatorSpecificDelegator (allows restaking across multiple networks with only a single operator) + // 3. OperatorNetworkSpecificDelegator (allocates the stake to a specific operator and network) + uint64 DELEGATOR_INDEX = 0; + // Setting depending on the delegator type: + // 0. NetworkLimitSetRoleHolders (adjust allocations for networks) + // 1. NetworkLimitSetRoleHolders (adjust allocations for networks) + // 2. NetworkLimitSetRoleHolders (adjust allocations for networks) + // 3. network (the only network that will receive the stake; should be an array with a single element) + address[] NETWORK_ALLOCATION_SETTERS_OR_NETWORK = [0x0000000000000000000000000000000000000000]; + // Setting depending on the delegator type: + // 0. OperatorNetworkSharesSetRoleHolders (adjust allocations for operators inside networks; in shares, resulting percentage is operatorShares / totalOperatorShares) + // 1. OperatorNetworkLimitSetRoleHolders (adjust allocations for operators inside networks; in shares, resulting percentage is operatorShares / totalOperatorShares) + // 2. operator (the only operator that will receive the stake; should be an array with a single element) + // 3. operator (the only operator that will receive the stake; should be an array with a single element) + address[] OPERATOR_ALLOCATION_SETTERS_OR_OPERATOR = [0x0000000000000000000000000000000000000000]; + // Whether to deploy a slasher + bool WITH_SLASHER = true; + // Type of the slasher: + // 0. Slasher (allows instant slashing) + // 1. VetoSlasher (allows having a veto period if the resolver is set) + uint64 SLASHER_INDEX = 1; + // Duration of a veto period (should be less than EPOCH_DURATION) + uint48 VETO_DURATION = 1 days; + + // Optional + + // Deposit limit (maximum amount of the active stake allowed in the vault) + uint256 DEPOSIT_LIMIT = 0; + // Addresses of the whitelisted depositors + address[] WHITELISTED_DEPOSITORS = new address[](0); + // Address of the hook contract which, e.g., can automatically adjust the allocations on slashing events (not used in case of no slasher) + address HOOK = 0x0000000000000000000000000000000000000000; + // Delay in epochs for a network to update a resolver + uint48 RESOLVER_SET_EPOCHS_DELAY = 3; + + function run() public { + run( + DeployVaultTokenizedParams({ + deployVaultParams: DeployVaultParams({ + owner: OWNER, + vaultParams: VaultParams({ + baseParams: IVault.InitParams({ + collateral: COLLATERAL, + burner: BURNER, + epochDuration: EPOCH_DURATION, + depositWhitelist: WHITELISTED_DEPOSITORS.length != 0, + isDepositLimit: DEPOSIT_LIMIT != 0, + depositLimit: DEPOSIT_LIMIT, + defaultAdminRoleHolder: OWNER, + depositWhitelistSetRoleHolder: OWNER, + depositorWhitelistRoleHolder: OWNER, + isDepositLimitSetRoleHolder: OWNER, + depositLimitSetRoleHolder: OWNER + }), + whitelistedDepositors: WHITELISTED_DEPOSITORS + }), + delegatorIndex: DELEGATOR_INDEX, + delegatorParams: DelegatorParams({ + baseParams: IBaseDelegator.BaseParams({defaultAdminRoleHolder: OWNER, hook: HOOK, hookSetRoleHolder: OWNER}), + networkAllocationSettersOrNetwork: NETWORK_ALLOCATION_SETTERS_OR_NETWORK, + operatorAllocationSettersOrOperator: OPERATOR_ALLOCATION_SETTERS_OR_OPERATOR + }), + withSlasher: WITH_SLASHER, + slasherIndex: SLASHER_INDEX, + slasherParams: SlasherParams({ + baseParams: IBaseSlasher.BaseParams({isBurnerHook: BURNER != address(0)}), + vetoDuration: VETO_DURATION, + resolverSetEpochsDelay: RESOLVER_SET_EPOCHS_DELAY + }) + }), + name: NAME, + symbol: SYMBOL + }) + ); + } +} diff --git a/script/base/DeployVaultBase.sol b/script/base/DeployVaultBase.sol new file mode 100644 index 00000000..d62f08da --- /dev/null +++ b/script/base/DeployVaultBase.sol @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.25; + +import {Script, console2} from "forge-std/Script.sol"; + +import {Vault} from "../../src/contracts/vault/Vault.sol"; + +import {IVault} from "../../src/interfaces/vault/IVault.sol"; +import {IVaultConfigurator} from "../../src/interfaces/IVaultConfigurator.sol"; +import {IBaseDelegator} from "../../src/interfaces/delegator/IBaseDelegator.sol"; +import {INetworkRestakeDelegator} from "../../src/interfaces/delegator/INetworkRestakeDelegator.sol"; +import {IFullRestakeDelegator} from "../../src/interfaces/delegator/IFullRestakeDelegator.sol"; +import {IOperatorSpecificDelegator} from "../../src/interfaces/delegator/IOperatorSpecificDelegator.sol"; +import {IOperatorNetworkSpecificDelegator} from "../../src/interfaces/delegator/IOperatorNetworkSpecificDelegator.sol"; +import {IBaseSlasher} from "../../src/interfaces/slasher/IBaseSlasher.sol"; +import {ISlasher} from "../../src/interfaces/slasher/ISlasher.sol"; +import {IVetoSlasher} from "../../src/interfaces/slasher/IVetoSlasher.sol"; +import {NetworkRestakeDelegator} from "../../src/contracts/delegator/NetworkRestakeDelegator.sol"; +import {FullRestakeDelegator} from "../../src/contracts/delegator/FullRestakeDelegator.sol"; +import {OperatorSpecificDelegator} from "../../src/contracts/delegator/OperatorSpecificDelegator.sol"; +import {OperatorNetworkSpecificDelegator} from "../../src/contracts/delegator/OperatorNetworkSpecificDelegator.sol"; +import {Logs} from "./Logs.sol"; +import {SymbioticCoreConstants} from "../../test/integration/SymbioticCoreConstants.sol"; + +contract DeployVaultBase is Script, Logs { + struct VaultParams { + IVault.InitParams baseParams; + address[] whitelistedDepositors; + } + + struct DelegatorParams { + IBaseDelegator.BaseParams baseParams; + address[] networkAllocationSettersOrNetwork; + address[] operatorAllocationSettersOrOperator; + } + + struct SlasherParams { + IBaseSlasher.BaseParams baseParams; + uint48 vetoDuration; + uint48 resolverSetEpochsDelay; + } + + struct DeployVaultParams { + address owner; + VaultParams vaultParams; + uint64 delegatorIndex; + DelegatorParams delegatorParams; + bool withSlasher; + uint64 slasherIndex; + SlasherParams slasherParams; + } + + bytes32 DEFAULT_ADMIN_ROLE = 0x00; + + function run( + DeployVaultParams memory params + ) public returns (address, address, address) { + vm.startBroadcast(); + (,, address deployer) = vm.readCallers(); + + bytes memory delegatorParamsEncoded; + IBaseDelegator.BaseParams memory baseParams = IBaseDelegator.BaseParams({ + defaultAdminRoleHolder: params.delegatorParams.baseParams.defaultAdminRoleHolder, + hook: params.delegatorParams.baseParams.hook, + hookSetRoleHolder: params.delegatorParams.baseParams.hookSetRoleHolder + }); + if (params.delegatorIndex == 0) { + delegatorParamsEncoded = abi.encode( + INetworkRestakeDelegator.InitParams({ + baseParams: baseParams, + networkLimitSetRoleHolders: params.delegatorParams.networkAllocationSettersOrNetwork, + operatorNetworkSharesSetRoleHolders: params.delegatorParams.operatorAllocationSettersOrOperator + }) + ); + } else if (params.delegatorIndex == 1) { + delegatorParamsEncoded = abi.encode( + IFullRestakeDelegator.InitParams({ + baseParams: baseParams, + networkLimitSetRoleHolders: params.delegatorParams.networkAllocationSettersOrNetwork, + operatorNetworkLimitSetRoleHolders: params.delegatorParams.operatorAllocationSettersOrOperator + }) + ); + } else if (params.delegatorIndex == 2) { + assert(params.delegatorParams.operatorAllocationSettersOrOperator.length == 1); + delegatorParamsEncoded = abi.encode( + IOperatorSpecificDelegator.InitParams({ + baseParams: baseParams, + networkLimitSetRoleHolders: params.delegatorParams.networkAllocationSettersOrNetwork, + operator: params.delegatorParams.operatorAllocationSettersOrOperator[0] + }) + ); + } else if (params.delegatorIndex == 3) { + assert(params.delegatorParams.networkAllocationSettersOrNetwork.length == 1); + assert(params.delegatorParams.operatorAllocationSettersOrOperator.length == 1); + delegatorParamsEncoded = abi.encode( + IOperatorNetworkSpecificDelegator.InitParams({ + baseParams: baseParams, + network: params.delegatorParams.networkAllocationSettersOrNetwork[0], + operator: params.delegatorParams.operatorAllocationSettersOrOperator[0] + }) + ); + } + + bytes memory slasherParamsEncoded; + if (params.slasherIndex == 0) { + slasherParamsEncoded = abi.encode( + ISlasher.InitParams({ + baseParams: IBaseSlasher.BaseParams({isBurnerHook: params.slasherParams.baseParams.isBurnerHook}) + }) + ); + } else if (params.slasherIndex == 1) { + slasherParamsEncoded = abi.encode( + IVetoSlasher.InitParams({ + baseParams: IBaseSlasher.BaseParams({isBurnerHook: params.slasherParams.baseParams.isBurnerHook}), + vetoDuration: params.slasherParams.vetoDuration, + resolverSetEpochsDelay: params.slasherParams.resolverSetEpochsDelay + }) + ); + } + + (address vault_, address delegator_, address slasher_) = IVaultConfigurator( + SymbioticCoreConstants.core().vaultConfigurator + ).create( + IVaultConfigurator.InitParams({ + version: _getVaultVersion(), + owner: params.owner, + vaultParams: _getVaultParamsEncoded(params), + delegatorIndex: params.delegatorIndex, + delegatorParams: delegatorParamsEncoded, + withSlasher: params.withSlasher, + slasherIndex: params.slasherIndex, + slasherParams: slasherParamsEncoded + }) + ); + + if (params.vaultParams.whitelistedDepositors.length != 0) { + for (uint256 i; i < params.vaultParams.whitelistedDepositors.length; ++i) { + Vault(vault_).setDepositorWhitelistStatus(params.vaultParams.whitelistedDepositors[i], true); + } + + if (deployer != params.vaultParams.baseParams.depositorWhitelistRoleHolder) { + Vault(vault_).grantRole( + Vault(vault_).DEPOSITOR_WHITELIST_ROLE(), params.vaultParams.baseParams.depositorWhitelistRoleHolder + ); + Vault(vault_).renounceRole(Vault(vault_).DEPOSITOR_WHITELIST_ROLE(), deployer); + } + + if (deployer != params.vaultParams.baseParams.defaultAdminRoleHolder) { + Vault(vault_).grantRole(DEFAULT_ADMIN_ROLE, params.vaultParams.baseParams.defaultAdminRoleHolder); + Vault(vault_).renounceRole(DEFAULT_ADMIN_ROLE, deployer); + } + } + + log( + string.concat( + "Deployed vault", + "\n vault:", + vm.toString(vault_), + "\n delegator:", + vm.toString(delegator_), + "\n slasher:", + vm.toString(slasher_) + ) + ); + + _validateOwnershipTransfer(vault_, delegator_, params); + + vm.stopBroadcast(); + return (vault_, delegator_, slasher_); + } + + function _getVaultVersion() internal virtual returns (uint64) { + return 1; + } + + function _getVaultParamsEncoded( + DeployVaultParams memory params + ) internal virtual returns (bytes memory) { + (,, address deployer) = vm.readCallers(); + bool needWhitelistDepositors = params.vaultParams.whitelistedDepositors.length != 0; + + IVault.InitParams memory baseParams = params.vaultParams.baseParams; + baseParams.defaultAdminRoleHolder = + needWhitelistDepositors ? deployer : params.vaultParams.baseParams.defaultAdminRoleHolder; + baseParams.depositorWhitelistRoleHolder = + needWhitelistDepositors ? deployer : params.vaultParams.baseParams.depositorWhitelistRoleHolder; + + return abi.encode(baseParams); + } + + function _validateOwnershipTransfer(address vault, address delegator, DeployVaultParams memory params) internal { + (,, address deployer) = vm.readCallers(); + // Validate vault role transfers + assert(Vault(vault).owner() == params.owner); + if (params.vaultParams.baseParams.defaultAdminRoleHolder != address(0)) { + assert( + Vault(vault).hasRole(DEFAULT_ADMIN_ROLE, params.vaultParams.baseParams.defaultAdminRoleHolder) == true + ); + } + if (params.vaultParams.baseParams.depositLimitSetRoleHolder != address(0)) { + assert( + Vault(vault).hasRole( + Vault(vault).DEPOSIT_LIMIT_SET_ROLE(), params.vaultParams.baseParams.depositLimitSetRoleHolder + ) == true + ); + } + if (params.vaultParams.baseParams.isDepositLimitSetRoleHolder != address(0)) { + assert( + Vault(vault).hasRole( + Vault(vault).IS_DEPOSIT_LIMIT_SET_ROLE(), params.vaultParams.baseParams.isDepositLimitSetRoleHolder + ) == true + ); + } + if (params.vaultParams.baseParams.depositWhitelistSetRoleHolder != address(0)) { + assert( + Vault(vault).hasRole( + Vault(vault).DEPOSIT_WHITELIST_SET_ROLE(), + params.vaultParams.baseParams.depositWhitelistSetRoleHolder + ) == true + ); + } + if (params.vaultParams.baseParams.depositorWhitelistRoleHolder != address(0)) { + assert( + Vault(vault).hasRole( + Vault(vault).DEPOSITOR_WHITELIST_ROLE(), params.vaultParams.baseParams.depositorWhitelistRoleHolder + ) == true + ); + } + if (deployer != params.vaultParams.baseParams.defaultAdminRoleHolder) { + assert(Vault(vault).hasRole(DEFAULT_ADMIN_ROLE, deployer) == false); + } + if (deployer != params.vaultParams.baseParams.depositLimitSetRoleHolder) { + assert(Vault(vault).hasRole(Vault(vault).DEPOSIT_LIMIT_SET_ROLE(), deployer) == false); + } + if (deployer != params.vaultParams.baseParams.isDepositLimitSetRoleHolder) { + assert(Vault(vault).hasRole(Vault(vault).IS_DEPOSIT_LIMIT_SET_ROLE(), deployer) == false); + } + if (deployer != params.vaultParams.baseParams.depositWhitelistSetRoleHolder) { + assert(Vault(vault).hasRole(Vault(vault).DEPOSIT_WHITELIST_SET_ROLE(), deployer) == false); + } + if (deployer != params.vaultParams.baseParams.depositorWhitelistRoleHolder) { + assert(Vault(vault).hasRole(Vault(vault).DEPOSITOR_WHITELIST_ROLE(), deployer) == false); + } + + // Validate delegator role transfers based on delegator type + if (params.delegatorIndex == 0) { + if (params.delegatorParams.baseParams.defaultAdminRoleHolder != address(0)) { + assert( + NetworkRestakeDelegator(delegator).hasRole( + DEFAULT_ADMIN_ROLE, params.delegatorParams.baseParams.defaultAdminRoleHolder + ) == true + ); + } + for (uint256 i; i < params.delegatorParams.networkAllocationSettersOrNetwork.length; ++i) { + assert( + NetworkRestakeDelegator(delegator).hasRole( + NetworkRestakeDelegator(delegator).NETWORK_LIMIT_SET_ROLE(), + params.delegatorParams.networkAllocationSettersOrNetwork[i] + ) == true + ); + } + for (uint256 i; i < params.delegatorParams.operatorAllocationSettersOrOperator.length; ++i) { + assert( + NetworkRestakeDelegator(delegator).hasRole( + NetworkRestakeDelegator(delegator).OPERATOR_NETWORK_SHARES_SET_ROLE(), + params.delegatorParams.operatorAllocationSettersOrOperator[i] + ) == true + ); + } + if (params.delegatorParams.baseParams.hookSetRoleHolder != address(0)) { + assert( + NetworkRestakeDelegator(delegator).hasRole( + NetworkRestakeDelegator(delegator).HOOK_SET_ROLE(), + params.delegatorParams.baseParams.hookSetRoleHolder + ) == true + ); + } + } else if (params.delegatorIndex == 1) { + if (params.delegatorParams.baseParams.defaultAdminRoleHolder != address(0)) { + assert( + FullRestakeDelegator(delegator).hasRole( + DEFAULT_ADMIN_ROLE, params.delegatorParams.baseParams.defaultAdminRoleHolder + ) == true + ); + } + for (uint256 i; i < params.delegatorParams.networkAllocationSettersOrNetwork.length; ++i) { + assert( + FullRestakeDelegator(delegator).hasRole( + FullRestakeDelegator(delegator).NETWORK_LIMIT_SET_ROLE(), + params.delegatorParams.networkAllocationSettersOrNetwork[i] + ) == true + ); + } + for (uint256 i; i < params.delegatorParams.operatorAllocationSettersOrOperator.length; ++i) { + assert( + FullRestakeDelegator(delegator).hasRole( + FullRestakeDelegator(delegator).OPERATOR_NETWORK_LIMIT_SET_ROLE(), + params.delegatorParams.operatorAllocationSettersOrOperator[i] + ) == true + ); + } + if (params.delegatorParams.baseParams.hookSetRoleHolder != address(0)) { + assert( + FullRestakeDelegator(delegator).hasRole( + FullRestakeDelegator(delegator).HOOK_SET_ROLE(), + params.delegatorParams.baseParams.hookSetRoleHolder + ) == true + ); + } + } else if (params.delegatorIndex == 2) { + if (params.delegatorParams.baseParams.defaultAdminRoleHolder != address(0)) { + assert( + OperatorSpecificDelegator(delegator).hasRole( + DEFAULT_ADMIN_ROLE, params.delegatorParams.baseParams.defaultAdminRoleHolder + ) == true + ); + } + if (params.delegatorParams.baseParams.hookSetRoleHolder != address(0)) { + assert( + OperatorSpecificDelegator(delegator).hasRole( + OperatorSpecificDelegator(delegator).HOOK_SET_ROLE(), + params.delegatorParams.baseParams.hookSetRoleHolder + ) == true + ); + } + assert( + OperatorSpecificDelegator(delegator).operator() + == params.delegatorParams.operatorAllocationSettersOrOperator[0] + ); + } else if (params.delegatorIndex == 3) { + if (params.delegatorParams.baseParams.defaultAdminRoleHolder != address(0)) { + assert( + OperatorNetworkSpecificDelegator(delegator).hasRole( + DEFAULT_ADMIN_ROLE, params.delegatorParams.baseParams.defaultAdminRoleHolder + ) == true + ); + } + if (params.delegatorParams.baseParams.hookSetRoleHolder != address(0)) { + assert( + OperatorNetworkSpecificDelegator(delegator).hasRole( + OperatorNetworkSpecificDelegator(delegator).HOOK_SET_ROLE(), + params.delegatorParams.baseParams.hookSetRoleHolder + ) == true + ); + } + assert( + OperatorNetworkSpecificDelegator(delegator).network() + == params.delegatorParams.networkAllocationSettersOrNetwork[0] + ); + assert( + OperatorNetworkSpecificDelegator(delegator).operator() + == params.delegatorParams.operatorAllocationSettersOrOperator[0] + ); + } + } +} diff --git a/script/base/DeployVaultTokenizedBase.sol b/script/base/DeployVaultTokenizedBase.sol new file mode 100644 index 00000000..a702991c --- /dev/null +++ b/script/base/DeployVaultTokenizedBase.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.25; + +import "./DeployVaultBase.sol"; +import {IVaultTokenized} from "../../src/interfaces/vault/IVaultTokenized.sol"; + +contract DeployVaultTokenizedBase is DeployVaultBase { + struct DeployVaultTokenizedParams { + DeployVaultParams deployVaultParams; + string name; + string symbol; + } + + string public name; + string public symbol; + + function run( + DeployVaultTokenizedParams memory params + ) public returns (address, address, address) { + name = params.name; + symbol = params.symbol; + return run(params.deployVaultParams); + } + + function _getVaultVersion() internal virtual override returns (uint64) { + return 2; + } + + function _getVaultParamsEncoded( + DeployVaultParams memory params + ) internal virtual override returns (bytes memory) { + (,, address deployer) = vm.readCallers(); + bool needWhitelistDepositors = params.vaultParams.whitelistedDepositors.length != 0; + + IVault.InitParams memory baseParams = params.vaultParams.baseParams; + baseParams.defaultAdminRoleHolder = + needWhitelistDepositors ? deployer : params.vaultParams.baseParams.defaultAdminRoleHolder; + baseParams.depositorWhitelistRoleHolder = + needWhitelistDepositors ? deployer : params.vaultParams.baseParams.depositorWhitelistRoleHolder; + + return abi.encode(IVaultTokenized.InitParamsTokenized({baseParams: baseParams, name: name, symbol: symbol})); + } +} diff --git a/script/base/Logs.sol b/script/base/Logs.sol new file mode 100644 index 00000000..2496cb11 --- /dev/null +++ b/script/base/Logs.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import {Script, console2} from "forge-std/Script.sol"; +import {Vm, VmSafe} from "forge-std/Vm.sol"; + +contract Logs is Script { + string internal constant LOG_FILE = "script/logs.txt"; + + function log( + string memory data + ) internal { + console2.log(data); + vm.writeFile(LOG_FILE, string.concat(vm.readFile(LOG_FILE), data, "\n")); + } +} diff --git a/script/logs.txt b/script/logs.txt new file mode 100644 index 00000000..e69de29b