diff --git a/foundry.toml b/foundry.toml index ddadb9f..3437ab2 100644 --- a/foundry.toml +++ b/foundry.toml @@ -6,6 +6,7 @@ out = "out" libs = ["lib"] fs_permissions = [{ access = "read-write", path = "./"}] gas_reports = ["*"] +gas_limit = "18446744073709551615" [rpc_endpoints] mainnet = "${ETH_RPC_URL}" diff --git a/test/integration/Bindings.sol b/test/integration/SymbioticCoreBindings.sol similarity index 98% rename from test/integration/Bindings.sol rename to test/integration/SymbioticCoreBindings.sol index a27080d..9625d22 100644 --- a/test/integration/Bindings.sol +++ b/test/integration/SymbioticCoreBindings.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "./Imports.sol"; +import "./SymbioticCoreImports.sol"; -import {Constants as SymbioticCoreConstants} from "./Constants.sol"; +import {SymbioticCoreConstants} from "./SymbioticCoreConstants.sol"; import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -contract Bindings is Test { +contract SymbioticCoreBindings is Test { using SafeERC20 for IERC20; function _registerOperator_SymbioticCore(SymbioticCoreConstants.Core memory symbioticCore, address who) internal { diff --git a/test/integration/Constants.sol b/test/integration/SymbioticCoreConstants.sol similarity index 89% rename from test/integration/Constants.sol rename to test/integration/SymbioticCoreConstants.sol index 651d7fc..93a5246 100644 --- a/test/integration/Constants.sol +++ b/test/integration/SymbioticCoreConstants.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "./Imports.sol"; +import "./SymbioticCoreImports.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; -library Constants { +library SymbioticCoreConstants { using Strings for string; struct Core { @@ -25,7 +25,7 @@ library Constants { function core() internal view returns (Core memory) { if (block.chainid == 1) { // mainnet - revert("Constants.core(): mainnet not supported yet"); + revert("SymbioticCoreConstants.core(): mainnet not supported yet"); } else if (block.chainid == 17_000) { // holesky return Core({ @@ -57,7 +57,7 @@ library Constants { vaultConfigurator: ISymbioticVaultConfigurator(0xD2191FE92987171691d552C219b8caEf186eb9cA) }); } else { - revert("Constants.core(): chainid not supported"); + revert("SymbioticCoreConstants.core(): chainid not supported"); } } @@ -99,7 +99,7 @@ library Constants { } else if (symbol.equal("LBTC")) { return LBTC(); } else { - revert("Constants.token(): symbol not supported"); + revert("SymbioticCoreConstants.token(): symbol not supported"); } } @@ -141,7 +141,7 @@ library Constants { } else if (symbol.equal("LBTC")) { return LBTCSupported(); } else { - revert("Constants.tokenSupported(): symbol not supported"); + revert("SymbioticCoreConstants.tokenSupported(): symbol not supported"); } } @@ -156,7 +156,7 @@ library Constants { // sepolia return 0xB82381A3fBD3FaFA77B3a7bE693342618240067b; } else { - revert("Constants.wstETH(): chainid not supported"); + revert("SymbioticCoreConstants.wstETH(): chainid not supported"); } } @@ -165,7 +165,7 @@ library Constants { // mainnet return 0xBe9895146f7AF43049ca1c1AE358B0541Ea49704; } else { - revert("Constants.cbETH(): chainid not supported"); + revert("SymbioticCoreConstants.cbETH(): chainid not supported"); } } @@ -174,7 +174,7 @@ library Constants { // mainnet return 0xa2E3356610840701BDf5611a53974510Ae27E2e1; } else { - revert("Constants.wBETH(): chainid not supported"); + revert("SymbioticCoreConstants.wBETH(): chainid not supported"); } } @@ -186,7 +186,7 @@ library Constants { // holesky return 0x7322c24752f79c05FFD1E2a6FCB97020C1C264F1; } else { - revert("Constants.rETH(): chainid not supported"); + revert("SymbioticCoreConstants.rETH(): chainid not supported"); } } @@ -201,7 +201,7 @@ library Constants { // sepolia return 0x072d71b257ECa6B60b5333626F6a55ea1B0c451c; } else { - revert("Constants.mETH(): chainid not supported"); + revert("SymbioticCoreConstants.mETH(): chainid not supported"); } } @@ -210,7 +210,7 @@ library Constants { // mainnet return 0xf951E335afb289353dc249e82926178EaC7DEd78; } else { - revert("Constants.swETH(): chainid not supported"); + revert("SymbioticCoreConstants.swETH(): chainid not supported"); } } @@ -219,7 +219,7 @@ library Constants { // mainnet return 0xac3E018457B222d93114458476f3E3416Abbe38F; } else { - revert("Constants.sfrxETH(): chainid not supported"); + revert("SymbioticCoreConstants.sfrxETH(): chainid not supported"); } } @@ -231,7 +231,7 @@ library Constants { // holesky return 0xB4F5fc289a778B80392b86fa70A7111E5bE0F859; } else { - revert("Constants.ETHx(): chainid not supported"); + revert("SymbioticCoreConstants.ETHx(): chainid not supported"); } } @@ -240,7 +240,7 @@ library Constants { // mainnet return 0x57e114B691Db790C35207b2e685D4A43181e6061; } else { - revert("Constants.ENA(): chainid not supported"); + revert("SymbioticCoreConstants.ENA(): chainid not supported"); } } @@ -249,7 +249,7 @@ library Constants { // mainnet return 0x9D39A5DE30e57443BfF2A8307A4256c8797A3497; } else { - revert("Constants.sUSDe(): chainid not supported"); + revert("SymbioticCoreConstants.sUSDe(): chainid not supported"); } } @@ -258,7 +258,7 @@ library Constants { // mainnet return 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599; } else { - revert("Constants.WBTC(): chainid not supported"); + revert("SymbioticCoreConstants.WBTC(): chainid not supported"); } } @@ -271,7 +271,7 @@ library Constants { // sepolia return 0x517f2982701695D4E52f1ECFBEf3ba31Df470161; } else { - revert("Constants.tBTC(): chainid not supported"); + revert("SymbioticCoreConstants.tBTC(): chainid not supported"); } } @@ -284,7 +284,7 @@ library Constants { // holesky return 0x1d8b30cC38Dba8aBce1ac29Ea27d9cFd05379A09; } else { - revert("Constants.LsETH(): chainid not supported"); + revert("SymbioticCoreConstants.LsETH(): chainid not supported"); } } @@ -297,7 +297,7 @@ library Constants { // holesky return 0xF603c5A3F774F05d4D848A9bB139809790890864; } else { - revert("Constants.osETH(): chainid not supported"); + revert("SymbioticCoreConstants.osETH(): chainid not supported"); } } @@ -306,7 +306,7 @@ library Constants { // mainnet return 0xFe0c30065B384F05761f15d0CC899D4F9F9Cc0eB; } else { - revert("Constants.ETHFI(): chainid not supported"); + revert("SymbioticCoreConstants.ETHFI(): chainid not supported"); } } @@ -315,7 +315,7 @@ library Constants { // mainnet return 0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0; } else { - revert("Constants.FXS(): chainid not supported"); + revert("SymbioticCoreConstants.FXS(): chainid not supported"); } } @@ -324,7 +324,7 @@ library Constants { // mainnet return 0x8236a87084f8B84306f72007F36F2618A5634494; } else { - revert("Constants.LBTC(): chainid not supported"); + revert("SymbioticCoreConstants.LBTC(): chainid not supported"); } } diff --git a/test/integration/Counter.sol b/test/integration/SymbioticCoreCounter.sol similarity index 84% rename from test/integration/Counter.sol rename to test/integration/SymbioticCoreCounter.sol index 666f270..87820b3 100644 --- a/test/integration/Counter.sol +++ b/test/integration/SymbioticCoreCounter.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -contract Counter { +contract SymbioticCoreCounter { uint256 internal _count; function count() public returns (uint256) { diff --git a/test/integration/Imports.sol b/test/integration/SymbioticCoreImports.sol similarity index 98% rename from test/integration/Imports.sol rename to test/integration/SymbioticCoreImports.sol index fcdd178..93e284b 100644 --- a/test/integration/Imports.sol +++ b/test/integration/SymbioticCoreImports.sol @@ -37,4 +37,4 @@ import {Subnetwork as SymbioticSubnetwork} from "../../src/contracts/libraries/S import {Test, console2, Vm} from "forge-std/Test.sol"; import {Vm, VmSafe} from "forge-std/Vm.sol"; -interface Imports {} +interface SymbioticCoreImports {} diff --git a/test/integration/ImportsContracts.sol b/test/integration/SymbioticCoreImportsContracts.sol similarity index 98% rename from test/integration/ImportsContracts.sol rename to test/integration/SymbioticCoreImportsContracts.sol index 56d60f6..b70de5f 100644 --- a/test/integration/ImportsContracts.sol +++ b/test/integration/SymbioticCoreImportsContracts.sol @@ -34,4 +34,4 @@ import {NetworkMiddlewareService as SymbioticNetworkMiddlewareService} from import {OptInService as SymbioticOptInService} from "../../src/contracts/service/OptInService.sol"; import {VaultConfigurator as SymbioticVaultConfigurator} from "../../src/contracts/VaultConfigurator.sol"; -interface ImportsContracts {} +interface SymbioticCoreImportsContracts {} diff --git a/test/integration/SymbioticInit.sol b/test/integration/SymbioticCoreInit.sol similarity index 64% rename from test/integration/SymbioticInit.sol rename to test/integration/SymbioticCoreInit.sol index 1705c90..a081736 100644 --- a/test/integration/SymbioticInit.sol +++ b/test/integration/SymbioticCoreInit.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "./Imports.sol"; +import "./SymbioticCoreImports.sol"; -import {Constants as SymbioticCoreConstants} from "./Constants.sol"; -import {Counter as SymbioticCoreCounter} from "./Counter.sol"; -import {Bindings as SymbioticBindings} from "./Bindings.sol"; +import {SymbioticCoreConstants} from "./SymbioticCoreConstants.sol"; +import {SymbioticCoreCounter} from "./SymbioticCoreCounter.sol"; +import {SymbioticCoreBindings} from "./SymbioticCoreBindings.sol"; import {Token} from "../mocks/Token.sol"; import {FeeOnTransferToken} from "../mocks/FeeOnTransferToken.sol"; @@ -14,24 +14,37 @@ import {IERC5267} from "@openzeppelin/contracts/interfaces/IERC5267.sol"; import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; +import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; -contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { +contract SymbioticCoreInit is SymbioticCoreCounter, SymbioticCoreBindings { using SafeERC20 for IERC20; using Math for uint256; + using SymbioticSubnetwork for bytes32; + using SymbioticSubnetwork for address; // General config + uint256 public SYMBIOTIC_CORE_SEED = 0; + string public SYMBIOTIC_CORE_PROJECT_ROOT = ""; uint256 public SYMBIOTIC_CORE_INIT_TIMESTAMP = 1_731_324_431; uint256 public SYMBIOTIC_CORE_INIT_BLOCK = 21_164_139; uint256 public SYMBIOTIC_CORE_BLOCK_TIME = 12; - bool public USE_EXISTING_DEPLOYMENT = false; + bool public SYMBIOTIC_CORE_USE_EXISTING_DEPLOYMENT = false; // Staker-related config uint256 public TOKENS_TO_SET_TIMES_1e18 = 100_000_000 * 1e18; uint256 public MIN_TOKENS_TO_DEPOSIT_TIMES_1e18 = 0.001 * 1e18; uint256 public MAX_TOKENS_TO_DEPOSIT_TIMES_1e18 = 10_000 * 1e18; + uint256 public MIN_MAX_NETWORK_LIMIT_TIMES_1e18 = 0.001 * 1e18; + uint256 public MAX_MAX_NETWORK_LIMIT_TIMES_1e18 = 2_000_000_000 * 1e18; + uint256 public MIN_NETWORK_LIMIT_TIMES_1e18 = 0.001 * 1e18; + uint256 public MAX_NETWORK_LIMIT_TIMES_1e18 = 2_000_000_000 * 1e18; + uint256 public MIN_OPERATOR_NETWORK_LIMIT_TIMES_1e18 = 0.001 * 1e18; + uint256 public MAX_OPERATOR_NETWORK_LIMIT_TIMES_1e18 = 2_000_000_000 * 1e18; + uint256 public MIN_OPERATOR_NETWORK_SHARES = 1000; + uint256 public MAX_OPERATOR_NETWORK_SHARES = 1e18; SymbioticCoreConstants.Core symbioticCore; @@ -43,7 +56,7 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { vm.roll(SYMBIOTIC_CORE_INIT_BLOCK); } - _initCore_SymbioticCore(USE_EXISTING_DEPLOYMENT); + _initCore_SymbioticCore(SYMBIOTIC_CORE_USE_EXISTING_DEPLOYMENT); } // ------------------------------------------------------------ GENERAL HELPERS ------------------------------------------------------------ // @@ -218,13 +231,21 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { } function random_SymbioticCore() internal returns (uint256) { - return uint256(keccak256(abi.encode(vm.getBlockTimestamp(), vm.getBlockNumber(), count()))); + return uint256(keccak256(abi.encode(SYMBIOTIC_CORE_SEED, vm.getBlockTimestamp(), vm.getBlockNumber(), count()))); + } + + function randomChoice_SymbioticCore( + uint256 coef + ) internal returns (bool) { + return _bound(random_SymbioticCore(), 0, coef) == 0; + } + + function randomWithBounds_SymbioticCore(uint256 lower, uint256 upper) internal returns (uint256) { + return _bound(random_SymbioticCore(), lower, upper); } - function random_SymbioticCore( - uint256 seed - ) internal returns (uint256) { - return uint256(keccak256(abi.encode(vm.getBlockTimestamp(), vm.getBlockNumber(), count(), seed))); + function _limit2tokens_SymbioticCore(uint256 amount, uint256 decimals) internal returns (uint256) { + return amount.mulDiv(10 ** decimals, 1e18); } function _getAccount_SymbioticCore() internal returns (Vm.Wallet memory) { @@ -260,6 +281,23 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { return false; } + function _getWalletByAddress_SymbioticCore( + Vm.Wallet[] memory array, + address element + ) internal returns (Vm.Wallet memory) { + for (uint256 i; i < array.length; ++i) { + if (array[i].addr == element) { + return array[i]; + } + } + } + + function _chooseAddress_SymbioticCore( + address[] memory array + ) internal returns (address) { + return array[_bound(random_SymbioticCore(), 0, array.length - 1)]; + } + modifier equalLengthsAddressAddress_SymbioticCore(address[] memory a, address[] memory b) { require(a.length == b.length, "Arrays must have equal lengths"); _; @@ -293,12 +331,6 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { } } - function _chooseToken_SymbioticCore( - address[] memory tokens - ) internal returns (address) { - return tokens[bound(random_SymbioticCore(), 0, tokens.length - 1)]; - } - // ------------------------------------------------------------ VAULT-RELATED HELPERS ------------------------------------------------------------ // function _getVault_SymbioticCore( @@ -483,6 +515,22 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { return vault; } + function _vaultValidating_SymbioticCore(address vault, bytes32 subnetwork) internal returns (bool) { + address delegator = ISymbioticVault(vault).delegator(); + uint64 type_ = ISymbioticEntity(delegator).TYPE(); + + bool delegatorSpecificCondition; + if (type_ == 0) { + delegatorSpecificCondition = ISymbioticNetworkRestakeDelegator(delegator).networkLimit(subnetwork) > 0; + } else if (type_ == 1) { + delegatorSpecificCondition = ISymbioticNetworkRestakeDelegator(delegator).networkLimit(subnetwork) > 0; + } else if (type_ == 2) { + delegatorSpecificCondition = ISymbioticNetworkRestakeDelegator(delegator).networkLimit(subnetwork) > 0; + } + + return delegatorSpecificCondition; + } + // ------------------------------------------------------------ OPERATOR-RELATED HELPERS ------------------------------------------------------------ // function _getOperator_SymbioticCore() internal returns (Vm.Wallet memory) { @@ -501,15 +549,6 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { return operator; } - function _getOperatorWithOptIns_SymbioticCore(address vault, address network) internal returns (Vm.Wallet memory) { - Vm.Wallet memory operator = _getOperator_SymbioticCore(); - - _optIn_SymbioticCore(symbioticCore, operator.addr, vault); - _optIn_SymbioticCore(symbioticCore, operator.addr, network); - - return operator; - } - function _getOperatorWithOptIns_SymbioticCore( address[] memory vaults ) internal returns (Vm.Wallet memory) { @@ -522,6 +561,15 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { return operator; } + function _getOperatorWithOptIns_SymbioticCore(address vault, address network) internal returns (Vm.Wallet memory) { + Vm.Wallet memory operator = _getOperator_SymbioticCore(); + + _optIn_SymbioticCore(symbioticCore, operator.addr, vault); + _optIn_SymbioticCore(symbioticCore, operator.addr, network); + + return operator; + } + function _getOperatorWithOptIns_SymbioticCore( address[] memory vaults, address[] memory networks @@ -543,6 +591,21 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { _optIn_SymbioticCore(symbioticCore, operator, where); } + function _operatorOptInWeak_SymbioticCore(address operator, address where) internal { + bool alreadyOptedIn; + if (symbioticCore.vaultFactory.isEntity(where)) { + alreadyOptedIn = symbioticCore.operatorVaultOptInService.isOptedIn(operator, where); + } else if (symbioticCore.networkRegistry.isEntity(where)) { + alreadyOptedIn = symbioticCore.operatorNetworkOptInService.isOptedIn(operator, where); + } + + if (alreadyOptedIn) { + return; + } + + _operatorOptIn_SymbioticCore(operator, where); + } + function _operatorOptOut_SymbioticCore(address operator, address where) internal { _optOut_SymbioticCore(symbioticCore, operator, where); } @@ -633,6 +696,38 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { return keccak256(abi.encode(DOMAIN_TYPEHASH, NAME_HASH, VERSION_HASH, chainId, service)); } + function _operatorPossibleValidating_SymbioticCore( + address operator, + address vault, + bytes32 subnetwork + ) internal returns (bool) { + address delegator = ISymbioticVault(vault).delegator(); + uint64 type_ = ISymbioticEntity(delegator).TYPE(); + + bool delegatorSpecificCondition; + if (type_ == 0) { + delegatorSpecificCondition = ISymbioticNetworkRestakeDelegator(delegator).networkLimit(subnetwork) > 0 + && ISymbioticNetworkRestakeDelegator(delegator).operatorNetworkShares(subnetwork, operator) > 0; + } else if (type_ == 1) { + delegatorSpecificCondition = ISymbioticNetworkRestakeDelegator(delegator).networkLimit(subnetwork) > 0 + && ISymbioticFullRestakeDelegator(delegator).operatorNetworkLimit(subnetwork, operator) > 0; + } else if (type_ == 2) { + delegatorSpecificCondition = ISymbioticOperatorSpecificDelegator(delegator).operator() == operator + && ISymbioticNetworkRestakeDelegator(delegator).networkLimit(subnetwork) > 0; + } + + return symbioticCore.operatorVaultOptInService.isOptedIn(operator, vault) && delegatorSpecificCondition; + } + + function _operatorConfirmedValidating_SymbioticCore( + address operator, + address vault, + bytes32 subnetwork + ) internal returns (bool) { + return _operatorPossibleValidating_SymbioticCore(operator, vault, subnetwork) + && symbioticCore.operatorNetworkOptInService.isOptedIn(operator, subnetwork.network()); + } + // ------------------------------------------------------------ NETWORK-RELATED HELPERS ------------------------------------------------------------ // function _getNetwork_SymbioticCore() internal returns (Vm.Wallet memory) { @@ -654,6 +749,17 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { return network; } + function _getNetworkWithMaxNetworkLimitsRandom_SymbioticCore( + uint96 identifier, + address vault + ) internal returns (Vm.Wallet memory) { + Vm.Wallet memory network = _getNetwork_SymbioticCore(); + + _networkSetMaxNetworkLimitRandom_SymbioticCore(network.addr, vault, identifier); + + return network; + } + function _getNetworkWithMaxNetworkLimits_SymbioticCore( uint96[] memory identifiers, address[] memory vaults, @@ -673,6 +779,19 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { return network; } + function _getNetworkWithMaxNetworkLimitsRandom_SymbioticCore( + uint96[] memory identifiers, + address[] memory vaults + ) internal equalLengthsUint96Address_SymbioticCore(identifiers, vaults) returns (Vm.Wallet memory) { + Vm.Wallet memory network = _getNetwork_SymbioticCore(); + + for (uint256 i; i < vaults.length; ++i) { + _networkSetMaxNetworkLimitRandom_SymbioticCore(network.addr, vaults[i], identifiers[i]); + } + + return network; + } + function _getNetworkWithMaxNetworkLimitsAndResolvers_SymbioticCore( uint96 identifier, address vault, @@ -687,6 +806,19 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { return network; } + function _getNetworkWithMaxNetworkLimitsAndResolversRandom_SymbioticCore( + uint96 identifier, + address vault, + address resolver + ) internal returns (Vm.Wallet memory) { + Vm.Wallet memory network = _getNetwork_SymbioticCore(); + + _networkSetMaxNetworkLimitRandom_SymbioticCore(network.addr, vault, identifier); + _setResolver_SymbioticCore(network.addr, vault, identifier, resolver); + + return network; + } + function _getNetworkWithMaxNetworkLimits_SymbioticCore( uint96[] memory identifiers, address[] memory vaults, @@ -709,7 +841,27 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { return network; } - function _networkSetMaxNetworkLimit( + function _getNetworkWithMaxNetworkLimitsRandom_SymbioticCore( + uint96[] memory identifiers, + address[] memory vaults, + address[] memory resolvers + ) + internal + equalLengthsUint96Address_SymbioticCore(identifiers, vaults) + equalLengthsUint96Address_SymbioticCore(identifiers, resolvers) + returns (Vm.Wallet memory) + { + Vm.Wallet memory network = _getNetwork_SymbioticCore(); + + for (uint256 i; i < vaults.length; ++i) { + _networkSetMaxNetworkLimitRandom_SymbioticCore(network.addr, vaults[i], identifiers[i]); + _setResolver_SymbioticCore(network.addr, vaults[i], identifiers[i], resolvers[i]); + } + + return network; + } + + function _networkSetMaxNetworkLimit_SymbioticCore( address network, address vault, uint96 identifier, @@ -718,7 +870,46 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { _setMaxNetworkLimit_SymbioticCore(network, vault, identifier, maxNetworkLimit); } - function _networkSetResolver(address network, address vault, uint96 identifier, address resolver) internal { + function _networkSetMaxNetworkLimitRandom_SymbioticCore( + address network, + address vault, + uint96 identifier + ) internal { + address collateral = ISymbioticVault(vault).collateral(); + uint256 decimals = ERC20(collateral).decimals(); + uint256 amount = randomWithBounds_SymbioticCore( + _limit2tokens_SymbioticCore(MIN_MAX_NETWORK_LIMIT_TIMES_1e18, decimals), + _limit2tokens_SymbioticCore(MAX_MAX_NETWORK_LIMIT_TIMES_1e18, decimals) + ); + if ( + ISymbioticBaseDelegator(ISymbioticVault(vault).delegator()).maxNetworkLimit(network.subnetwork(identifier)) + == amount + ) { + return; + } + _networkSetMaxNetworkLimit_SymbioticCore(network, vault, identifier, amount); + } + + function _networkSetMaxNetworkLimitReset_SymbioticCore( + address network, + address vault, + uint96 identifier + ) internal { + if ( + ISymbioticBaseDelegator(ISymbioticVault(vault).delegator()).maxNetworkLimit(network.subnetwork(identifier)) + == 0 + ) { + return; + } + _networkSetMaxNetworkLimit_SymbioticCore(network, vault, identifier, 0); + } + + function _networkSetResolver_SymbioticCore( + address network, + address vault, + uint96 identifier, + address resolver + ) internal { _setResolver_SymbioticCore(network, vault, identifier, resolver); } @@ -731,13 +922,34 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { for (uint256 i; i < possibleTokens.length; ++i) { uint256 decimals = ERC20(possibleTokens[i]).decimals(); - deal(possibleTokens[i], staker.addr, TOKENS_TO_SET_TIMES_1e18.mulDiv(10 ** decimals, 1e18), true); // should cover most cases + deal(possibleTokens[i], staker.addr, _limit2tokens_SymbioticCore(TOKENS_TO_SET_TIMES_1e18, decimals), true); // should cover most cases } return staker; } - function _getStakerWithStakes_SymbioticCore( + function _getStakerWithStake_SymbioticCore( + address[] memory possibleTokens, + address vault + ) internal returns (Vm.Wallet memory) { + Vm.Wallet memory staker = _getStaker_SymbioticCore(possibleTokens); + + address collateral = ISymbioticVault(vault).collateral(); + uint256 decimals = ERC20(collateral).decimals(); + + _deposit_SymbioticCore( + staker.addr, + vault, + randomWithBounds_SymbioticCore( + _limit2tokens_SymbioticCore(MIN_TOKENS_TO_DEPOSIT_TIMES_1e18, decimals), + _limit2tokens_SymbioticCore(MAX_TOKENS_TO_DEPOSIT_TIMES_1e18, decimals) + ) + ); + + return staker; + } + + function _getStakerWithStake_SymbioticCore( address[] memory possibleTokens, address[] memory vaults ) internal returns (Vm.Wallet memory) { @@ -747,13 +959,14 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { address collateral = ISymbioticVault(vaults[i]).collateral(); uint256 decimals = ERC20(collateral).decimals(); - uint256 amount = bound( - random_SymbioticCore(), - MIN_TOKENS_TO_DEPOSIT_TIMES_1e18.mulDiv(10 ** decimals, 1e18), - MAX_TOKENS_TO_DEPOSIT_TIMES_1e18.mulDiv(10 ** decimals, 1e18) + _deposit_SymbioticCore( + staker.addr, + vaults[i], + randomWithBounds_SymbioticCore( + _limit2tokens_SymbioticCore(MIN_TOKENS_TO_DEPOSIT_TIMES_1e18, decimals), + _limit2tokens_SymbioticCore(MAX_TOKENS_TO_DEPOSIT_TIMES_1e18, decimals) + ) ); - - _deposit_SymbioticCore(staker.addr, vaults[i], amount); } return staker; @@ -767,13 +980,24 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { address collateral = ISymbioticVault(vault).collateral(); uint256 decimals = ERC20(collateral).decimals(); - uint256 amount = bound( - random_SymbioticCore(), - MIN_TOKENS_TO_DEPOSIT_TIMES_1e18.mulDiv(10 ** decimals, 1e18), - MAX_TOKENS_TO_DEPOSIT_TIMES_1e18.mulDiv(10 ** decimals, 1e18) + if (ISymbioticVault(vault).depositWhitelist()) { + return; + } + + uint256 minAmount = _limit2tokens_SymbioticCore(MIN_TOKENS_TO_DEPOSIT_TIMES_1e18, decimals); + uint256 amount = randomWithBounds_SymbioticCore( + minAmount, _limit2tokens_SymbioticCore(MAX_TOKENS_TO_DEPOSIT_TIMES_1e18, decimals) ); - _stakerDeposit_SymbioticCore(staker, vault, amount); + if (ISymbioticVault(vault).isDepositLimit()) { + uint256 depositLimit = ISymbioticVault(vault).depositLimit(); + uint256 activeStake = ISymbioticVault(vault).activeStake(); + amount = Math.min(depositLimit - Math.min(activeStake, depositLimit), amount); + } + + if (amount >= minAmount) { + _stakerDeposit_SymbioticCore(staker, vault, amount); + } } function _stakerWithdraw_SymbioticCore(address staker, address vault, uint256 amount) internal { @@ -783,7 +1007,11 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { function _stakerWithdrawRandom_SymbioticCore(address staker, address vault) internal { uint256 balance = ISymbioticVault(vault).activeBalanceOf(staker); - uint256 amount = bound(random_SymbioticCore(), 1, balance); + if (balance == 0) { + return; + } + + uint256 amount = _bound(random_SymbioticCore(), 1, balance); _stakerWithdraw_SymbioticCore(staker, vault, amount); } @@ -827,10 +1055,6 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { _setHook_SymbioticCore(curator, vault, hook); } - function _curatorSetHook_SymbioticCore(address vault, address hook) internal { - _curatorSetHook_SymbioticCore(address(this), vault, hook); - } - function _curatorSetNetworkLimit_SymbioticCore( address curator, address vault, @@ -840,8 +1064,36 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { _setNetworkLimit_SymbioticCore(curator, vault, subnetwork, amount); } - function _curatorSetNetworkLimit_SymbioticCore(address vault, bytes32 subnetwork, uint256 amount) internal { - _curatorSetNetworkLimit_SymbioticCore(address(this), vault, subnetwork, amount); + function _curatorSetNetworkLimitRandom_SymbioticCore(address curator, address vault, bytes32 subnetwork) internal { + address collateral = ISymbioticVault(vault).collateral(); + uint256 decimals = ERC20(collateral).decimals(); + address delegator = ISymbioticVault(vault).delegator(); + uint64 type_ = ISymbioticEntity(delegator).TYPE(); + + uint256 minAmount = _limit2tokens_SymbioticCore(MIN_NETWORK_LIMIT_TIMES_1e18, decimals); + uint256 maxAmount = _limit2tokens_SymbioticCore(MAX_NETWORK_LIMIT_TIMES_1e18, decimals); + + uint256 amount; + if (type_ == 0 || type_ == 1 || type_ == 2) { + uint256 maxNetworkLimit = ISymbioticBaseDelegator(delegator).maxNetworkLimit(subnetwork); + if (maxNetworkLimit < minAmount) { + _curatorSetNetworkLimitReset_SymbioticCore(curator, vault, subnetwork); + return; + } + amount = randomWithBounds_SymbioticCore(minAmount, Math.min(maxNetworkLimit, maxAmount)); + } + + if (ISymbioticNetworkRestakeDelegator(delegator).networkLimit(subnetwork) == amount) { + return; + } + _curatorSetNetworkLimit_SymbioticCore(curator, vault, subnetwork, amount); + } + + function _curatorSetNetworkLimitReset_SymbioticCore(address curator, address vault, bytes32 subnetwork) internal { + if (ISymbioticNetworkRestakeDelegator(ISymbioticVault(vault).delegator()).networkLimit(subnetwork) == 0) { + return; + } + _curatorSetNetworkLimit_SymbioticCore(curator, vault, subnetwork, 0); } function _curatorSetOperatorNetworkShares_SymbioticCore( @@ -854,13 +1106,37 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { _setOperatorNetworkShares_SymbioticCore(curator, vault, subnetwork, operator, shares); } - function _curatorSetOperatorNetworkShares_SymbioticCore( + function _curatorSetOperatorNetworkSharesRandom_SymbioticCore( + address curator, address vault, bytes32 subnetwork, - address operator, - uint256 shares + address operator + ) internal { + uint256 shares = randomWithBounds_SymbioticCore(MIN_OPERATOR_NETWORK_SHARES, MAX_OPERATOR_NETWORK_SHARES); + if ( + ISymbioticNetworkRestakeDelegator(ISymbioticVault(vault).delegator()).operatorNetworkShares( + subnetwork, operator + ) == shares + ) { + return; + } + _setOperatorNetworkShares_SymbioticCore(curator, vault, subnetwork, operator, shares); + } + + function _curatorSetOperatorNetworkSharesReset_SymbioticCore( + address curator, + address vault, + bytes32 subnetwork, + address operator ) internal { - _curatorSetOperatorNetworkShares_SymbioticCore(address(this), vault, subnetwork, operator, shares); + if ( + ISymbioticNetworkRestakeDelegator(ISymbioticVault(vault).delegator()).operatorNetworkShares( + subnetwork, operator + ) == 0 + ) { + return; + } + _setOperatorNetworkShares_SymbioticCore(curator, vault, subnetwork, operator, 0); } function _curatorSetOperatorNetworkLimit_SymbioticCore( @@ -873,12 +1149,141 @@ contract SymbioticInit is SymbioticCoreCounter, SymbioticBindings { _setOperatorNetworkLimit_SymbioticCore(curator, vault, subnetwork, operator, amount); } - function _curatorSetOperatorNetworkLimit_SymbioticCore( + function _curatorSetOperatorNetworkLimitRandom_SymbioticCore( + address curator, address vault, bytes32 subnetwork, - address operator, - uint256 amount + address operator + ) internal { + address collateral = ISymbioticVault(vault).collateral(); + uint256 decimals = ERC20(collateral).decimals(); + uint256 amount = randomWithBounds_SymbioticCore( + _limit2tokens_SymbioticCore(MIN_OPERATOR_NETWORK_LIMIT_TIMES_1e18, decimals), + _limit2tokens_SymbioticCore(MAX_OPERATOR_NETWORK_LIMIT_TIMES_1e18, decimals) + ); + if ( + ISymbioticFullRestakeDelegator(ISymbioticVault(vault).delegator()).operatorNetworkLimit( + subnetwork, operator + ) == amount + ) { + return; + } + _setOperatorNetworkLimit_SymbioticCore(curator, vault, subnetwork, operator, amount); + } + + function _curatorSetOperatorNetworkLimitReset_SymbioticCore( + address curator, + address vault, + bytes32 subnetwork, + address operator + ) internal { + if ( + ISymbioticFullRestakeDelegator(ISymbioticVault(vault).delegator()).operatorNetworkLimit( + subnetwork, operator + ) == 0 + ) { + return; + } + _setOperatorNetworkLimit_SymbioticCore(curator, vault, subnetwork, operator, 0); + } + + function _curatorDelegateNetworkRandom_SymbioticCore(address curator, address vault, bytes32 subnetwork) internal { + address delegator = ISymbioticVault(vault).delegator(); + uint64 type_ = ISymbioticEntity(delegator).TYPE(); + + if (type_ == 0) { + _curatorSetNetworkLimitRandom_SymbioticCore(curator, vault, subnetwork); + } else if (type_ == 1) { + _curatorSetNetworkLimitRandom_SymbioticCore(curator, vault, subnetwork); + } else if (type_ == 2) {} + } + + function _curatorDelegateNetworkHasRoles_SymbioticCore( + address curator, + address vault, + bytes32 /* subnetwork */ + ) internal returns (bool) { + address delegator = ISymbioticVault(vault).delegator(); + uint64 type_ = ISymbioticEntity(delegator).TYPE(); + + if (type_ == 0) { + return IAccessControl(delegator).hasRole( + ISymbioticNetworkRestakeDelegator(delegator).NETWORK_LIMIT_SET_ROLE(), curator + ); + } else if (type_ == 1) { + return IAccessControl(delegator).hasRole( + ISymbioticFullRestakeDelegator(delegator).NETWORK_LIMIT_SET_ROLE(), curator + ); + } else if (type_ == 2) {} + + return true; + } + + function _curatorDelegateOperatorRandom_SymbioticCore( + address curator, + address vault, + bytes32 subnetwork, + address operator + ) internal { + address delegator = ISymbioticVault(vault).delegator(); + uint64 type_ = ISymbioticEntity(delegator).TYPE(); + + if (type_ == 0) { + _curatorSetOperatorNetworkSharesRandom_SymbioticCore(curator, vault, subnetwork, operator); + } else if (type_ == 1) { + _curatorSetOperatorNetworkLimitRandom_SymbioticCore(curator, vault, subnetwork, operator); + } else if (type_ == 2) { + if (ISymbioticOperatorSpecificDelegator(delegator).operator() == operator) { + _curatorSetNetworkLimitRandom_SymbioticCore(curator, vault, subnetwork); + } + } + } + + function _curatorDelegateOperatorHasRoles_SymbioticCore( + address curator, + address vault, + bytes32, /* subnetwork */ + address operator + ) internal returns (bool) { + address delegator = ISymbioticVault(vault).delegator(); + uint64 type_ = ISymbioticEntity(delegator).TYPE(); + + if (type_ == 0) { + return IAccessControl(delegator).hasRole( + ISymbioticNetworkRestakeDelegator(delegator).OPERATOR_NETWORK_SHARES_SET_ROLE(), curator + ); + } else if (type_ == 1) { + return IAccessControl(delegator).hasRole( + ISymbioticFullRestakeDelegator(delegator).OPERATOR_NETWORK_LIMIT_SET_ROLE(), curator + ); + } else if (type_ == 2) { + if (ISymbioticOperatorSpecificDelegator(delegator).operator() == operator) { + return IAccessControl(delegator).hasRole( + ISymbioticOperatorSpecificDelegator(delegator).NETWORK_LIMIT_SET_ROLE(), curator + ); + } + } + + return true; + } + + function _curatorDelegateRandom_SymbioticCore( + address curator, + address vault, + bytes32 subnetwork, + address operator ) internal { - _curatorSetOperatorNetworkLimit_SymbioticCore(address(this), vault, subnetwork, operator, amount); + _curatorDelegateNetworkRandom_SymbioticCore(curator, vault, subnetwork); + _curatorDelegateOperatorRandom_SymbioticCore(curator, vault, subnetwork, operator); + } + + function _curatorDelegateHasRoles_SymbioticCore( + address curator, + address vault, + bytes32 subnetwork, + address operator + ) internal returns (bool) { + return _curatorDelegateNetworkHasRoles_SymbioticCore(curator, vault, subnetwork) + && _curatorDelegateOperatorHasRoles_SymbioticCore(curator, vault, subnetwork, operator); } } diff --git a/test/integration/SymbioticCoreIntegration.sol b/test/integration/SymbioticCoreIntegration.sol new file mode 100644 index 0000000..97569b0 --- /dev/null +++ b/test/integration/SymbioticCoreIntegration.sol @@ -0,0 +1,397 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./SymbioticCoreInit.sol"; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; + +contract SymbioticCoreIntegration is SymbioticCoreInit { + using SymbioticSubnetwork for bytes32; + using SymbioticSubnetwork for address; + + address[] public tokens; + + address[] public vaults; + Vm.Wallet[] public networks; + Vm.Wallet[] public operators; + Vm.Wallet[] public stakers; + + address[] public existingTokens; + address[] public existingVaults; + Vm.Wallet[] public existingNetworks; + Vm.Wallet[] public existingOperators; + + // allocated network stake + mapping(bytes32 subnetwork => mapping(address vault => bool)) public isVaultForSubnetwork; + mapping(bytes32 subnetwork => address[] vaults) public vaultsForSubnetwork; + // fully opted in and has stake + mapping(bytes32 subnetwork => mapping(address vault => mapping(address operator => bool))) public + isConfirmedOperatorForSubnetwork; + mapping(bytes32 subnetwork => mapping(address vault => address[] operators)) public confirmedOperatorsForSubnetwork; + // only needs to opt into network (map be used to test opt-in with signature) + mapping(bytes32 subnetwork => mapping(address vault => mapping(address operator => bool))) public + isPossibleOperatorForSubnetwork; + mapping(bytes32 subnetwork => mapping(address vault => address[] operators)) public possibleOperatorsForSubnetwork; + + uint256 public SYMBIOTIC_CORE_NUMBER_OF_VAULTS = 20; + uint256 public SYMBIOTIC_CORE_NUMBER_OF_NETWORKS = 10; + uint256 public SYMBIOTIC_CORE_NUMBER_OF_OPERATORS = 20; + uint256 public SYMBIOTIC_CORE_NUMBER_OF_STAKERS = 30; + + uint256 public SYMBIOTIC_CORE_DEPOSIT_INTO_VAULT_CHANCE = 1; // lower -> higher probability + uint256 public SYMBIOTIC_CORE_WITHDRAW_FROM_VAULT_CHANCE = 3; + uint256 public SYMBIOTIC_CORE_MAX_NETWORK_LIMIT_CHANCE = 1; + uint256 public SYMBIOTIC_CORE_DELEGATE_TO_NETWORK_CHANCE = 1; + uint256 public SYMBIOTIC_CORE_DELEGATE_TO_OPERATOR_CHANCE = 1; + uint256 public SYMBIOTIC_CORE_OPT_IN_TO_VAULT_CHANCE = 1; + uint256 public SYMBIOTIC_CORE_OPT_IN_TO_NETWORK_CHANCE = 1; + + uint96[] public SYMBIOTIC_CORE_SUBNETWORKS = [0, 1, 2]; + + function setUp() public virtual override { + // vm.selectFork(vm.createFork(vm.rpcUrl("mainnet"))); + // SYMBIOTIC_CORE_PROJECT_ROOT = ""; + + super.setUp(); + + _loadPossibleTokens(); + + _loadExistingEntities(); + if (SYMBIOTIC_CORE_USE_EXISTING_DEPLOYMENT) { + _loadExistingTokens(); + _loadExistingVaults(); + _loadExistingNetworks(); + _loadExistingOperators(); + } + + _createEnvironment(); + + _loadDataForNetworks(); + } + + function _loadExistingEntities() internal virtual { + if (SYMBIOTIC_CORE_USE_EXISTING_DEPLOYMENT) { + uint256 numberOfVaults = ISymbioticRegistry(symbioticCore.vaultFactory).totalEntities(); + for (uint256 i; i < numberOfVaults; ++i) { + address vault = ISymbioticRegistry(symbioticCore.vaultFactory).entity(i); + existingVaults.push(vault); + existingTokens.push(ISymbioticVault(vault).collateral()); + } + uint256 numberOfNetworks = ISymbioticRegistry(symbioticCore.networkRegistry).totalEntities(); + for (uint256 i; i < numberOfNetworks; ++i) { + existingNetworks.push( + VmSafe.Wallet({ + addr: ISymbioticRegistry(symbioticCore.networkRegistry).entity(i), + publicKeyX: 0, + publicKeyY: 0, + privateKey: 0 + }) + ); + } + uint256 numberOfOperators = ISymbioticRegistry(symbioticCore.operatorRegistry).totalEntities(); + for (uint256 i; i < numberOfOperators; ++i) { + existingOperators.push( + VmSafe.Wallet({ + addr: ISymbioticRegistry(symbioticCore.operatorRegistry).entity(i), + publicKeyX: 0, + publicKeyY: 0, + privateKey: 0 + }) + ); + } + } + } + + function _loadPossibleTokens() internal virtual { + // address[] memory supportedTokens = _getSupportedTokens_SymbioticCore(); + // if (supportedTokens.length != 0) { + // for (uint256 i; i < supportedTokens.length; i++) { + // tokens.push(supportedTokens[i]); + // } + // } else { + // tokens.push(_getToken_SymbioticCore()); + // tokens.push(_getFeeOnTransferToken_SymbioticCore()); + // } + + tokens.push(_getToken_SymbioticCore()); + tokens.push(_getFeeOnTransferToken_SymbioticCore()); + } + + function _loadExistingTokens() internal virtual { + for (uint256 i; i < existingTokens.length; ++i) { + if (!_contains_SymbioticCore(tokens, existingTokens[i])) { + tokens.push(existingTokens[i]); + } + } + } + + function _loadExistingVaults() internal virtual { + for (uint256 i; i < existingVaults.length; ++i) { + if (!_contains_SymbioticCore(vaults, existingVaults[i])) { + vaults.push(existingVaults[i]); + } + } + } + + function _loadExistingNetworks() internal virtual { + for (uint256 i; i < existingNetworks.length; ++i) { + if (!_contains_SymbioticCore(networks, existingNetworks[i])) { + networks.push(existingNetworks[i]); + } + } + } + + function _loadExistingOperators() internal virtual { + for (uint256 i; i < existingOperators.length; ++i) { + if (!_contains_SymbioticCore(operators, existingOperators[i])) { + operators.push(existingOperators[i]); + } + } + } + + function _createEnvironment() internal virtual { + _createParties( + SYMBIOTIC_CORE_NUMBER_OF_VAULTS, + SYMBIOTIC_CORE_NUMBER_OF_NETWORKS, + SYMBIOTIC_CORE_NUMBER_OF_OPERATORS, + SYMBIOTIC_CORE_NUMBER_OF_STAKERS + ); + + _depositIntoVaults(); + _withdrawFromVaults(); + + _setMaxNetworkLimits(); + _delegateToNetworks(); + _delegateToOperators(); + _optInOperators(); + } + + function _createParties( + uint256 numberOfVaults, + uint256 numberOfNetworks, + uint256 numberOfOperators, + uint256 numberOfStakers + ) internal virtual { + for (uint256 i; i < numberOfVaults; ++i) { + vaults.push(_getVault_SymbioticCore(_chooseAddress_SymbioticCore(tokens))); + } + for (uint256 i; i < numberOfNetworks; ++i) { + networks.push(_getNetwork_SymbioticCore()); + } + for (uint256 i; i < numberOfOperators; ++i) { + operators.push(_getOperator_SymbioticCore()); + } + for (uint256 i; i < numberOfStakers; ++i) { + stakers.push(_getStaker_SymbioticCore(tokens)); + } + } + + function _depositIntoVaults() internal virtual { + for (uint256 i; i < stakers.length; ++i) { + for (uint256 j; j < vaults.length; ++j) { + if (randomChoice_SymbioticCore(SYMBIOTIC_CORE_DEPOSIT_INTO_VAULT_CHANCE)) { + _stakerDepositRandom_SymbioticCore(stakers[i].addr, vaults[j]); + } + } + } + } + + function _withdrawFromVaults() internal virtual { + for (uint256 i; i < stakers.length; ++i) { + for (uint256 j; j < vaults.length; ++j) { + if (randomChoice_SymbioticCore(SYMBIOTIC_CORE_WITHDRAW_FROM_VAULT_CHANCE)) { + _stakerWithdrawRandom_SymbioticCore(stakers[i].addr, vaults[j]); + } + } + } + } + + function _setMaxNetworkLimits() internal virtual { + for (uint256 i; i < vaults.length; ++i) { + for (uint256 j; j < networks.length; ++j) { + for (uint256 k; k < SYMBIOTIC_CORE_SUBNETWORKS.length; ++k) { + if (randomChoice_SymbioticCore(SYMBIOTIC_CORE_MAX_NETWORK_LIMIT_CHANCE)) { + _networkSetMaxNetworkLimitRandom_SymbioticCore( + networks[j].addr, vaults[i], SYMBIOTIC_CORE_SUBNETWORKS[k] + ); + } + } + } + } + } + + function _delegateToNetworks() internal virtual { + for (uint256 i; i < vaults.length; ++i) { + for (uint256 j; j < networks.length; ++j) { + for (uint256 k; k < SYMBIOTIC_CORE_SUBNETWORKS.length; ++k) { + if ( + _curatorDelegateNetworkHasRoles_SymbioticCore( + address(this), vaults[i], networks[j].addr.subnetwork(SYMBIOTIC_CORE_SUBNETWORKS[k]) + ) + ) { + if (randomChoice_SymbioticCore(SYMBIOTIC_CORE_DELEGATE_TO_NETWORK_CHANCE)) { + _curatorDelegateNetworkRandom_SymbioticCore( + address(this), vaults[i], networks[j].addr.subnetwork(SYMBIOTIC_CORE_SUBNETWORKS[k]) + ); + } + continue; + } + + if ( + _curatorDelegateNetworkHasRoles_SymbioticCore( + Ownable(vaults[i]).owner(), + vaults[i], + networks[j].addr.subnetwork(SYMBIOTIC_CORE_SUBNETWORKS[k]) + ) + ) { + if (randomChoice_SymbioticCore(SYMBIOTIC_CORE_DELEGATE_TO_NETWORK_CHANCE)) { + _curatorDelegateNetworkRandom_SymbioticCore( + Ownable(vaults[i]).owner(), + vaults[i], + networks[j].addr.subnetwork(SYMBIOTIC_CORE_SUBNETWORKS[k]) + ); + } + } + } + } + } + } + + function _delegateToOperators() internal virtual { + for (uint256 i; i < vaults.length; ++i) { + for (uint256 j; j < networks.length; ++j) { + for (uint256 k; k < SYMBIOTIC_CORE_SUBNETWORKS.length; ++k) { + for (uint256 l; l < operators.length; ++l) { + if ( + _curatorDelegateOperatorHasRoles_SymbioticCore( + address(this), + vaults[i], + networks[j].addr.subnetwork(SYMBIOTIC_CORE_SUBNETWORKS[k]), + operators[l].addr + ) + ) { + if (randomChoice_SymbioticCore(SYMBIOTIC_CORE_DELEGATE_TO_OPERATOR_CHANCE)) { + _curatorDelegateOperatorRandom_SymbioticCore( + address(this), + vaults[i], + networks[j].addr.subnetwork(SYMBIOTIC_CORE_SUBNETWORKS[k]), + operators[l].addr + ); + } + continue; + } + + if ( + _curatorDelegateOperatorHasRoles_SymbioticCore( + Ownable(vaults[i]).owner(), + vaults[i], + networks[j].addr.subnetwork(SYMBIOTIC_CORE_SUBNETWORKS[k]), + operators[l].addr + ) + ) { + if (randomChoice_SymbioticCore(SYMBIOTIC_CORE_DELEGATE_TO_OPERATOR_CHANCE)) { + _curatorDelegateOperatorRandom_SymbioticCore( + Ownable(vaults[i]).owner(), + vaults[i], + networks[j].addr.subnetwork(SYMBIOTIC_CORE_SUBNETWORKS[k]), + operators[l].addr + ); + } + } + } + } + } + } + } + + function _optInOperators() internal virtual { + _optInOperatorsVauls(); + _optInOperatorsNetworks(); + } + + function _optInOperatorsVauls() internal virtual { + for (uint256 i; i < vaults.length; ++i) { + for (uint256 j; j < operators.length; ++j) { + if (randomChoice_SymbioticCore(SYMBIOTIC_CORE_OPT_IN_TO_VAULT_CHANCE)) { + _operatorOptInWeak_SymbioticCore(operators[j].addr, vaults[i]); + } + } + } + } + + function _optInOperatorsNetworks() internal virtual { + for (uint256 i; i < networks.length; ++i) { + for (uint256 j; j < networks.length; ++j) { + if (randomChoice_SymbioticCore(SYMBIOTIC_CORE_OPT_IN_TO_NETWORK_CHANCE)) { + _operatorOptInWeak_SymbioticCore(operators[j].addr, networks[i].addr); + } + } + } + } + + function _loadDataForNetworks() internal virtual { + for (uint256 i; i < networks.length; ++i) { + for (uint256 j; j < SYMBIOTIC_CORE_SUBNETWORKS.length; ++j) { + bytes32 subnetwork = networks[i].addr.subnetwork(SYMBIOTIC_CORE_SUBNETWORKS[j]); + for (uint256 k; k < vaults.length; ++k) { + if (_vaultValidating_SymbioticCore(vaults[k], subnetwork)) { + isVaultForSubnetwork[subnetwork][vaults[k]] = true; + vaultsForSubnetwork[subnetwork].push(vaults[k]); + } + + for (uint256 l; l < operators.length; ++l) { + if (_operatorPossibleValidating_SymbioticCore(operators[l].addr, vaults[k], subnetwork)) { + isPossibleOperatorForSubnetwork[subnetwork][vaults[k]][operators[l].addr] = true; + possibleOperatorsForSubnetwork[subnetwork][vaults[k]].push(operators[l].addr); + } + if (_operatorConfirmedValidating_SymbioticCore(operators[l].addr, vaults[k], subnetwork)) { + isConfirmedOperatorForSubnetwork[subnetwork][vaults[k]][operators[l].addr] = true; + confirmedOperatorsForSubnetwork[subnetwork][vaults[k]].push(operators[l].addr); + } + } + } + } + } + } + + function test_Abc() public { + address network = networks[0].addr; + uint96 identifier = SYMBIOTIC_CORE_SUBNETWORKS[0]; + address collateral = tokens[0]; + bytes32 subnetwork = network.subnetwork(identifier); + + for (uint256 i; i < vaultsForSubnetwork[subnetwork].length; ++i) { + address vault = vaultsForSubnetwork[subnetwork][i]; + console2.log("Vault:", vault); + } + + for (uint256 i; i < vaultsForSubnetwork[subnetwork].length; ++i) { + address vault = vaultsForSubnetwork[subnetwork][i]; + if (ISymbioticVault(vault).collateral() == collateral) { + for (uint256 j; j < confirmedOperatorsForSubnetwork[subnetwork][vault].length; ++j) { + address operator = confirmedOperatorsForSubnetwork[subnetwork][vault][j]; + console2.log("Vault/Operator:", vault, operator); + } + } + } + + address vault = vaultsForSubnetwork[subnetwork][0]; + Vm.Wallet memory newOperator = _getOperatorWithOptIns_SymbioticCore(vault, network); + _curatorDelegateRandom_SymbioticCore(address(this), vault, subnetwork, newOperator.addr); + + console2.log( + "Stake before new staker:", + ISymbioticBaseDelegator(ISymbioticVault(vault).delegator()).stake(subnetwork, newOperator.addr) + ); + console2.log("Total stake before new staker:", ISymbioticVault(vault).totalStake()); + + Vm.Wallet memory newStaker = _getStakerWithStake_SymbioticCore(tokens, vault); + + console2.log( + "Stake after new staker:", + ISymbioticBaseDelegator(ISymbioticVault(vault).delegator()).stake(subnetwork, newOperator.addr) + ); + console2.log("Total stake after new staker:", ISymbioticVault(vault).totalStake()); + console2.log("User stake:", ISymbioticVault(vault).slashableBalanceOf(newStaker.addr)); + } +} diff --git a/test/integration/SymbioticIntegration.sol b/test/integration/SymbioticIntegration.sol deleted file mode 100644 index c11c795..0000000 --- a/test/integration/SymbioticIntegration.sol +++ /dev/null @@ -1,153 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "./SymbioticInit.sol"; - -contract SymbioticIntegration is SymbioticInit { - address[] public tokens; - - address[] public vaults; - Vm.Wallet[] public networks; - Vm.Wallet[] public operators; - Vm.Wallet[] public stakers; - - address[] public existingTokens; - address[] public existingVaults; - Vm.Wallet[] public existingNetworks; - Vm.Wallet[] public existingOperators; - - uint256 public NUMBER_OF_VAULTS = 20; - uint256 public NUMBER_OF_NETWORKS = 40; - uint256 public NUMBER_OF_OPERATORS = 100; - uint256 public NUMBER_OF_STAKERS = 200; - - bool public SIMULATION_WITH_WITHDRAWALS = true; - - function setUp() public virtual override { - // vm.selectFork(vm.createFork(vm.rpcUrl("mainnet"))); - // SYMBIOTIC_CORE_PROJECT_ROOT = ""; - - super.setUp(); - - _loadPossibleTokens(); - - _loadExistingEntities(); - if (USE_EXISTING_DEPLOYMENT) { - _loadExistingTokens(); - _loadExistingVaults(); - _loadExistingNetworks(); - _loadExistingOperators(); - } - - _createEnvironment(); - } - - function _loadExistingEntities() internal { - if (USE_EXISTING_DEPLOYMENT) { - uint256 numberOfVaults = ISymbioticRegistry(symbioticCore.vaultFactory).totalEntities(); - for (uint256 i; i < numberOfVaults; ++i) { - address vault = ISymbioticRegistry(symbioticCore.vaultFactory).entity(i); - existingVaults.push(vault); - existingTokens.push(ISymbioticVault(vault).collateral()); - } - uint256 numberOfNetworks = ISymbioticRegistry(symbioticCore.networkRegistry).totalEntities(); - for (uint256 i; i < numberOfNetworks; ++i) { - existingNetworks.push( - VmSafe.Wallet({ - addr: ISymbioticRegistry(symbioticCore.networkRegistry).entity(i), - publicKeyX: 0, - publicKeyY: 0, - privateKey: 0 - }) - ); - } - uint256 numberOfOperators = ISymbioticRegistry(symbioticCore.operatorRegistry).totalEntities(); - for (uint256 i; i < numberOfOperators; ++i) { - existingOperators.push( - VmSafe.Wallet({ - addr: ISymbioticRegistry(symbioticCore.operatorRegistry).entity(i), - publicKeyX: 0, - publicKeyY: 0, - privateKey: 0 - }) - ); - } - } - } - - function _loadPossibleTokens() internal { - address[] memory supportedTokens = _getSupportedTokens_SymbioticCore(); - if (supportedTokens.length != 0) { - for (uint256 i; i < supportedTokens.length; i++) { - tokens.push(supportedTokens[i]); - } - } else { - tokens.push(_getToken_SymbioticCore()); - tokens.push(_getFeeOnTransferToken_SymbioticCore()); - } - } - - function _loadExistingTokens() internal { - for (uint256 i; i < existingTokens.length; ++i) { - if (!_contains_SymbioticCore(tokens, existingTokens[i])) { - tokens.push(existingTokens[i]); - } - } - } - - function _loadExistingVaults() internal { - for (uint256 i; i < existingVaults.length; ++i) { - if (!_contains_SymbioticCore(vaults, existingVaults[i])) { - vaults.push(existingVaults[i]); - } - } - } - - function _loadExistingNetworks() internal { - for (uint256 i; i < existingNetworks.length; ++i) { - if (!_contains_SymbioticCore(networks, existingNetworks[i])) { - networks.push(existingNetworks[i]); - } - } - } - - function _loadExistingOperators() internal { - for (uint256 i; i < existingOperators.length; ++i) { - if (!_contains_SymbioticCore(operators, existingOperators[i])) { - operators.push(existingOperators[i]); - } - } - } - - function _createEnvironment() internal { - _createParties(NUMBER_OF_VAULTS, NUMBER_OF_NETWORKS, NUMBER_OF_OPERATORS, NUMBER_OF_STAKERS); - - if (SIMULATION_WITH_WITHDRAWALS) {} - } - - function _createParties( - uint256 numberOfVaults, - uint256 numberOfNetworks, - uint256 numberOfOperators, - uint256 numberOfStakers - ) internal { - for (uint256 i; i < numberOfVaults; ++i) { - vaults.push(_getVault_SymbioticCore(_chooseToken_SymbioticCore(tokens))); - } - for (uint256 i; i < numberOfNetworks; ++i) { - networks.push(_getNetwork_SymbioticCore()); - } - for (uint256 i; i < numberOfOperators; ++i) { - operators.push(_getOperator_SymbioticCore()); - } - for (uint256 i; i < numberOfStakers; ++i) { - stakers.push(_getStaker_SymbioticCore(tokens)); - } - } - - function test_Abc() public { - console2.log(vm.getBlockTimestamp(), vm.getBlockNumber()); - _skipBlocks_SymbioticCore(36); - console2.log(vm.getBlockTimestamp(), vm.getBlockNumber()); - } -}