diff --git a/scripts/vote_2025_MM_DD.py b/scripts/vote_2025_MM_DD.py new file mode 100644 index 00000000..a5241e51 --- /dev/null +++ b/scripts/vote_2025_MM_DD.py @@ -0,0 +1,88 @@ +""" +# TODO Vote 2025__
+ +# TODO + +# TODO (after vote) Vote #{vote number} passed & executed on ${date+time}, block ${blockNumber}. +""" + + +import time + +from typing import Dict +from brownie import interface +from utils.voting import bake_vote_items, confirm_vote_script, create_vote +from utils.ipfs import upload_vote_ipfs_description, calculate_vote_ipfs_description +from utils.config import ( + get_deployer_account, + get_is_live, + get_priority_fee, +) +from utils.mainnet_fork import pass_and_exec_dao_vote + +# TODO + +IPFS_DESCRIPTION = """ +# TODO +""" + +# TODO + +def start_vote(tx_params: Dict[str, str], silent: bool = False): + # TODO arrange all variables neccessary for the vote + + vote_desc_items, call_script_items = zip( + # TODO + ( + "1. TODO ", + # TODO , + ), + ( + "2. TODO ", + # TODO , + ), + + # TODO + ( + "3. TODO ", + # TODO , + ), + ( + "4. TODO ", + # TODO , + ), + ) + + vote_items = bake_vote_items(list(vote_desc_items), list(call_script_items)) + + if silent: + desc_ipfs = calculate_vote_ipfs_description(IPFS_DESCRIPTION) + else: + desc_ipfs = upload_vote_ipfs_description(IPFS_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}.") + + +def start_and_execute_vote_on_fork_manual(): + if get_is_live(): + raise Exception("This script is for local testing only.") + + tx_params = {"from": get_deployer_account()} + vote_id, _ = start_vote(tx_params=tx_params, silent=True) + + time.sleep(5) # hack for waiting thread #2. + + print(f"Vote created: {vote_id}.") + pass_and_exec_dao_vote(int(vote_id), step_by_step=True) diff --git a/tests/_test_2025_MM_DD.py b/tests/_test_2025_MM_DD.py new file mode 100644 index 00000000..45ac4183 --- /dev/null +++ b/tests/_test_2025_MM_DD.py @@ -0,0 +1,81 @@ +from brownie import chain, interface +# TODO import voting script +from scripts. import start_vote +from brownie.network.transaction import TransactionReceipt +from utils.test.tx_tracing_helpers import * + + +# TODO list all contract addresses used in tests - do not use imports from config! +DUAL_GOVERNANCE = "0xcdF49b058D606AD34c5789FD8c3BF8B3E54bA2db" +EMERGENCY_PROTECTED_TIMELOCK = "0xCE0425301C85c5Ea2A0873A2dEe44d78E02D2316" +DUAL_GOVERNANCE_ADMIN_EXECUTOR = "0x23E0B465633FF5178808F4A75186E2F2F9537021" +VOTING = "0x2e59A20f205bB85a89C53f1936454680651E618e" +vote_events_count = # TODO <# of events emitted by the vote> +dg_proposal_id = # TODO (if DG proposal exists in vote) + + +def test_vote(helpers, accounts, ldo_holder, vote_ids_from_env, stranger): + + # ======================================================================= + # ========================= Arrange variables =========================== + # ======================================================================= + # TODO arrange all variables necessary for the test + dual_governance = interface.DualGovernance(DUAL_GOVERNANCE) + timelock = interface.EmergencyProtectedTimelock(EMERGENCY_PROTECTED_TIMELOCK) + voting = interface.Voting(VOTING) + + # ======================================================================= + # ========================= Before voting tests ========================= + # ======================================================================= + # TODO run asserts that check the "before" vote state + + # ======================================================================= + # ============================== Voting ================================= + # ======================================================================= + vote_id = vote_ids_from_env[0] if vote_ids_from_env else start_vote({"from": ldo_holder}, silent=True)[0] + vote_tx: TransactionReceipt = helpers.execute_vote(vote_id=vote_id, accounts=accounts, dao_voting=voting) + + # ======================================================================= + # ========================= After voting tests ========================== + # ======================================================================= + # TODO run asserts that check the "after" vote state + + # TODO run vote happy path tests + + # ======================================================================= + # ====================== Before DG Proposal tests ======================= + # ======================================================================= + # TODO (if DG proposal exists in vote) run asserts that checks the "before" DG proposal execution state + + # ======================================================================= + # ==================== DG Proposal Submit => Execute ==================== + # ======================================================================= + # TODO (if DG proposal exists in vote) execute DG proposal + chain.sleep(timelock.getAfterSubmitDelay() + 1) + dual_governance.scheduleProposal(dg_proposal_id, {"from": stranger}) + chain.sleep(timelock.getAfterScheduleDelay() + 1) + dg_tx: TransactionReceipt = timelock.execute(dg_proposal_id, {"from": stranger}) + + # ======================================================================= + # ================= After DG proposal execution tests =================== + # ======================================================================= + # TODO (if DG proposal exists in vote) run asserts that checks the "after" DG proposal execution state + + # TODO (if DG proposal exists in vote) run DG proposal happy path tests + + # ======================================================================= + # ======================== IPFS & events checks ========================= + # ======================================================================= + # TODO check IPFS description + #metadata = find_metadata_by_vote_id(vote_id) + #assert get_lido_vote_cid_from_str(metadata) == "TODO " + + # validate event count + evs = group_voting_events_from_receipt(vote_tx) + assert len(evs) == vote_events_count + assert count_vote_items_by_events(vote_tx, voting) == vote_events_count, "Incorrect voting items count" + + # TODO validate all events emitted during the vote (check the event emitter as well!) + + # TODO (if DG proposal exists in vote) validate all events emitted during the DG execution (check the event emitter as well!) + dg_evs = group_dg_events_from_receipt(dg_tx, timelock=EMERGENCY_PROTECTED_TIMELOCK, admin_executor=DUAL_GOVERNANCE_ADMIN_EXECUTOR)