diff --git a/safe_relay_service/relay/services/safe_creation_service.py b/safe_relay_service/relay/services/safe_creation_service.py index 4d34ffb2..885689dc 100644 --- a/safe_relay_service/relay/services/safe_creation_service.py +++ b/safe_relay_service/relay/services/safe_creation_service.py @@ -153,6 +153,25 @@ def _check_safe_balance(self, safe_creation2: SafeCreation2) -> NoReturn: logger.info('Found %d balance for safe=%s with payment-token=%s. Required=%d', safe_balance, safe_address, safe_creation2.payment_token, safe_creation2.payment) + def existing_predicted_address(self, salt_nonce: int, owners: Iterable[str]) -> str: + """ + Return a previously predicted Safe address. + Note that the prediction parameters are not updated for the SafeCreation2 object + :param salt_nonce: Random value for solidity `create2` salt + :param owners: Owners of the new Safe + :rtype: str + """ + try: + # The salt_nonce is deterministicly generated from the owner address + safe_creation = SafeCreation2.objects.filter(owners__contains=owners, salt_nonce=salt_nonce).order_by('created').first() + if not safe_creation: + return NULL_ADDRESS + logger.info('The relayer had already predicted an address for this owner. Safe addr: %s, owner: %s', safe_creation.safe_id, owners) + return safe_creation.safe_id + except SafeCreation2.DoesNotExist: + return NULL_ADDRESS + + def predict_address(self, salt_nonce: int, owners: Iterable[str], threshold: int, payment_token: Optional[str]) -> str: """ diff --git a/safe_relay_service/relay/views_v3.py b/safe_relay_service/relay/views_v3.py index 680ce4bb..c5b33a11 100644 --- a/safe_relay_service/relay/views_v3.py +++ b/safe_relay_service/relay/views_v3.py @@ -50,7 +50,8 @@ class SafeAddressPredictionView(CreateAPIView): 422: 'Cannot process data'}) def post(self, request, *args, **kwargs): """ - Predicts the safe address + Predicts the safe address. If the relayer already predicted an address for that owner, it doesn't do the prediction again. + Note that the prediction parameters are not updated for the SafeCreation2 object """ serializer = self.serializer_class(data=request.data) if serializer.is_valid(): @@ -59,7 +60,9 @@ def post(self, request, *args, **kwargs): serializer.data['payment_token']) safe_creation_service = SafeCreationServiceProvider() - safe_prediction = safe_creation_service.predict_address(salt_nonce, owners, threshold, payment_token) + safe_prediction = safe_creation_service.existing_predicted_address(salt_nonce, owners) + if safe_prediction == NULL_ADDRESS: + safe_prediction = safe_creation_service.predict_address(salt_nonce, owners, threshold, payment_token) safe_prediction_response_data = SafeAddressPredictionResponseSerializer(data={ 'safe': safe_prediction, })