Example #1
0
    def create_safe(self,
                    owners: List[Account],
                    threshold: int = 2,
                    payment_token: Optional[None] = None,
                    create2: bool = True):
        if create2:
            creation_url = urljoin(self.base_url, reverse('v2:safe-creation'))
            data = {
                'saltNonce': generate_valid_s(),
                'owners': owners,
                'threshold': threshold,
            }
            if payment_token:
                data['paymentToken'] = payment_token
        else:
            creation_url = urljoin(self.base_url, reverse('v1:safe-creation'))
            data = {
                's': generate_valid_s(),
                'owners': owners,
                'threshold': threshold,
            }
            if payment_token:
                data['paymentToken'] = payment_token
        r = requests.post(creation_url, json=data)
        assert r.ok, "Error creating safe %s" % r.content

        safe_address, payment = r.json()['safe'], int(r.json()['payment'])
        return safe_address, payment
Example #2
0
    def test_safe_creation_with_fixed_cost(self):
        s = generate_valid_s()
        owner1, _ = get_eth_address_with_key()
        owner2, _ = get_eth_address_with_key()
        serializer = SafeCreationSerializer(data={
            's': s,
            'owners': [owner1, owner2],
            'threshold': 2
        })
        self.assertTrue(serializer.is_valid())
        fixed_creation_cost = 123
        with self.settings(SAFE_FIXED_CREATION_COST=fixed_creation_cost):
            SafeCreationServiceProvider.del_singleton()
            response = self.client.post(reverse('v1:safe-creation'),
                                        data=serializer.data,
                                        format='json')
            response_json = response.json()
            self.assertEqual(response.status_code, status.HTTP_201_CREATED)
            deployer = response_json['deployer']
            self.assertTrue(check_checksum(deployer))
            self.assertTrue(check_checksum(response_json['safe']))
            self.assertTrue(check_checksum(response_json['funder']))
            self.assertEqual(response_json['paymentToken'], NULL_ADDRESS)
            self.assertEqual(int(response_json['payment']),
                             fixed_creation_cost)

            safe_creation = SafeCreation.objects.get(deployer=deployer)
            self.assertEqual(safe_creation.payment_token, None)
            self.assertEqual(safe_creation.payment, fixed_creation_cost)
            self.assertGreater(safe_creation.wei_deploy_cost(),
                               safe_creation.payment)
            SafeCreationServiceProvider.del_singleton()
Example #3
0
    def create_safe(
        self,
        owners: List[Account],
        threshold: int = 2,
        payment_token: Optional[None] = None,
        v2: bool = False,
    ):
        if v2:
            creation_url = urljoin(self.base_url, reverse("v2:safe-creation"))
        else:
            creation_url = urljoin(self.base_url, reverse("v3:safe-creation"))
        data = {
            "saltNonce": generate_valid_s(),
            "owners": owners,
            "threshold": threshold,
        }
        if payment_token:
            data["paymentToken"] = payment_token
        self.stdout.write(
            self.style.SUCCESS(f"Calling creation url {creation_url}"))
        r = requests.post(creation_url, json=data)
        assert r.ok, f"Error creating safe {r.content} using url={creation_url}"

        safe_address, payment = r.json()["safe"], int(r.json()["payment"])
        return safe_address, payment
Example #4
0
    def create_test_safe_in_db(self,
                               owners=None,
                               number_owners=3,
                               threshold=None,
                               payment_token=None) -> SafeCreation:
        s = generate_valid_s()
        owners = owners or [
            Account.create().address for _ in range(number_owners)
        ]
        threshold = threshold if threshold else len(owners)

        safe_creation = self.safe_creation_service.create_safe_tx(
            s, owners, threshold, payment_token)
        return safe_creation
Example #5
0
    def test_safe_creation(self):
        s = generate_valid_s()
        owner1, _ = get_eth_address_with_key()
        owner2, _ = get_eth_address_with_key()
        serializer = SafeCreationSerializer(data={
            's': s,
            'owners': [owner1, owner2],
            'threshold': 2
        })
        self.assertTrue(serializer.is_valid())
        response = self.client.post(reverse('v1:safe-creation'),
                                    data=serializer.data,
                                    format='json')
        response_json = response.json()
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        deployer = response_json['deployer']
        self.assertTrue(check_checksum(deployer))
        self.assertTrue(check_checksum(response_json['safe']))
        self.assertTrue(check_checksum(response_json['funder']))
        self.assertEqual(response_json['paymentToken'], NULL_ADDRESS)
        self.assertGreater(int(response_json['payment']), 0)

        self.assertTrue(
            SafeContract.objects.filter(address=response.data['safe']))
        self.assertTrue(SafeCreation.objects.filter(owners__contains=[owner1]))
        safe_creation = SafeCreation.objects.get(deployer=deployer)
        self.assertEqual(safe_creation.payment_token, None)
        # Payment includes deployment gas + gas to send eth to the deployer
        self.assertGreater(safe_creation.payment,
                           safe_creation.wei_deploy_cost())

        serializer = SafeCreationSerializer(data={
            's': -1,
            'owners': [owner1, owner2],
            'threshold': 2
        })
        self.assertFalse(serializer.is_valid())
        response = self.client.post(reverse('v1:safe-creation'),
                                    data=serializer.data,
                                    format='json')
        self.assertEqual(response.status_code,
                         status.HTTP_422_UNPROCESSABLE_ENTITY)
    def create_safe(self,
                    owners: List[Account],
                    threshold: int = 2,
                    payment_token: Optional[None] = None,
                    v2: bool = False):
        if v2:
            creation_url = urljoin(self.base_url, reverse('v2:safe-creation'))
        else:
            creation_url = urljoin(self.base_url, reverse('v3:safe-creation'))
        data = {
            'saltNonce': generate_valid_s(),
            'owners': owners,
            'threshold': threshold,
        }
        if payment_token:
            data['paymentToken'] = payment_token
        self.stdout.write(
            self.style.SUCCESS(f'Calling creation url {creation_url}'))
        r = requests.post(creation_url, json=data)
        assert r.ok, f"Error creating safe {r.content} using url={creation_url}"

        safe_address, payment = r.json()['safe'], int(r.json()['payment'])
        return safe_address, payment
