Skip to content

Commit

Permalink
fix: simple dvt acceptance test
Browse files Browse the repository at this point in the history
  • Loading branch information
krogla committed Feb 12, 2024
1 parent 1817fcd commit d0d9847
Show file tree
Hide file tree
Showing 2 changed files with 259 additions and 4 deletions.
256 changes: 256 additions & 0 deletions tests/acceptance/test_simple_dvt_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
import pytest
from brownie import ZERO_ADDRESS, interface, web3, reverts # type: ignore

from utils.config import (
contracts,
SIMPLE_DVT,
SIMPLE_DVT_IMPL,
SIMPLE_DVT_ARAGON_APP_ID,
SIMPLE_DVT_MODULE_STUCK_PENALTY_DELAY,
SIMPLE_DVT_MODULE_TYPE,
EASYTRACK_SIMPLE_DVT_TRUSTED_CALLER,
EASYTRACK_EVMSCRIPT_EXECUTOR,
EASYTRACK_SIMPLE_DVT_ADD_NODE_OPERATORS_FACTORY,
EASYTRACK_SIMPLE_DVT_ACTIVATE_NODE_OPERATORS_FACTORY,
EASYTRACK_SIMPLE_DVT_DEACTIVATE_NODE_OPERATORS_FACTORY,
EASYTRACK_SIMPLE_DVT_SET_VETTED_VALIDATORS_LIMITS_FACTORY,
EASYTRACK_SIMPLE_DVT_SET_NODE_OPERATOR_NAMES_FACTORY,
EASYTRACK_SIMPLE_DVT_SET_NODE_OPERATOR_REWARD_ADDRESSES_FACTORY,
EASYTRACK_SIMPLE_DVT_UPDATE_TARGET_VALIDATOR_LIMITS_FACTORY,
EASYTRACK_SIMPLE_DVT_CHANGE_NODE_OPERATOR_MANAGERS_FACTORY,
)

REQUEST_BURN_SHARES_ROLE = "0x4be29e0e4eb91f98f709d98803cba271592782e293b84a625e025cbb40197ba8"
STAKING_ROUTER_ROLE = "0xbb75b874360e0bfd87f964eadd8276d8efb7c942134fc329b513032d0803e0c6"
MANAGE_NODE_OPERATOR_ROLE = "0x78523850fdd761612f46e844cf5a16bda6b3151d6ae961fd7e8e7b92bfbca7f8"
SET_NODE_OPERATOR_LIMIT_ROLE = "0x07b39e0faf2521001ae4e58cb9ffd3840a63e205d288dc9c93c3774f0d794754"
MANAGE_SIGNING_KEYS = "0x75abc64490e17b40ea1e66691c3eb493647b24430b358bd87ec3e5127f1621ee"


@pytest.fixture(scope="module")
def contract() -> interface.SimpleDVT:
return interface.SimpleDVT(SIMPLE_DVT)


def test_links(contract):
assert contract.getLocator() == contracts.lido_locator


def test_aragon(contract):
proxy = interface.AppProxyUpgradeable(contract)
assert proxy.implementation() == SIMPLE_DVT_IMPL
assert contract.kernel() == contracts.kernel
assert contract.appId() == SIMPLE_DVT_ARAGON_APP_ID
assert contract.hasInitialized() == True
assert contract.isPetrified() == False


def test_role_keccaks(contract):
assert contract.MANAGE_SIGNING_KEYS() == web3.keccak(text="MANAGE_SIGNING_KEYS").hex()
assert contract.SET_NODE_OPERATOR_LIMIT_ROLE() == web3.keccak(text="SET_NODE_OPERATOR_LIMIT_ROLE").hex()
assert contract.MANAGE_NODE_OPERATOR_ROLE() == web3.keccak(text="MANAGE_NODE_OPERATOR_ROLE").hex()
assert contract.STAKING_ROUTER_ROLE() == web3.keccak(text="STAKING_ROUTER_ROLE").hex()


def test_versioned(contract):
assert contract.getContractVersion() == 2


def test_initialize(contract):
with reverts("INIT_ALREADY_INITIALIZED"):
contract.initialize(
contracts.lido_locator,
SIMPLE_DVT_MODULE_TYPE,
SIMPLE_DVT_MODULE_STUCK_PENALTY_DELAY,
{"from": contracts.voting},
)


def test_finalize_upgrade(contract):
with reverts("UNEXPECTED_CONTRACT_VERSION"):
contract.finalizeUpgrade_v2(
contracts.lido_locator,
SIMPLE_DVT_MODULE_TYPE,
SIMPLE_DVT_MODULE_STUCK_PENALTY_DELAY,
{"from": contracts.voting},
)


def test_petrified():
contract = interface.SimpleDVT(SIMPLE_DVT_IMPL)
with reverts("INIT_ALREADY_INITIALIZED"):
contract.initialize(
contracts.lido_locator,
SIMPLE_DVT_MODULE_TYPE,
SIMPLE_DVT_MODULE_STUCK_PENALTY_DELAY,
{"from": contracts.voting},
)

