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
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()
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
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
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
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) }