Skip to content

Commit 8c2e3c3

Browse files
feat(orc-483): add unit tests on DelegationModule
1 parent c476b6b commit 8c2e3c3

File tree

2 files changed

+75
-111
lines changed

2 files changed

+75
-111
lines changed

src/web3py/extensions/delegation.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,17 @@
1313
logger = logging.getLogger(__name__)
1414

1515

16-
class DelegationNotConfiguredError(Exception):
17-
"""Raised when delegation contract has no delegatee assigned"""
18-
pass
19-
20-
21-
class DelegateMismatchError(Exception):
22-
"""Raised when delegation contract delegatee doesn't match oracle account"""
23-
pass
24-
25-
2616
class DelegationModule(Module):
2717
w3: Web3
2818
delegation_contract: DelegationContract | None
2919
delegation_address: str | None
3020

21+
class NotConfiguredError(Exception):
22+
"""Raised when delegation contract has no delegatee assigned"""
23+
24+
class DelegateMismatchError(Exception):
25+
"""Raised when delegation contract delegatee doesn't match oracle account"""
26+
3127
def __init__(self, w3: Web3, delegation_address: str | None = None):
3228
super().__init__(w3)
3329

@@ -87,17 +83,21 @@ def _validate_delegation_setup(self) -> None:
8783
if not self.delegation_contract:
8884
return
8985

86+
if not variables.ACCOUNT:
87+
logger.warning({'msg': 'Skipping delegation validation - ACCOUNT is not set'})
88+
return
89+
9090
current_delegatee = self.delegation_contract.get_delegatee()
9191
oracle_address = cast(ChecksumAddress, variables.ACCOUNT.address)
9292