with reverts("CONTRACT_NOT_INITIALIZED"):
contract.finalizeUpgrade_v2(
contracts.lido_locator,
SIMPLE_DVT_MODULE_TYPE,
SIMPLE_DVT_MODULE_STUCK_PENALTY_DELAY,
{"from": contracts.voting},
)


def test_simple_dvt_state(contract):
node_operators_count = contract.getNodeOperatorsCount()
# assert node_operators_count == CURATED_STAKING_MODULE_OPERATORS_COUNT
# assert contract.getActiveNodeOperatorsCount() == CURATED_STAKING_MODULE_OPERATORS_ACTIVE_COUNT
assert contract.getNonce() >= 0
assert contract.getStuckPenaltyDelay() == SIMPLE_DVT_MODULE_STUCK_PENALTY_DELAY
assert contract.getType() == _str_to_bytes32("curated-onchain-v1")

summary = contract.getStakingModuleSummary()
assert summary["totalExitedValidators"] >= 0
assert summary["totalDepositedValidators"] >= 0
assert summary["depositableValidatorsCount"] > 0

deactivated_node_operators = [] # reserved for future use
exited_node_operators = [] # reserved for future use

for id in range(node_operators_count):
node_operator = contract.getNodeOperator(id, True)

assert node_operator["active"] == (id not in deactivated_node_operators)
assert node_operator["name"] is not None
assert node_operator["name"] != ""
assert node_operator["rewardAddress"] != ZERO_ADDRESS

# Invariant check
# https://github.com/lidofinance/lido-dao/blob/cadffa46a2b8ed6cfa1127fca2468bae1a82d6bf/contracts/0.4.24/nos/NodeOperatorsRegistry.sol#L168
assert node_operator["totalExitedValidators"] >= 0
assert node_operator["totalExitedValidators"] <= node_operator["totalDepositedValidators"]
assert node_operator["totalDepositedValidators"] <= node_operator["totalVettedValidators"]
assert node_operator["totalVettedValidators"] <= node_operator["totalAddedValidators"]

node_operator_summary = contract.getNodeOperatorSummary(id)
if id in exited_node_operators:
assert (
node_operator_summary["isTargetLimitActive"] is True
), f"isTargetLimitActive is inactive for node {id}"
else:
assert node_operator_summary["isTargetLimitActive"] is False, f"isTargetLimitActive is active for node {id}"
assert node_operator_summary["targetValidatorsCount"] == 0
# Can be more than 0 in regular protocol operations
# assert node_operator_summary["stuckValidatorsCount"] == 0
assert node_operator_summary["refundedValidatorsCount"] == 0
# Can be more than 0 in regular protocol operations
# assert node_operator_summary["stuckPenaltyEndTimestamp"] == 0

# Invariant check
# https://github.com/lidofinance/lido-dao/blob/cadffa46a2b8ed6cfa1127fca2468bae1a82d6bf/contracts/0.4.24/nos/NodeOperatorsRegistry.sol#L168
assert node_operator_summary["totalExitedValidators"] >= 0
assert node_operator_summary["totalExitedValidators"] <= node_operator_summary["totalDepositedValidators"]

assert node_operator_summary["depositableValidatorsCount"] is not None

assert node_operator["totalExitedValidators"] == node_operator_summary["totalExitedValidators"]
assert node_operator["totalDepositedValidators"] == node_operator_summary["totalDepositedValidators"]

no_depositable_validators_count = (
node_operator["totalVettedValidators"] - node_operator["totalDepositedValidators"]
)

assert node_operator_summary["depositableValidatorsCount"] == no_depositable_validators_count


def test_simple_dvt_easytrack(contract):

easy_track = contracts.easy_track

assert contract.canPerform(EASYTRACK_EVMSCRIPT_EXECUTOR, STAKING_ROUTER_ROLE, [])
assert contract.canPerform(EASYTRACK_EVMSCRIPT_EXECUTOR, MANAGE_NODE_OPERATOR_ROLE, [])
assert contract.canPerform(EASYTRACK_EVMSCRIPT_EXECUTOR, SET_NODE_OPERATOR_LIMIT_ROLE, [])
assert contracts.acl.getPermissionManager(contract.address, MANAGE_SIGNING_KEYS) == EASYTRACK_EVMSCRIPT_EXECUTOR
assert contract.canPerform(EASYTRACK_EVMSCRIPT_EXECUTOR, MANAGE_SIGNING_KEYS, [])

add_node_operators_evm_script_factory = EASYTRACK_SIMPLE_DVT_ADD_NODE_OPERATORS_FACTORY
activate_node_operators_evm_script_factory = EASYTRACK_SIMPLE_DVT_ACTIVATE_NODE_OPERATORS_FACTORY
deactivate_node_operators_evm_script_factory = EASYTRACK_SIMPLE_DVT_DEACTIVATE_NODE_OPERATORS_FACTORY
set_vetted_validators_limits_evm_script_factory = EASYTRACK_SIMPLE_DVT_SET_VETTED_VALIDATORS_LIMITS_FACTORY
set_node_operator_names_evm_script_factory = EASYTRACK_SIMPLE_DVT_SET_NODE_OPERATOR_NAMES_FACTORY
set_node_operator_reward_addresses_evm_script_factory = (
EASYTRACK_SIMPLE_DVT_SET_NODE_OPERATOR_REWARD_ADDRESSES_FACTORY
)
update_target_validator_limits_evm_script_factory = EASYTRACK_SIMPLE_DVT_UPDATE_TARGET_VALIDATOR_LIMITS_FACTORY
change_node_operator_managers_evm_script_factory = EASYTRACK_SIMPLE_DVT_CHANGE_NODE_OPERATOR_MANAGERS_FACTORY

