Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor delegate endpoint signatures to use EIP712 #2001

Merged
merged 9 commits into from
Apr 24, 2024

Conversation

falvaradorodriguez
Copy link
Contributor

@falvaradorodriguez falvaradorodriguez commented Apr 19, 2024

Closes #1989

Points of interest:

  • Added endpoints in v2 to manage delegates. The delete and add endpoint has an optional "safe" field to manage the case of adding/deleting delegates for a safe (previously there were two delete endpoints).

  • A valid signature can be obtained with the following python script:

import environ

from eth_account import Account
from gnosis.eth.eip712 import eip712_encode_hash
from gnosis.eth import EthereumClient

env = environ.Env()

ethereum_client = EthereumClient(env.str("RPC_URL"))
account_a = Account.from_key(env.str("ACCOUNT_A_PRIVATE_KEY"))
account_b = Account.from_key(env.str("ACCOUNT_B_PRIVATE_KEY"))

types = {'EIP712Domain': [{'name': 'name', 'type': 'string'},
                          {'name': 'version', 'type': 'string'},
                          {'name': 'chainId', 'type': 'uint256'}],
         'Delegate': [{"name": "delegateAddress", "type": "bytes32"},
                      {"name": "totp", "type": "uint256"}]}

message = {"delegateAddress": account_b.address,
           "totp": get_totp()}

payload = {'types': types,
           'primaryType': 'Delegate',
           'domain': {"name": "Safe Transaction Service",
                      "version": "1.0",
                      "chainId": ethereum_client.get_chain_id()},
           'message': message}

eip712_hash = eip712_encode_hash(payload)
signature = account_a.signHash(eip712_hash)

@falvaradorodriguez falvaradorodriguez marked this pull request as ready for review April 19, 2024 11:19
@falvaradorodriguez falvaradorodriguez requested a review from a team as a code owner April 19, 2024 11:19
"""
Deprecated in favour of DelegateDeleteSerializer
Deprecated in favour of DelegateDeleteDeprecatedSerializer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Deprecated in favour of DelegateDeleteDeprecatedSerializer
Deprecated in favour of DelegateDeleteSerializer

I can understand the mistake, in my opinion would be better indicate that the serializer is a V2 version of the serializer, same that we are doing with the endpoint.
I mean, new Serializer DelegateDeleteSerializerV2 previous serializer DelegateDeleteSerializerV1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finally I have added the deprecated documentation tag and added V2 to the new classes.

):
return attrs
raise ValidationError("Only EOA and ETH_SIGN signatures are supported")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn´t find this restriction in the previous version of serializer. Is this new restriction expected?
If for example there is a Safe which one owner is other Safe, and this Safe delegated using contract signature EIPT1271 with the previous version wouldn´t be able to remove the delegate with the new version of the endpoint?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we didn't have the limit before, we shouldn't enforce now, good catch @moisses89

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed and updated! 👍

safe_address = Account.create().address
delegate = Account.create()
delegator = Account.create()
label = "Saul Goodman"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😄

# Create delegate
self.assertEqual(SafeContractDelegate.objects.count(), 0)
chain_id = self.ethereum_client.get_chain_id()
hash_to_sign = DelegateSignatureHelperV2.calculate_hash(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case we are using to calculate the hash the same function that is used to validate.
If there is an error in the way that the hash is calculated the test will pass without detect it.
My suggestion would be use the same safe_address, totp and delegate info to hardcode the expected hash or add a unit test of helper hash caclulation .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a unit test. Agree that it is better :)

self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(SafeContractDelegate.objects.count(), 2)

# Test not internal server error on contract signature
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What means this test? that we don't return a 500 for a specific case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have just updated the commentary to avoid confusion.

response = self.client.get(url, format="json")
self.assertEqual(response.data[0], "At least one query param must be provided")
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you include a test for not found delegate address?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

Copy link
Member

@moisses89 moisses89 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some minor comments

delegate_address = "0x1234567890123456789012345678901234567890"
chain_id = 1

expected_hash_previous_false = HexBytes(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It takes some time to me to understand what means the false, previous_false did me to think that was a previous wrong hash.
I think that could help add a comment to this line as # Hash calculated when totp previous is false the same for the previous true.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

@@ -982,9 +970,10 @@ class AllTransactionsSchemaSerializer(serializers.Serializer):
# Deprecated ---------------------------------------------------------------


class SafeDelegateDeleteSerializer(serializers.Serializer):
class SafeDelegateDeleteDeprecatedSerializer(serializers.Serializer):
Copy link
Member

@moisses89 moisses89 Apr 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other deprecated classes were keeping the class name but with a comment that the class is deprecated, are you aware that this class is renamed including the Deprecated tag?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the name, it had been forgotten. As for the reasons, it was in this PR, but I don't know why.

@falvaradorodriguez falvaradorodriguez merged commit 0b7acde into main Apr 24, 2024
5 checks passed
@falvaradorodriguez falvaradorodriguez deleted the refactor-delegate-endpoint-use-eip712 branch April 24, 2024 08:19
@github-actions github-actions bot locked and limited conversation to collaborators Apr 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Refactor delegate endpoint signatures to use EIP712
3 participants