9393
if current_delegatee == '0x0000000000000000000000000000000000000000':
94-
raise DelegationNotConfiguredError(
94+
raise DelegationModule.NotConfiguredError(
9595
f"Delegation contract has no delegatee assigned. "
9696
f"Admin must call assignDelegate({oracle_address})"
9797
)
9898

9999
if current_delegatee.lower() != oracle_address.lower():
100-
raise DelegateMismatchError(
100+
raise DelegationModule.DelegateMismatchError(
101101
f"Delegation contract delegatee ({current_delegatee}) "
102102
f"does not match oracle account ({oracle_address}). "
103103
f"Admin must call assignDelegate({oracle_address})"
Lines changed: 63 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,69 @@
1+
from unittest.mock import MagicMock, Mock
2+
13
import pytest
24

35
from src import variables
6+
from src.web3py.extensions.delegation import DelegationModule
7+
48

9+
DUMMY_ADDRESS = '0x' + '12' * 20
10+
ORACLE_ADDRESS = '0x' + 'ab' * 20
11+
ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
512

6-
@pytest.mark.testnet
7-
@pytest.mark.integration
13+
14+
@pytest.mark.unit
815
class TestDelegationModule:
9-
def test_delegation_module_init__real_contract__validates_successfully(self, web3_integration, caplog):
10-
delegation_module = web3_integration.delegation
11-
12-
assert delegation_module.is_enabled() is True
13-
assert delegation_module.delegation_address == variables.DELEGATION_CONTRACT_ADDRESS
14-
assert delegation_module.delegation_contract is not None
15-
assert any('DelegationModule initialized with contract' in message for message in caplog.messages)
16-
17-
def test_delegation_module_init__real_contract__logs_validation_success(self, web3_integration, caplog):
18-
delegation_module = web3_integration.delegation
19-
20-
assert delegation_module.is_enabled()
21-
assert any('Delegation contract validation passed' in message for message in caplog.messages)
22-
23-
def test_wrap_call_for_delegation__real_contract__builds_execute_call(
24-
self, web3_integration, delegation_contract, caplog
25-
):
26-
delegation_module = web3_integration.delegation
27-
mock_target_call = delegation_contract.functions.admin()
28-
29-
wrapped_call = delegation_module.wrap_call_for_delegation(mock_target_call)
30-
31-
assert wrapped_call.address == delegation_contract.address
32-
assert wrapped_call.function_identifier == 'execute'
33-
assert any('Wrapping call for delegation' in message for message in caplog.messages)
34-
35-
def test_is_enabled__real_contract__returns_true(self, web3_integration):
36-
delegation_module = web3_integration.delegation
37-
38-
assert delegation_module.is_enabled() is True
39-
40-
def test_validation_setup__real_delegatee__has_valid_delegatee(self, web3_integration):
41-
delegation_module = web3_integration.delegation
42-
current_delegatee = delegation_module.delegation_contract.get_delegatee()
43-
44-
assert current_delegatee != '0x0000000000000000000000000000000000000000'
45-
assert delegation_module.is_enabled() is True
46-
47-
def test_delegation_module_disabled__no_address__initialization_succeeds(self, caplog, monkeypatch):
48-
from web3 import Web3
49-
50-
from src.web3py.contract_tweak import tweak_w3_contracts
51-
from src.web3py.extensions import DelegationModule, FallbackProviderModule
52-
53-
monkeypatch.setattr(variables, 'DELEGATION_CONTRACT_ADDRESS', '')
54-
55-
w3_no_delegation = Web3(
56-
FallbackProviderModule(
57-
variables.EXECUTION_CLIENT_URI,
58-
request_kwargs={'timeout': variables.HTTP_REQUEST_TIMEOUT_EXECUTION},
59-
cache_allowed_requests=True,
60-
)
61-
)
62-
tweak_w3_contracts(w3_no_delegation)
63-
w3_no_delegation.attach_modules(
64-
{
65-
'delegation': lambda: DelegationModule(w3_no_delegation, variables.DELEGATION_CONTRACT_ADDRESS),
66-
}
67-
)
68-
69-
delegation_module = w3_no_delegation.delegation
70-
71-
assert delegation_module.is_enabled() is False
72-
assert delegation_module.delegation_address == ''
73-
assert delegation_module.delegation_contract is None
74-
assert any(
75-
'DelegationModule initialized without contract - delegation disabled' in message
76-
for message in caplog.messages
77-
)
78-
79-
def test_wrap_call_for_delegation__no_contract__raises_error(self, delegation_contract, monkeypatch):
80-
from web3 import Web3
81-
82-
from src.web3py.contract_tweak import tweak_w3_contracts
83-
from src.web3py.extensions import DelegationModule, FallbackProviderModule
84-
85-
monkeypatch.setattr(variables, 'DELEGATION_CONTRACT_ADDRESS', '')
86-
87-
w3_no_delegation = Web3(
88-
FallbackProviderModule(
89-
variables.EXECUTION_CLIENT_URI,
90-
request_kwargs={'timeout': variables.HTTP_REQUEST_TIMEOUT_EXECUTION},
91-
cache_allowed_requests=True,
92-
)
93-
)
94-
tweak_w3_contracts(w3_no_delegation)
95-
w3_no_delegation.attach_modules(
96-
{
97-
'delegation': lambda: DelegationModule(w3_no_delegation, variables.DELEGATION_CONTRACT_ADDRESS),
98-
}
99-
)
100-
101-
delegation_module = w3_no_delegation.delegation
102-
mock_target_call = delegation_contract.functions.admin()
103-
104-
with pytest.raises(RuntimeError, match="Delegation is not enabled"):
105-
delegation_module.wrap_call_for_delegation(mock_target_call)
16+
@pytest.fixture
17+
def mock_w3(self):
18+
w3 = MagicMock()
19+
w3.eth.contract.return_value = Mock()
20+
w3.eth.contract.return_value.address = DUMMY_ADDRESS
21+
return w3
22+
23+
@pytest.fixture
24+
def mock_account(self):
25+
account = Mock()
26+
account.address = ORACLE_ADDRESS
27+
return account
28+
29+
def test_init__no_delegation_address__disabled(self, mock_w3, caplog):
30+
module = DelegationModule(mock_w3, delegation_address=None)
31+
32+
assert module.delegation_contract is None
33+
assert module.delegation_address is None
34+
assert module.is_enabled() is False
35+
assert 'delegation disabled' in caplog.text
36+
37+
def test_init__valid_delegation_setup__enabled(self, mock_w3, mock_account, monkeypatch, caplog):
38+
monkeypatch.setattr(variables, 'ACCOUNT', mock_account)
39+
mock_w3.eth.contract.return_value.get_delegatee.return_value = ORACLE_ADDRESS
40+
mock_w3.eth.contract.return_value.get_admin.return_value = DUMMY_ADDRESS
41+
42+
module = DelegationModule(mock_w3, delegation_address=DUMMY_ADDRESS)
43+
44+
assert module.delegation_contract is not None
45+
assert module.is_enabled() is True
46+
assert 'Delegation contract validation passed' in caplog.text
47+
48+
def test_init__no_account__skips_validation(self, mock_w3, monkeypatch, caplog):
49+
monkeypatch.setattr(variables, 'ACCOUNT', None)
50+
51+
module = DelegationModule(mock_w3, delegation_address=DUMMY_ADDRESS)
52+
53+
assert module.delegation_contract is not None
54+
assert 'Skipping delegation validation' in caplog.text
55+
56+
def test_init__delegatee_is_zero_address__raises_not_configured_error(self, mock_w3, mock_account, monkeypatch):
57+
monkeypatch.setattr(variables, 'ACCOUNT', mock_account)
58+
mock_w3.eth.contract.return_value.get_delegatee.return_value = ZERO_ADDRESS
59+
60+
with pytest.raises(DelegationModule.NotConfiguredError):
61+
DelegationModule(mock_w3, delegation_address=DUMMY_ADDRESS)
62+
63+
def test_init__delegatee_mismatch__raises_mismatch_error(self, mock_w3, mock_account, monkeypatch):
64+
monkeypatch.setattr(variables, 'ACCOUNT', mock_account)
65+
other_address = '0x' + 'cc' * 20
66+
mock_w3.eth.contract.return_value.get_delegatee.return_value = other_address
67+
68+
with pytest.raises(DelegationModule.DelegateMismatchError):
69+
DelegationModule(mock_w3, delegation_address=DUMMY_ADDRESS)

0 commit comments

Comments
 (0)