Example #7
0
    def test_safe_creation_with_payment_token(self):
        s = generate_valid_s()
        owner1, _ = get_eth_address_with_key()
        owner2, _ = get_eth_address_with_key()
        payment_token, _ = get_eth_address_with_key()
        serializer = SafeCreationSerializer(
            data={
                's': s,
                'owners': [owner1, owner2],
                'threshold': 2,
                'payment_token': payment_token,
            })
        self.assertTrue(serializer.is_valid())
        response = self.client.post(reverse('v1:safe-creation'),
                                    data=serializer.data,
                                    format='json')
        self.assertEqual(response.status_code,
                         status.HTTP_422_UNPROCESSABLE_ENTITY)
        response_json = response.json()
        self.assertIn('InvalidPaymentToken', response_json['exception'])
        self.assertIn(payment_token, response_json['exception'])

        # With previous versions of ganache it failed, because token was on DB but not in blockchain,
        # so gas cannot be estimated. With new versions of ganache estimation is working
        token_model = TokenFactory(address=payment_token,
                                   fixed_eth_conversion=0.1)
        response = self.client.post(reverse('v1:safe-creation'),
                                    data=serializer.data,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        erc20_contract = self.deploy_example_erc20(10000, NULL_ADDRESS)
        payment_token = erc20_contract.address
        serializer = SafeCreationSerializer(
            data={
                's': s,
                'owners': [owner1, owner2],
                'threshold': 2,
                'payment_token': payment_token,
            })
        self.assertTrue(serializer.is_valid())
        token_model = TokenFactory(address=payment_token,
                                   fixed_eth_conversion=0.1)
        response = self.client.post(reverse('v1:safe-creation'),
                                    data=serializer.data,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)

        response_json = response.json()
        deployer = response_json['deployer']
        self.assertTrue(check_checksum(deployer))
        self.assertTrue(check_checksum(response_json['safe']))
        self.assertEqual(response_json['paymentToken'], payment_token)

        self.assertTrue(
            SafeContract.objects.filter(address=response.data['safe']))
        safe_creation = SafeCreation.objects.get(deployer=deployer)
        self.assertIn(owner1, safe_creation.owners)
        self.assertEqual(safe_creation.payment_token, payment_token)
        self.assertGreater(safe_creation.payment,
                           safe_creation.wei_deploy_cost())

        # Check that payment is more than with ether
        token_payment = response_json['payment']
        serializer = SafeCreationSerializer(data={
            's': s,
            'owners': [owner1, owner2],
            'threshold': 2,
        })
        self.assertTrue(serializer.is_valid())
        response = self.client.post(reverse('v1:safe-creation'),
                                    data=serializer.data,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        response_json = response.json()
        payment_using_ether = response_json['payment']
        self.assertGreater(token_payment, payment_using_ether)

        # Check that token with fixed conversion price to 1 is a little higher than with ether
        # (We need to pay for storage for token transfer, as funder does not own any token yet)
        erc20_contract = self.deploy_example_erc20(10000, NULL_ADDRESS)
        payment_token = erc20_contract.address
        token_model = TokenFactory(address=payment_token,
                                   fixed_eth_conversion=1)
        serializer = SafeCreationSerializer(
            data={
                's': s,
                'owners': [owner1, owner2],
                'threshold': 2,
                'payment_token': payment_token
            })
        self.assertTrue(serializer.is_valid())
        response = self.client.post(reverse('v1:safe-creation'),
                                    data=serializer.data,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        response_json = response.json()
        deployer = response_json['deployer']
        payment_using_token = response_json['payment']
        self.assertGreater(payment_using_token, payment_using_ether)
        safe_creation = SafeCreation.objects.get(deployer=deployer)
        # Payment includes also the gas to send ether to the safe deployer
        self.assertGreater(safe_creation.payment,
                           safe_creation.wei_deploy_cost())
def generate_payload(owners, threshold=None):
    return {
        "owners": owners,
        "s": generate_valid_s(),
        "threshold": threshold if threshold else len(owners)
    }