Skip to content

Commit

Permalink
Fix wrong domain separator for contract version 1.1.1 (#422)
Browse files Browse the repository at this point in the history
Add domainSeparator calculation for contract version 1.1.1
Add test eip1271 signing for v1.1.1
  • Loading branch information
moisses89 authored Jan 12, 2023
1 parent 478a38a commit c000120
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 12 deletions.
4 changes: 4 additions & 0 deletions gnosis/safe/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ class CannotRetrieveSafeInfoException(SafeServiceException):
pass


class InvalidSafeVersion(SafeServiceException):
pass


class InvalidChecksumAddress(SafeServiceException):
pass

Expand Down
41 changes: 31 additions & 10 deletions gnosis/safe/safe.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
CannotEstimateGas,
CannotRetrieveSafeInfoException,
InvalidPaymentToken,
InvalidSafeVersion,
)
from .safe_create2_tx import SafeCreate2Tx, SafeCreate2TxBuilder
from .safe_creation_tx import InvalidERC20Token, SafeCreationTx
Expand Down Expand Up @@ -88,9 +89,13 @@ class Safe:
0x4A204F620C8C5CCDCA3FD54D003BADD85BA500436A431F0CBDA4F558C93C34C8
)
# keccak256("EIP712Domain(uint256 chainId,address verifyingContract)");
DOMAIN_TYPEHASH = bytes.fromhex(
DOMAIN_TYPEHASH_V1_3_0 = bytes.fromhex(
"47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218"
)
# keccak256("EIP712Domain(address verifyingContract)")
DOMAIN_TYPEHASH_V1_1_1 = bytes.fromhex(
"035aff83d86937d35b32e04f0ddc6ff469290eef2f1b692d8a815c89404d4749"
)
# keccak256("SafeMessage(bytes message)");
SAFE_MESSAGE_TYPEHASH = bytes.fromhex(
"60b3cbf8b4a223d68d641b3b6ddf9a298e7f33710cf3d3a9d1146b5a6150fbca"
Expand Down Expand Up @@ -519,16 +524,32 @@ def contract(self) -> Contract:

@cached_property
def domain_separator(self):
return fast_keccak(
encode_abi(
["bytes32", "uint256", "address"],
[
self.DOMAIN_TYPEHASH,
self.ethereum_client.get_chain_id(),
self.address,
],
version = self.retrieve_version()
if version == "1.3.0":
return fast_keccak(
encode_abi(
["bytes32", "uint256", "address"],
[
self.DOMAIN_TYPEHASH_V1_3_0,
self.ethereum_client.get_chain_id(),
self.address,
],
)
)
elif version == "1.1.1":
return fast_keccak(
encode_abi(
["bytes32", "address"],
[
self.DOMAIN_TYPEHASH_V1_1_1,
self.address,
],
)
)
else:
raise InvalidSafeVersion(
f"Cannot get domain separator for version {version}"
)
)

def check_funds_for_tx_gas(
self, safe_tx_gas: int, base_gas: int, gas_price: int, gas_token: str
Expand Down
33 changes: 31 additions & 2 deletions gnosis/safe/tests/test_signatures.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@


class TestSafeSignature(SafeTestCaseMixin, TestCase):
EIP1271_MAGIC_VALUE = "20c13b0b"
EIP1271_MAGIC_VALUE_UPDATED = "1626ba7e"

def test_get_signing_address(self):
account = Account.create()
# Random hash
Expand Down Expand Up @@ -52,7 +55,7 @@ def test_eip1271_signing(self):
)
self.assertEqual(
is_valid_bytes_fn(message.encode(), signature.signature).call(),
bytes.fromhex("20c13b0b"),
bytes.fromhex(self.EIP1271_MAGIC_VALUE),
)

# Use new isValidSignature method (receives bytes32 == hash of the message)
Expand All @@ -70,5 +73,31 @@ def test_eip1271_signing(self):
)
self.assertEqual(
is_valid_bytes_fn(message_hash, signature.signature).call(),
bytes.fromhex("1626ba7e"),
bytes.fromhex(self.EIP1271_MAGIC_VALUE_UPDATED),
)

def test_eip1271_signing_v1_1_1_contract(self):
owner = Account.create()
message = "luar_na_lubre"
safe = self.deploy_test_safe_v1_1_1(threshold=1, owners=[owner.address])

self.assertEqual(
safe.contract.functions.domainSeparator().call(), safe.domain_separator
)

contract = safe.contract
safe_message_hash = safe.get_message_hash(message)
self.assertEqual(
contract.functions.getMessageHash(message.encode()).call(),
safe_message_hash,
)

# Use isValidSignature method (receives bytes)
signature = owner.signHash(safe_message_hash)

self.assertEqual(
contract.functions.isValidSignature(
message.encode(), signature.signature
).call(),
bytes.fromhex(self.EIP1271_MAGIC_VALUE),
)

0 comments on commit c000120

Please sign in to comment.