diff --git a/Makefile b/Makefile index a72480bc28..7aa792c182 100644 --- a/Makefile +++ b/Makefile @@ -289,6 +289,24 @@ verifier_disable: @echo "Disabling verifier with ID: $(VERIFIER_ID)" @. contracts/scripts/.env && . contracts/scripts/disable_verifier.sh $(VERIFIER_ID) +strategies_get_weight: + @echo "Getting weight of strategy: $(STRATEGY_INDEX)" + @. contracts/scripts/.env.$(NETWORK) && . contracts/scripts/get_strategy_weight.sh $(STRATEGY_INDEX) + +strategies_update_weight: + @echo "Updating strategy weights: " + @echo "STRATEGY_INDICES: $(STRATEGY_INDICES)" + @echo "NEW_MULTIPLIERS: $(NEW_MULTIPLIERS)" + @. contracts/scripts/.env.$(NETWORK) && . contracts/scripts/update_strategy_weight.sh $(STRATEGY_INDICES) $(NEW_MULTIPLIERS) + +strategies_remove: + @echo "Removing strategies: $(INDICES_TO_REMOVE)" + @. contracts/scripts/.env.$(NETWORK) && . contracts/scripts/remove_strategy.sh $(INDICES_TO_REMOVE) + +strategies_get_addresses: + @echo "Getting strategy addresses" + @. contracts/scripts/.env.$(NETWORK) && . contracts/scripts/get_restakeable_strategies.sh + __BATCHER__: BURST_SIZE ?= 5 diff --git a/contracts/scripts/get_restakeable_strategies.sh b/contracts/scripts/get_restakeable_strategies.sh new file mode 100755 index 0000000000..c09866bd7a --- /dev/null +++ b/contracts/scripts/get_restakeable_strategies.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# cd to the directory of this script so that this can be run from anywhere +parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) +# At this point we are in contracts/scripts +cd "$parent_path" + +# At this point we are in contracts +cd ../ + +if [ -z "$OUTPUT_PATH" ]; then + echo "OUTPUT_PATH env var is not set" + exit 1 +fi + +if [ -z "$RPC_URL" ]; then + echo "RPC_URL env var is not set" + exit 1 +fi + +ALIGNED_SERVICE_MANAGER=$(jq -r '.addresses.alignedLayerServiceManager' "$OUTPUT_PATH") + +## Using in this cast call: + +# /** +# * @notice Returns the list of strategies that the AVS supports for restaking +# * @dev This function is intended to be called off-chain +# * @dev No guarantee is made on uniqueness of each element in the returned array. +# * The off-chain service should do that validation separately +# */ +# function getRestakeableStrategies() external view returns (address[] memory) { + +cast call $ALIGNED_SERVICE_MANAGER "getRestakeableStrategies()(address[])" --rpc-url $RPC_URL + +# Expected output: +# [addresses] +# example: +# [0xc5a5C42992dECbae36851359345FE25997F5C42d, 0x80528D6e9A2BAbFc766965E0E26d5aB08D9CFaF9] diff --git a/contracts/scripts/get_strategy_weight.sh b/contracts/scripts/get_strategy_weight.sh new file mode 100755 index 0000000000..cb5a04bff1 --- /dev/null +++ b/contracts/scripts/get_strategy_weight.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# cd to the directory of this script so that this can be run from anywhere +parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) +# At this point we are in contracts/scripts +cd "$parent_path" + +# At this point we are in contracts +cd ../ + +if [ "$#" -ne 1 ]; then + echo "Error: 1 arguments is required, STRATEGY_INDEX" + exit 1 +fi + +STRATEGY_INDEX=$1 + +if [ -z "$OUTPUT_PATH" ]; then + echo "OUTPUT_PATH env var is not set" + exit 1 +fi + +if [ -z "$RPC_URL" ]; then + echo "RPC_URL env var is not set" + exit 1 +fi + +STAKE_REGISTRY=$(jq -r '.addresses.stakeRegistry' "$OUTPUT_PATH") + +## Using in this cast call: + +# struct StrategyParams { +# IStrategy strategy; (iface -> address) +# uint96 multiplier; +# } + +# /// @notice Returns the strategy and weight multiplier for the `index`'th strategy in the quorum `quorumNumber` +# function strategyParamsByIndex( +# uint8 quorumNumber, +# uint256 index +# ) public view returns (StrategyParams memory) +# + +QUORUM_NUMER=0x0 #Aligned has only 1 quorum for now + +cast call $STAKE_REGISTRY "strategyParamsByIndex(uint8,uint256)((address,uint96))" $QUORUM_NUMER $STRATEGY_INDEX --rpc-url $RPC_URL + +# Expected output: +# (strategy_address, multiplier) +# example: +# (0xc5a5C42992dECbae36851359345FE25997F5C42d, 1000000000000000000 [1e18]) diff --git a/contracts/scripts/remove_strategy.sh b/contracts/scripts/remove_strategy.sh new file mode 100755 index 0000000000..b63ac68d08 --- /dev/null +++ b/contracts/scripts/remove_strategy.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +# cd to the directory of this script so that this can be run from anywhere +parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) +# At this point we are in contracts/scripts +cd "$parent_path" + +# At this point we are in contracts +cd ../ + +if [ "$#" -ne 1 ]; then + echo "Error: 1 arguments is required, INDICES_TO_REMOVE" + exit 1 +fi + +INDICES_TO_REMOVE=$1 + +if [[ ! "$INDICES_TO_REMOVE" =~ ^\[[0-9]+(,[0-9]+)*\]$ ]]; then + echo "The INDICES_TO_REMOVE doesn't match the required format: [0,1,...,n]" + exit 1 +fi + +if [ -z "$MULTISIG" ]; then + echo "MULTISIG env var is not set" + exit 1 +fi +if [ "$MULTISIG" = false ]; then + if [ -z "$PRIVATE_KEY" ]; then + echo "PRIVATE_KEY env var is not set" + exit 1 + fi + if [ -z "$RPC_URL" ]; then + echo "RPC_URL env var is not set" + exit 1 + fi + if [ -z "$OUTPUT_PATH" ]; then + echo "OUTPUT_PATH env var is not set" + exit 1 + fi + STAKE_REGISTRY=$(jq -r '.addresses.stakeRegistry' "$OUTPUT_PATH") +fi + + +## Using in this cast call: + + # /** + # * @notice This function is used for removing strategies and their associated weights from the + # * mapping strategyParams for a specific @param quorumNumber. + # * @dev higher indices should be *first* in the list of @param indicesToRemove, since otherwise + # * the removal of lower index entries will cause a shift in the indices of the other strategiesToRemove + # */ + # function removeStrategies(uint8 quorumNumber, uint256[] calldata indicesToRemove) external; + +QUORUM_NUMBER=0 #Aligned has only 1 quorum for now + +data=$(cast calldata "removeStrategies(uint8, uint256[])()" $QUORUM_NUMBER $INDICES_TO_REMOVE) + +if [ "$MULTISIG" = false ]; then + echo "Executing remove strategies transaction" + + cast send $STAKE_REGISTRY $data \ + --rpc-url $RPC_URL \ + --private-key $PRIVATE_KEY +else + echo "You can propose the remove strategies transaction with the multisig using this calldata:" + echo $data +fi diff --git a/contracts/scripts/update_strategy_weight.sh b/contracts/scripts/update_strategy_weight.sh new file mode 100755 index 0000000000..43f084685a --- /dev/null +++ b/contracts/scripts/update_strategy_weight.sh @@ -0,0 +1,100 @@ +#!/bin/bash + +# cd to the directory of this script so that this can be run from anywhere +parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) +# At this point we are in contracts/scripts +cd "$parent_path" + +# At this point we are in contracts +cd ../ + +if [ "$#" -ne 2 ]; then + echo "Error: 2 arguments are required, STRATEGY_INDICES and NEW_MULTIPLIERS" + exit 1 +fi + +STRATEGY_INDICES=$1 +NEW_MULTIPLIERS=$2 + + +if [[ ! "$STRATEGY_INDICES" =~ ^\[[0-9]+(,[0-9]+)*\]$ ]]; then + echo "The STRATEGY_INDICES doesn't match the required format: [0,1,...,n]" + exit 1 +fi + +if [ -z "$NEW_MULTIPLIERS" ]; then + echo "NEW_MULTIPLIERS env var is not set" + exit 1 +fi +if [[ ! "$NEW_MULTIPLIERS" =~ ^\[[0-9]+(,[0-9]+)*\]$ ]]; then + echo "The NEW_MULTIPLIERS doesn't match the required format: [0,1,...,n]" + exit 1 +fi + +count_elements() { + local var="$1" + # Remove brackets and count elements by splitting on commas + echo "$var" | sed 's/[\[\]]//g' | awk -F',' '{print NF}' +} +count1=$(count_elements "$STRATEGY_INDICES") +count2=$(count_elements "$NEW_MULTIPLIERS") + + +if [[ $count1 -ne $count2 ]]; then + echo "STRATEGY_INDICES and NEW_MULTIPLIERS have different numbers of elements:" + echo "STRATEGY_INDICES: $STRATEGY_INDICES" + echo "NEW_MULTIPLIERS: $NEW_MULTIPLIERS" + exit 1 +fi + + +if [ -z "$MULTISIG" ]; then + echo "MULTISIG env var is not set" + exit 1 +fi +if [ "$MULTISIG" = false ]; then + if [ -z "$PRIVATE_KEY" ]; then + echo "PRIVATE_KEY env var is not set" + exit 1 + fi + if [ -z "$RPC_URL" ]; then + echo "RPC_URL env var is not set" + exit 1 + fi + if [ -z "$OUTPUT_PATH" ]; then + echo "OUTPUT_PATH env var is not set" + exit 1 + fi + STAKE_REGISTRY=$(jq -r '.addresses.stakeRegistry' "$OUTPUT_PATH") +fi + + +## Using in this cast call: + +# /** +# * @notice This function is used for modifying the weights of strategies that are already in the +# * mapping strategyParams for a specific +# * @param quorumNumber is the quorum number to change the strategy for +# * @param strategyIndices are the indices of the strategies to change +# * @param newMultipliers are the new multipliers for the strategies +# */ +# function modifyStrategyParams( +# uint8 quorumNumber, +# uint256[] calldata strategyIndices, +# uint96[] calldata newMultipliers +# ) external; + +QUORUM_NUMBER=0 #Aligned has only 1 quorum for now + +data=$(cast calldata "modifyStrategyParams(uint8, uint256[], uint96[])()" $QUORUM_NUMBER $STRATEGY_INDICES $NEW_MULTIPLIERS) + +if [ "$MULTISIG" = false ]; then + echo "Executing modify strategy params transaction" + + cast send $STAKE_REGISTRY $data \ + --rpc-url $RPC_URL \ + --private-key $PRIVATE_KEY +else + echo "You can propose the modify strategy params transaction with the multisig using this calldata:" + echo $data +fi diff --git a/docs/0_internal/images/6_b_1_modify_strategies_1.png b/docs/0_internal/images/6_b_1_modify_strategies_1.png new file mode 100644 index 0000000000..639487d0b6 Binary files /dev/null and b/docs/0_internal/images/6_b_1_modify_strategies_1.png differ diff --git a/docs/0_internal/images/6_b_1_modify_strategies_2.png b/docs/0_internal/images/6_b_1_modify_strategies_2.png new file mode 100644 index 0000000000..a5b59fbc39 Binary files /dev/null and b/docs/0_internal/images/6_b_1_modify_strategies_2.png differ diff --git a/docs/0_internal/images/6_b_1_modify_strategies_3.png b/docs/0_internal/images/6_b_1_modify_strategies_3.png new file mode 100644 index 0000000000..a299f0cb9d Binary files /dev/null and b/docs/0_internal/images/6_b_1_modify_strategies_3.png differ diff --git a/docs/0_internal/images/6_b_1_modify_strategies_4.png b/docs/0_internal/images/6_b_1_modify_strategies_4.png new file mode 100644 index 0000000000..60ec848d65 Binary files /dev/null and b/docs/0_internal/images/6_b_1_modify_strategies_4.png differ diff --git a/docs/0_internal/images/6_b_1_modify_strategies_5.png b/docs/0_internal/images/6_b_1_modify_strategies_5.png new file mode 100644 index 0000000000..363c5838ff Binary files /dev/null and b/docs/0_internal/images/6_b_1_modify_strategies_5.png differ diff --git a/docs/0_internal/images/6_b_2_approve_1.png b/docs/0_internal/images/6_b_2_approve_1.png new file mode 100644 index 0000000000..03f7a880a5 Binary files /dev/null and b/docs/0_internal/images/6_b_2_approve_1.png differ diff --git a/docs/0_internal/images/6_b_2_approve_2.png b/docs/0_internal/images/6_b_2_approve_2.png new file mode 100644 index 0000000000..b7c379e810 Binary files /dev/null and b/docs/0_internal/images/6_b_2_approve_2.png differ diff --git a/docs/0_internal/modify strategies/6_a_modify_strategies.md b/docs/0_internal/modify strategies/6_a_modify_strategies.md new file mode 100644 index 0000000000..0a169144b4 --- /dev/null +++ b/docs/0_internal/modify strategies/6_a_modify_strategies.md @@ -0,0 +1,38 @@ +# Modify Strategy Weight Multipliers +This doc contains a guide on how to modify the strategy weight multipliers on Aligned. + +To run the make targets specified in this guide, you must first have the relevant following env vars under `contracts/scripts/.env`: +``` +RPC_URL= +PRIVATE_KEY= +OUTPUT_PATH= +MULTISIG=false +``` + +## +To view some relevant information you can: + +### Get all available strategies: + +``` +make strategies_get_addresses +``` + +### Get weight multiplier of a specific strategy: + +``` +make strategies_get_weight STRATEGY_INDEX= +``` + +### Update the weight of any amount of stratefies + +``` +make strategies_update_weight STRATEGY_INDICES="[0,1,...,n]" NEW_MULTIPLIERS="[0,1,...,n]" +``` + +### Remove a strategy + +``` +make strategies_remove INDICES_TO_REMOVE="[0,1,...,n]" +``` + diff --git a/docs/0_internal/modify strategies/6_b_1_propose_modify_strategies.md b/docs/0_internal/modify strategies/6_b_1_propose_modify_strategies.md new file mode 100644 index 0000000000..a5ae44b6a1 --- /dev/null +++ b/docs/0_internal/modify strategies/6_b_1_propose_modify_strategies.md @@ -0,0 +1,54 @@ +# Propose the Transaction for Modify Strategy Weight Multipliers using Multisig + +If you want to modify the Strategy Weight Multipliers the contracts, you can propose the transaction using the multisig wallet. + +## Prerequisites + +- You need to have deployed the contracts following the [Deploy Contracts Guide](./2_deploy_contracts.md). + +## Propose transaction for Pause AlignedLayerServiceManager + +To propose the modify Strategy Weight Multipliers transaction you can follow the steps below: + +1. Go to [Safe](https://app.safe.global/home) + +2. Click on `New transaction` -> `Transaction Builder` + + ![New transaction](../images/6_b_1_modify_strategies_1.png) + + ![Transaction Builder](../images/6_b_1_modify_strategies_2.png) + +3. . Get the `StakeRegistry` address from ```contracts/script/output/mainnet/alignedlayer_deployment_output.json``` or ```contracts/script/output/holesky/alignedlayer_deployment_output.json``` or ```contracts/script/output/sepolia/alignedlayer_deployment_output.json``` + +4. Paste the `StakeRegistry` address on `Enter Address or ENS Name` + +5. As this is a Proxy contract, choose `Use Implementation ABI` + +![use implementation abi](../images/6_b_1_modify_strategies_3.png) + +6. In `contract method selector` choose `modifyStrategyParams` , and fill in the parameter values accordingly. + +Note: Aligned currently only has `quorumNumber: 0`, and you will replace `strategyIndices` with `newMultipliers` + +![choose modify strategy params](../images/6_b_1_modify_strategies_4.png) + +7. Click on `+ Add new transaction` + + You should see the new transaction to be executed + +8. Click on `Create batch` to create the transaction. + +9. Simulate the transaction by clicking on `Simulate` + +10. If everything is correct, click on `Send batch` to send the transaction. + +11. Simulate the transaction, and if everything is correct, click on `Sign`. + +![send batch](../images/6_b_1_modify_strategies_5.png) + +> [!NOTE] +> In the `call` field, you will see `fallback`. + +12. Wait for the transaction to be executed. You can check the transaction status on the `Transactions` tab. + +If the transaction is correctly created, you have to wait until the required Multisig member signs the transaction to send it. For this, you can follow [the following guide](./6_b_2_approve_modify_strategies.md) diff --git a/docs/0_internal/modify strategies/6_b_2_approve_modify_strategies.md b/docs/0_internal/modify strategies/6_b_2_approve_modify_strategies.md new file mode 100644 index 0000000000..f1f6e8fdd8 --- /dev/null +++ b/docs/0_internal/modify strategies/6_b_2_approve_modify_strategies.md @@ -0,0 +1,37 @@ +# Approve the Modify Strategy Weight Multipliers Transaction + +Once the transaction is proposed, the multisig owners must approve the transaction. + +## Approve the Pause for AlignedLayerServiceManager + +1. Go to [Safe](https://app.safe.global/home) and connect your wallet. + +2. Go to the `Transactions` tab and find the transaction that was proposed. + +3. Get the ```modifyStrategyParams()()``` signature by running: + + ```bash + cast calldata "modifyStrategyParams(uint8,uint256[],uint96[])()" <[strategyIndices]> <[newMultipliers]> + ``` + + for example: + + ```bash + cast calldata "modifyStrategyParams(uint8,uint256[],uint96[])()" 0 "[0]" "[123456]" + ``` + + It must show you ```0x20b66298...```. + +4. Click on the transaction, and then click on ```Advanced Details```. + +![check details](../images/6_b_2_approve_1.png) + +5. Copy the ```Raw Data```, paste it in a text editor and verify it is the same value as the one you got in step 3. + +6. If the data is correct, click on the `Confirm` button. + +7. Simulate the transaction. If everything is correct, click on the `Sign` button, or `Execute` if you are the last signer. + +![Sign execute](../images/6_b_2_approve_2.png) + +8. Once the transaction is executed, the modification will be effective.