evm_script_factories = easy_track.getEVMScriptFactories()

assert add_node_operators_evm_script_factory in evm_script_factories
assert activate_node_operators_evm_script_factory in evm_script_factories
assert deactivate_node_operators_evm_script_factory in evm_script_factories
assert set_vetted_validators_limits_evm_script_factory in evm_script_factories
assert update_target_validator_limits_evm_script_factory in evm_script_factories
assert set_node_operator_names_evm_script_factory in evm_script_factories
assert set_node_operator_reward_addresses_evm_script_factory in evm_script_factories
assert change_node_operator_managers_evm_script_factory in evm_script_factories

assert interface.AddNodeOperators(add_node_operators_evm_script_factory).nodeOperatorsRegistry() == contract
assert (
interface.AddNodeOperators(add_node_operators_evm_script_factory).trustedCaller()
== EASYTRACK_SIMPLE_DVT_TRUSTED_CALLER
)
assert (
interface.ActivateNodeOperators(activate_node_operators_evm_script_factory).nodeOperatorsRegistry() == contract
)
assert (
interface.ActivateNodeOperators(activate_node_operators_evm_script_factory).trustedCaller()
== EASYTRACK_SIMPLE_DVT_TRUSTED_CALLER
)
assert (
interface.DeactivateNodeOperators(deactivate_node_operators_evm_script_factory).nodeOperatorsRegistry()
== contract
)
assert (
interface.DeactivateNodeOperators(deactivate_node_operators_evm_script_factory).trustedCaller()
== EASYTRACK_SIMPLE_DVT_TRUSTED_CALLER
)
assert (
interface.SetVettedValidatorsLimits(set_vetted_validators_limits_evm_script_factory).nodeOperatorsRegistry()
== contract
)
assert (
interface.SetVettedValidatorsLimits(set_vetted_validators_limits_evm_script_factory).trustedCaller()
== EASYTRACK_SIMPLE_DVT_TRUSTED_CALLER
)
assert (
interface.SetNodeOperatorNames(set_node_operator_names_evm_script_factory).nodeOperatorsRegistry() == contract
)
assert (
interface.SetNodeOperatorNames(set_node_operator_names_evm_script_factory).trustedCaller()
== EASYTRACK_SIMPLE_DVT_TRUSTED_CALLER
)
assert (
interface.SetNodeOperatorRewardAddresses(
set_node_operator_reward_addresses_evm_script_factory
).nodeOperatorsRegistry()
== contract
)
assert (
interface.SetNodeOperatorRewardAddresses(set_node_operator_reward_addresses_evm_script_factory).trustedCaller()
== EASYTRACK_SIMPLE_DVT_TRUSTED_CALLER
)
assert (
interface.UpdateTargetValidatorLimits(update_target_validator_limits_evm_script_factory).nodeOperatorsRegistry()
== contract
)
assert (
interface.UpdateTargetValidatorLimits(update_target_validator_limits_evm_script_factory).trustedCaller()
== EASYTRACK_SIMPLE_DVT_TRUSTED_CALLER
)
assert (
interface.ChangeNodeOperatorManagers(change_node_operator_managers_evm_script_factory).nodeOperatorsRegistry()
== contract
)
assert (
interface.ChangeNodeOperatorManagers(change_node_operator_managers_evm_script_factory).trustedCaller()
== EASYTRACK_SIMPLE_DVT_TRUSTED_CALLER
)


def _str_to_bytes32(s: str) -> str:
return "0x{:0<64}".format(s.encode("utf-8").hex())
7 changes: 3 additions & 4 deletions tests/acceptance/test_staking_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,9 @@ def test_staking_modules(contract):
assert simple_dvt_module["targetShare"] == SIMPLE_DVT_MODULE_TARGET_SHARE_BP
assert simple_dvt_module["status"] == 0
assert simple_dvt_module["name"] == SIMPLE_DVT_MODULE_NAME
# TODO: fix values after adding new keys
# assert simple_dvt_module["lastDepositAt"] >= 0
# assert simple_dvt_module["lastDepositBlock"] >= 0
# assert simple_dvt_module["exitedValidatorsCount"] >= 0
assert simple_dvt_module["lastDepositAt"] > 0
assert simple_dvt_module["lastDepositBlock"] > 0
assert simple_dvt_module["exitedValidatorsCount"] >= 0

fee_aggregate_distribution = contract.getStakingFeeAggregateDistribution()
assert fee_aggregate_distribution["modulesFee"] == SR_MODULES_FEE_E20
Expand Down

0 comments on commit d0d9847

Please sign in to comment.