diff --git a/scripts/vote_2024_11_26.py b/scripts/vote_2024_11_26.py new file mode 100644 index 00000000..e8568df1 --- /dev/null +++ b/scripts/vote_2024_11_26.py @@ -0,0 +1,168 @@ +""" +Voting 26/11/2024. + +I. Change the limits for ET on ATC & PML +1. ATC: increase from 1,5m per quarter to 7m USDC/USDT/DAI per quarter - set 7'000'000 limit on ATC registry `0xe07305F43B11F230EaA951002F6a55a16419B707` for 3 mos +2. PML: decrease from 6m per quarter to 4m USDC/USDT/DAI per quarter - set 4'000'000 limit on PML registry `0xDFfCD3BF14796a62a804c1B16F877Cf7120379dB` for 3 mos + +II. TMC limits update +3. Reset the TMC amount spent on TMC registry `0x1a7cFA9EFB4D5BfFDE87B0FaEb1fC65d653868C0` +4. Update TMC limit to 12,000 stETH on TMC registry `0x1a7cFA9EFB4D5BfFDE87B0FaEb1fC65d653868C0` for 6 mos + +III. Simply staking reward address change +5. Change staking reward address to `0x1EC3Cbe8fb1D8019092500CcA2111C158a35bC82` for node operator with id = 16 + +Vote passed & executed on XXX-XX-XXXX XX:XX:XX PM UTC, block #XXXXXXXX. +""" + +import time + +from typing import Dict, Tuple, Optional, List + +from brownie import interface +from brownie.network.transaction import TransactionReceipt +from utils.voting import bake_vote_items, confirm_vote_script, create_vote +from utils.easy_track import add_evmscript_factory, create_permissions +from utils.permission_parameters import Param, SpecialArgumentID, ArgumentValue, Op +from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description +from utils.node_operators import encode_set_node_operator_reward_address + +from utils.config import ( + get_deployer_account, + contracts, + get_is_live, + get_priority_fee, +) + +from utils.easy_track import ( + add_evmscript_factory, + create_permissions, + remove_evmscript_factory +) +from utils.allowed_recipients_registry import ( + set_limit_parameters, + update_spent_amount, + unsafe_set_spent_amount +) + +from utils.agent import agent_forward + +description = """ +I. Change the limits for ET on ATC & PML +1. ATC: increase from 1,5m per quarter to 7m USDC/USDT/DAI per quarter - set 7'000'000 limit on ATC registry `0xe07305F43B11F230EaA951002F6a55a16419B707` for 3 mos +2. PML: decrease from 6m per quarter to 4m USDC/USDT/DAI per quarter - set 4'000'000 limit on PML registry `0xDFfCD3BF14796a62a804c1B16F877Cf7120379dB` for 3 mos + +II. TMC limits update +3. Update TMC limit to 12,000 stETH on TMC registry `0x1a7cFA9EFB4D5BfFDE87B0FaEb1fC65d653868C0` for 6 mos +4. Reset the TMC amount spent on TMC registry `0x1a7cFA9EFB4D5BfFDE87B0FaEb1fC65d653868C0` + +III. Simply staking reward address change +5. Change staking reward address to `0x1EC3Cbe8fb1D8019092500CcA2111C158a35bC82` for node operator with id = 16 +""" + +def start_vote(tx_params: Dict[str, str], silent: bool) -> bool | list[int | TransactionReceipt | None]: + """Prepare and run voting.""" + + atc_registry = interface.AllowedRecipientRegistry("0xe07305F43B11F230EaA951002F6a55a16419B707") + pml_registry = interface.AllowedRecipientRegistry("0xDFfCD3BF14796a62a804c1B16F877Cf7120379dB") + + tmc_registry = interface.AllowedRecipientRegistry("0x1a7cFA9EFB4D5BfFDE87B0FaEb1fC65d653868C0") + + NO_registry = contracts.node_operators_registry + SimplyStaking_id = 16 + SimplyStaking_new_reward_address = "0x1EC3Cbe8fb1D8019092500CcA2111C158a35bC82" + + vote_desc_items, call_script_items = zip( + # + # I. Change the limits for ET on ATC & PML + # + ( + "1. Set 7'000'000 limit on ATC registry `0xe07305F43B11F230EaA951002F6a55a16419B707` for 3 mos", + agent_forward( + [ + set_limit_parameters( + registry_address=atc_registry, + limit=7_000_000 * 10 ** 18, + period_duration_months=3 + ), + ] + ), + ), + ( + "2. Set 4'000'000 limit on PML registry `0xDFfCD3BF14796a62a804c1B16F877Cf7120379dB` for 3 mos", + agent_forward( + [ + set_limit_parameters( + registry_address=pml_registry, + limit=4_000_000 * 10 ** 18, + period_duration_months=3 + ), + ] + ), + ), + # + # II. TMC limits update + # + ( + "3. Update TMC limit to 12,000 stETH on TMC registry `0x1a7cFA9EFB4D5BfFDE87B0FaEb1fC65d653868C0` for 6 mos", + agent_forward( + [ + set_limit_parameters( + registry_address=tmc_registry, + limit=12_000 * 10 ** 18, + period_duration_months=6 + ), + ] + ), + ), + ( + "4. Reset the TMC amount spent on TMC registry `0x1a7cFA9EFB4D5BfFDE87B0FaEb1fC65d653868C0`", + agent_forward( + [ + unsafe_set_spent_amount( + spent_amount=0, + registry_address=tmc_registry + ), + ] + ), + ), + # + # III. Simply staking reward address change + # + ( + "5. Change staking reward address to `0x1EC3Cbe8fb1D8019092500CcA2111C158a35bC82` for node operator with id = 16", + agent_forward( + [ + encode_set_node_operator_reward_address( + SimplyStaking_id, + SimplyStaking_new_reward_address, + NO_registry + ), + ] + ), + ), + ) + + vote_items = bake_vote_items(list(vote_desc_items), list(call_script_items)) + + if silent: + desc_ipfs = calculate_vote_ipfs_description(description) + else: + desc_ipfs = upload_vote_ipfs_description(description) + + return confirm_vote_script(vote_items, silent, desc_ipfs) and list( + create_vote(vote_items, tx_params, desc_ipfs=desc_ipfs) + ) + + +def main(): + tx_params = {"from": get_deployer_account()} + + if get_is_live(): + tx_params["priority_fee"] = get_priority_fee() + + vote_id, _ = start_vote(tx_params=tx_params, silent=False) + + vote_id >= 0 and print(f"Vote created: {vote_id}.") + + time.sleep(5) # hack for waiting thread #2. \ No newline at end of file diff --git a/tests/test_2024_11_26.py b/tests/test_2024_11_26.py new file mode 100644 index 00000000..338b747b --- /dev/null +++ b/tests/test_2024_11_26.py @@ -0,0 +1,110 @@ +""" +Tests for voting 26/11/2024. +""" + +from scripts.vote_2024_11_26 import start_vote +from brownie import interface, ZERO_ADDRESS, reverts, web3, accounts, convert +from utils.test.tx_tracing_helpers import * +from utils.voting import find_metadata_by_vote_id +from utils.ipfs import get_lido_vote_cid_from_str +from utils.config import contracts, LDO_HOLDER_ADDRESS_FOR_TESTS, network_name +from utils.easy_track import create_permissions +from utils.test.easy_track_helpers import create_and_enact_payment_motion, check_add_and_remove_recipient_with_voting +from utils.test.event_validators.easy_track import ( + validate_evmscript_factory_added_event, + EVMScriptFactoryAdded, + validate_evmscript_factory_removed_event, +) +from utils.test.event_validators.allowed_recipients_registry import ( + validate_set_limit_parameter_event +) +from configs.config_holesky import ( + DAI_TOKEN, + USDC_TOKEN, + USDT_TOKEN, +) + + +# STETH_TRANSFER_MAX_DELTA = 2 + +def test_vote(helpers, accounts, vote_ids_from_env, stranger, ldo_holder, bypass_events_decoding): + + # NO's data indexes + activeIndex = 0 + nameIndex = 1 + rewardAddressIndex = 2 + stakingLimitIndex = 3 + stoppedValidatorsIndex = 4 + + nor = contracts.node_operators_registry + + # easy_track = interface.EasyTrack("0xF0211b7660680B49De1A7E9f25C65660F0a13Fea") + + atc_allowed_recipients_registry = interface.AllowedRecipientRegistry("0xe07305F43B11F230EaA951002F6a55a16419B707") + pml_allowed_recipients_registry = interface.AllowedRecipientRegistry("0xDFfCD3BF14796a62a804c1B16F877Cf7120379dB") + tmc_allowed_recipients_registry = interface.AllowedRecipientRegistry("0x1a7cFA9EFB4D5BfFDE87B0FaEb1fC65d653868C0") + #atc_top_up_evm_script_factory = interface.TopUpAllowedRecipients("0x1843Bc35d1fD15AbE1913b9f72852a79457C42Ab") + atc_multisig_acc = accounts.at("0x9B1cebF7616f2BC73b47D226f90b01a7c9F86956", force=True) + #atc_trusted_caller_acc = atc_multisig_acc + SimplyStakingId = 16 + SimplyStakingOldRewardAddress = "0xFEf3C7aa6956D03dbad8959c59155c4A465DCacd" + SimplyStakingNewRewardAddress = "0x1EC3Cbe8fb1D8019092500CcA2111C158a35bC82" + + # Item 1 + atcBudgetLimitBefore, atcPeriodDurationMonthsBefore = interface.AllowedRecipientRegistry(atc_allowed_recipients_registry).getLimitParameters() + assert atcBudgetLimitBefore == 1_500_000 * 10 ** 18 + assert atcPeriodDurationMonthsBefore == 3 + + # Item 2 + pmlBudgetLimitBefore, pmlPeriodDurationMonthsBefore = interface.AllowedRecipientRegistry(pml_allowed_recipients_registry).getLimitParameters() + assert pmlBudgetLimitBefore == 6_000_000 * 10 ** 18 + assert pmlPeriodDurationMonthsBefore == 3 + + # Item 3 + tmcBudgetLimitBefore, tmcPeriodDurationMonthsBefore = interface.AllowedRecipientRegistry(tmc_allowed_recipients_registry).getLimitParameters() + assert tmcBudgetLimitBefore == 9_000 * 10 ** 18 + assert tmcPeriodDurationMonthsBefore == 6 + + # Item 4 + alreadySpentAmountBefore, spendableBalanceInPeriodBefore, periodStartTimestampBefore, periodEndTimestampBefore = tmc_allowed_recipients_registry.getPeriodState() + assert alreadySpentAmountBefore > 0 + + # Item 5 + SimplyStakingDataBefore = nor.getNodeOperator(SimplyStakingId, True) + assert SimplyStakingOldRewardAddress == SimplyStakingDataBefore[rewardAddressIndex] + + + # START VOTE + if len(vote_ids_from_env) > 0: + (vote_id,) = vote_ids_from_env + else: + tx_params = {"from": LDO_HOLDER_ADDRESS_FOR_TESTS} + vote_id, _ = start_vote(tx_params, silent=True) + + vote_tx = helpers.execute_vote(accounts, vote_id, contracts.voting) + + print(f"voteId = {vote_id}, gasUsed = {vote_tx.gas_used}") + + + # Item 1 + atcBudgetLimitAfter, atcPeriodDurationMonthsAfter = interface.AllowedRecipientRegistry(atc_allowed_recipients_registry).getLimitParameters() + assert atcBudgetLimitAfter == 7_000_000 * 10 ** 18 + assert atcPeriodDurationMonthsAfter == 3 + + # Item 2 + pmlBudgetLimitAfter, pmlPeriodDurationMonthsAfter = interface.AllowedRecipientRegistry(pml_allowed_recipients_registry).getLimitParameters() + assert pmlBudgetLimitAfter == 4_000_000 * 10 ** 18 + assert pmlPeriodDurationMonthsAfter == 3 + + # Item 3 + tmcBudgetLimitAfter, tmcPeriodDurationMonthsAfter = interface.AllowedRecipientRegistry(tmc_allowed_recipients_registry).getLimitParameters() + assert tmcBudgetLimitAfter == 12_000 * 10 ** 18 + assert tmcPeriodDurationMonthsAfter == 6 + + # Item 4 + alreadySpentAmountAfter, spendableBalanceInPeriodAfter, periodStartTimestampAfter, periodEndTimestampAfter = tmc_allowed_recipients_registry.getPeriodState() + assert alreadySpentAmountAfter == 0 + + # Item 5 + SimplyStakingDataAfter = nor.getNodeOperator(SimplyStakingId, True) + assert SimplyStakingNewRewardAddress == SimplyStakingDataAfter[rewardAddressIndex] \ No newline at end of file diff --git a/utils/allowed_recipients_registry.py b/utils/allowed_recipients_registry.py index 40b11d86..3d4c5576 100644 --- a/utils/allowed_recipients_registry.py +++ b/utils/allowed_recipients_registry.py @@ -14,6 +14,9 @@ def update_spent_amount(registry_address: str, spent_amount: int) -> Tuple[str, registry = interface.AllowedRecipientRegistry(registry_address) return (registry.address, registry.updateSpentAmount.encode_input(spent_amount)) +def unsafe_set_spent_amount(registry_address: str, spent_amount: int) -> Tuple[str, str]: + registry = interface.AllowedRecipientRegistry(registry_address) + return (registry.address, registry.unsafeSetSpentAmount.encode_input(spent_amount)) def create_top_up_allowed_recipient_permission(registry_address: str) -> str: return (