diff --git a/gnosis/safe/signatures.py b/gnosis/safe/signatures.py index a927c7395..c0a22d816 100644 --- a/gnosis/safe/signatures.py +++ b/gnosis/safe/signatures.py @@ -1,8 +1,11 @@ from typing import List, Tuple, Union from eth_keys import keys +from eth_keys.exceptions import BadSignature from hexbytes import HexBytes +from gnosis.eth.constants import NULL_ADDRESS + def signature_split( signatures: Union[bytes, str], pos: int = 0 @@ -53,7 +56,10 @@ def signatures_to_bytes(signatures: List[Tuple[int, int, int]]) -> bytes: def get_signing_address(signed_hash: Union[bytes, str], v: int, r: int, s: int) -> str: """ :return: checksummed ethereum address, for example `0x568c93675A8dEb121700A6FAdDdfE7DFAb66Ae4A` - :rtype: str + :rtype: str or `NULL_ADDRESS` if signature is not valid """ - public_key = keys.ecdsa_recover(signed_hash, keys.Signature(vrs=(v - 27, r, s))) - return public_key.to_checksum_address() + try: + public_key = keys.ecdsa_recover(signed_hash, keys.Signature(vrs=(v - 27, r, s))) + return public_key.to_checksum_address() + except BadSignature: + return NULL_ADDRESS diff --git a/gnosis/safe/tests/test_signatures.py b/gnosis/safe/tests/test_signatures.py new file mode 100644 index 000000000..5aa98b248 --- /dev/null +++ b/gnosis/safe/tests/test_signatures.py @@ -0,0 +1,26 @@ +from django.test import TestCase + +from eth_account import Account +from web3 import Web3 + +from gnosis.eth.constants import NULL_ADDRESS + +from ..signatures import get_signing_address + + +class TestSafeSignature(TestCase): + def test_get_signing_address(self): + account = Account.create() + # Random hash + random_hash = Web3.keccak(text="tanxugueiras") + signature = account.signHash(random_hash) + self.assertEqual( + get_signing_address(random_hash, signature.v, signature.r, signature.s), + account.address, + ) + + # Invalid signature will return the `NULL_ADDRESS` + self.assertEqual( + get_signing_address(random_hash, signature.v - 8, signature.r, signature.s), + NULL_ADDRESS, + )