Beispiel #1
0
    def test_safe_creation_estimate(self):
        url = reverse('v2:safe-creation-estimates')
        number_owners = 4
        data = {
            'numberOwners': number_owners
        }

        response = self.client.post(url, data=data, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        safe_creation_estimates = response.json()
        self.assertEqual(len(safe_creation_estimates), 1)
        safe_creation_estimate = safe_creation_estimates[0]
        self.assertEqual(safe_creation_estimate['paymentToken'], NULL_ADDRESS)

        token = TokenFactory(gas=True, fixed_eth_conversion=None)
        response = self.client.post(url, data=data, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        safe_creation_estimates = response.json()
        # No price oracles, so no estimation
        self.assertEqual(len(safe_creation_estimates), 1)

        fixed_price_token = TokenFactory(gas=True, fixed_eth_conversion=1.0)
        response = self.client.post(url, data=data, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        safe_creation_estimates = response.json()
        # Fixed price oracle, so estimation will work
        self.assertEqual(len(safe_creation_estimates), 2)
        safe_creation_estimate = safe_creation_estimates[1]
        self.assertEqual(safe_creation_estimate['paymentToken'], fixed_price_token.address)
        self.assertGreater(int(safe_creation_estimate['payment']), 0)
        self.assertGreater(int(safe_creation_estimate['gasPrice']), 0)
        self.assertGreater(int(safe_creation_estimate['gas']), 0)
    def test_estimate_safe_creation_for_all_tokens(self):
        number_owners = 4
        safe_creation_estimates = self.safe_creation_service.estimate_safe_creation_for_all_tokens(
            number_owners)
        self.assertEqual(len(safe_creation_estimates), 1)
        safe_creation_estimate = safe_creation_estimates[0]
        self.assertEqual(safe_creation_estimate.payment_token, NULL_ADDRESS)

        token = TokenFactory(gas=True, fixed_eth_conversion=None)
        safe_creation_estimates = self.safe_creation_service.estimate_safe_creation_for_all_tokens(
            number_owners)
        # No price oracles, so no estimation
        self.assertEqual(len(safe_creation_estimates), 1)

        fixed_price_token = TokenFactory(gas=True, fixed_eth_conversion=1.0)
        safe_creation_estimates = self.safe_creation_service.estimate_safe_creation_for_all_tokens(
            number_owners)
        # Fixed price oracle, so estimation will work
        self.assertEqual(len(safe_creation_estimates), 2)
        safe_creation_estimate = safe_creation_estimates[1]
        self.assertEqual(safe_creation_estimate.payment_token,
                         fixed_price_token.address)
        self.assertGreater(safe_creation_estimate.payment, 0)
        self.assertGreater(safe_creation_estimate.gas_price, 0)
        self.assertGreater(safe_creation_estimate.gas, 0)
Beispiel #3
0
    def test_estimate_tx_for_all_tokent(self):
        safe_address = self.deploy_test_safe().safe_address
        to = Account.create().address
        value = 0
        data = b''
        operation = SafeOperation.CALL.value

        # TokenFactory(address=gas_token, gas=True)
        transaction_estimations = self.transaction_service.estimate_tx_for_all_tokens(
            safe_address, to, value, data, operation)
        self.assertEqual(transaction_estimations.last_used_nonce, None)
        self.assertGreater(transaction_estimations.safe_tx_gas, 0)
        self.assertEqual(transaction_estimations.operational_gas,
                         0)  # Operational gas must be `0` for new Safes
        self.assertEqual(len(transaction_estimations.estimations),
                         1)  # Just ether
        estimation = transaction_estimations.estimations[0]
        self.assertGreater(estimation.gas_price, 0)
        self.assertGreater(estimation.base_gas, 0)
        self.assertEqual(estimation.gas_token, NULL_ADDRESS)

        TokenFactory(address=Account.create().address,
                     gas=True,
                     fixed_eth_conversion=None)
        transaction_estimations = self.transaction_service.estimate_tx_for_all_tokens(
            safe_address, to, value, data, operation)
        self.assertEqual(len(transaction_estimations.estimations),
                         1)  # Just ether as no price was configured

        valid_token = TokenFactory(address=Account.create().address,
                                   gas=True,
                                   fixed_eth_conversion=2)
        transaction_estimations = self.transaction_service.estimate_tx_for_all_tokens(
            safe_address, to, value, data, operation)
        self.assertEqual(transaction_estimations.last_used_nonce, None)
        self.assertGreater(transaction_estimations.safe_tx_gas, 0)
        self.assertEqual(transaction_estimations.operational_gas,
                         0)  # Operational gas must be `0` for new Safes
        self.assertEqual(len(transaction_estimations.estimations),
                         2)  # Just ether
        estimation_ether = transaction_estimations.estimations[0]
        self.assertGreater(estimation_ether.gas_price, 0)
        self.assertGreater(estimation_ether.base_gas, 0)
        self.assertEqual(estimation_ether.gas_token, NULL_ADDRESS)
        estimation_token = transaction_estimations.estimations[1]
        self.assertAlmostEqual(estimation_token.gas_price,
                               estimation_ether.gas_price // 2,
                               delta=1.0)
        self.assertGreater(estimation_token.base_gas,
                           estimation_ether.base_gas)
        self.assertEqual(estimation_token.gas_token, valid_token.address)
Beispiel #4
0
    def test_estimate_tx(self):
        safe_address = Account.create().address
        to = Account.create().address
        value = 0
        data = b''
        operation = SafeOperation.CALL.value
        gas_token = Account().create().address

        with self.assertRaises(InvalidGasToken):
            self.transaction_service.estimate_tx(safe_address, to, value, data,
                                                 operation, gas_token)

        TokenFactory(address=gas_token, gas=True)
        with self.assertRaises(SafeDoesNotExist):
            self.transaction_service.estimate_tx(safe_address, to, value, data,
                                                 operation, gas_token)

        # We need a real safe deployed for this method to work
        gas_token = NULL_ADDRESS
        safe_address = self.deploy_test_safe().safe_address
        transaction_estimation = self.transaction_service.estimate_tx(
            safe_address, to, value, data, operation, gas_token)
        self.assertEqual(transaction_estimation.last_used_nonce, None)
        self.assertGreater(transaction_estimation.safe_tx_gas, 0)
        self.assertGreater(transaction_estimation.base_gas, 0)
        self.assertGreater(transaction_estimation.data_gas, 0)
        self.assertGreater(transaction_estimation.gas_price, 0)
        self.assertEqual(transaction_estimation.operational_gas, 0)
        self.assertEqual(transaction_estimation.gas_token, NULL_ADDRESS)
Beispiel #5
0
    def test_safe_creation_estimate(self):
        data = {
            'number_owners': 4,
            'payment_token': None,
        }

        response = self.client.post(reverse('v1:safe-creation-estimate'),
                                    data=data,
                                    format='json')
        response_json = response.json()
        for field in ['payment', 'gasPrice', 'gas']:
            self.assertIn(field, response_json)
            self.assertGreater(int(response_json[field]), 0)
        estimated_payment = response_json['payment']

        # With payment token
        erc20_contract = self.deploy_example_erc20(10000, NULL_ADDRESS)
        payment_token = erc20_contract.address
        token_model = TokenFactory(address=payment_token,
                                   gas=True,
                                   fixed_eth_conversion=0.1)
        data = {
            'number_owners': 4,
            'payment_token': payment_token,
        }

        response = self.client.post(reverse('v1:safe-creation-estimate'),
                                    data=data,
                                    format='json')
        response_json = response.json()
        for field in ['payment', 'gasPrice', 'gas']:
            self.assertIn(field, response_json)
            self.assertGreater(int(response_json[field]), 0)
        self.assertGreater(response_json['payment'], estimated_payment)
    def test_safe_multisig_tx_estimates(self):
        my_safe_address = get_eth_address_with_invalid_checksum()
        response = self.client.post(reverse('v1:safe-multisig-tx-estimates', args=(my_safe_address,)),
                                    data={},
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_422_UNPROCESSABLE_ENTITY)

        my_safe_address, _ = get_eth_address_with_key()
        response = self.client.post(reverse('v1:safe-multisig-tx-estimates', args=(my_safe_address,)),
                                    data={},
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

        initial_funding = self.w3.toWei(0.0001, 'ether')

        safe_creation = self.deploy_test_safe(number_owners=3, threshold=2, initial_funding_wei=initial_funding)
        my_safe_address = safe_creation.safe_address
        SafeContractFactory(address=my_safe_address)

        to = Account.create().address
        tx = {
            'to': to,
            'value': initial_funding // 2,
            'data': '0x',
            'operation': 1
        }
        response = self.client.post(reverse('v1:safe-multisig-tx-estimates', args=(my_safe_address,)),
                                    data=tx,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        response = response.json()
        self.assertGreater(int(response['safeTxGas']), 0)
        self.assertEqual(response['operationalGas'], '0')
        self.assertIsNone(response['lastUsedNonce'])
        self.assertEqual(len(response['estimations']), 1)
        estimation = response['estimations'][0]
        self.assertGreater(int(estimation['baseGas']), 0)
        self.assertGreater(int(estimation['gasPrice']), 0)
        self.assertEqual(estimation['gasToken'], NULL_ADDRESS)

        valid_token = TokenFactory(address=Account.create().address, gas=True, fixed_eth_conversion=2)
        response = self.client.post(reverse('v1:safe-multisig-tx-estimates', args=(my_safe_address,)),
                                    data=tx,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        response = response.json()
        self.assertGreater(int(response['safeTxGas']), 0)
        self.assertEqual(response['operationalGas'], '0')
        self.assertIsNone(response['lastUsedNonce'])
        self.assertEqual(len(response['estimations']), 2)
        estimation_ether = response['estimations'][0]
        self.assertGreater(int(estimation_ether['baseGas']), 0)
        self.assertGreater(int(estimation_ether['gasPrice']), 0)
        self.assertEqual(estimation_ether['gasToken'], NULL_ADDRESS)
        estimation_token = response['estimations'][1]
        self.assertGreater(int(estimation_token['baseGas']), int(estimation_ether['baseGas']))
        self.assertAlmostEqual(int(estimation_token['gasPrice']), int(estimation_ether['gasPrice']) // 2, delta=1.0)
        self.assertEqual(estimation_token['gasToken'], valid_token.address)
    def test_estimate_safe_creation2(self):
        gas_price = self.safe_creation_service._get_configured_gas_price()

        number_owners = 4
        payment_token = None
        safe_creation_estimate = self.safe_creation_service.estimate_safe_creation2(
            number_owners, payment_token)
        self.assertGreater(safe_creation_estimate.gas, 0)
        self.assertEqual(safe_creation_estimate.gas_price, gas_price)
        self.assertGreater(safe_creation_estimate.payment, 0)
        self.assertEqual(safe_creation_estimate.payment_token, NULL_ADDRESS)
        estimated_payment = safe_creation_estimate.payment

        # Compare with safe_creation
        salt_nonce = 4815162342
        owners = [Account.create().address for _ in range(number_owners)]
        threshold = 1
        safe_creation_2 = self.safe_creation_service.create2_safe_tx(
            salt_nonce, owners, threshold, payment_token=payment_token)
        self.assertAlmostEqual(safe_creation_2.gas_estimated,
                               safe_creation_estimate.gas,
                               delta=1000)
        # Compare with estimation for all tokens (position 0 is ether)
        self.assertAlmostEqual(
            self.safe_creation_service.estimate_safe_creation_for_all_tokens(
                number_owners)[0].gas,
            safe_creation_estimate.gas,
            delta=1000,
        )

        number_owners = 8
        payment_token = None
        safe_creation_estimate = self.safe_creation_service.estimate_safe_creation2(
            number_owners, payment_token)
        self.assertGreater(safe_creation_estimate.gas, 0)
        self.assertEqual(safe_creation_estimate.gas_price, gas_price)
        self.assertGreater(safe_creation_estimate.payment, estimated_payment)
        self.assertEqual(safe_creation_estimate.payment_token, NULL_ADDRESS)

        payment_token = get_eth_address_with_key()[0]
        with self.assertRaisesMessage(InvalidPaymentToken, payment_token):
            self.safe_creation_service.estimate_safe_creation2(
                number_owners, payment_token)

        number_tokens = 1000
        owner = Account.create()
        erc20 = self.deploy_example_erc20(number_tokens, owner.address)
        number_owners = 4
        payment_token = erc20.address
        payment_token_db = TokenFactory(address=payment_token,
                                        fixed_eth_conversion=0.1)
        safe_creation_estimate = self.safe_creation_service.estimate_safe_creation2(
            number_owners, payment_token)
        self.assertGreater(safe_creation_estimate.gas, 0)
        self.assertEqual(safe_creation_estimate.gas_price, gas_price)
        self.assertGreater(safe_creation_estimate.payment, estimated_payment)
        self.assertEqual(safe_creation_estimate.payment_token, payment_token)
Beispiel #8
0
    def test_safe_creation_with_payment_token(self):
        salt_nonce = generate_salt_nonce()
        owners = [Account.create().address for _ in range(2)]
        payment_token = Account.create().address
        data = {
            "saltNonce": salt_nonce,
            "owners": owners,
            "threshold": len(owners),
            "paymentToken": payment_token,
        }

        response = self.client.post(reverse("v3:safe-creation"),
                                    data=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"])

        fixed_eth_conversion = 0.1
        token_model = TokenFactory(address=payment_token,
                                   fixed_eth_conversion=fixed_eth_conversion)
        response = self.client.post(reverse("v3:safe-creation"),
                                    data,
                                    format="json")
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        response_json = response.json()
        safe_address = response_json["safe"]
        self.assertTrue(check_checksum(safe_address))
        self.assertTrue(check_checksum(response_json["paymentReceiver"]))
        self.assertEqual(response_json["paymentToken"], payment_token)
        self.assertEqual(
            int(response_json["payment"]),
            int(response_json["gasEstimated"]) *
            int(response_json["gasPriceEstimated"]) *
            (1 / fixed_eth_conversion),
        )
        self.assertGreater(int(response_json["gasEstimated"]), 0)
        self.assertGreater(int(response_json["gasPriceEstimated"]), 0)
        self.assertGreater(len(response_json["setupData"]), 2)

        self.assertTrue(SafeContract.objects.filter(address=safe_address))
        self.assertTrue(
            SafeCreation2.objects.filter(owners__contains=[owners[0]]))
        safe_creation = SafeCreation2.objects.get(safe=safe_address)
        self.assertEqual(safe_creation.payment_token, payment_token)
        # Payment includes deployment gas + gas to send eth to the deployer
        self.assertEqual(
            safe_creation.payment,
            safe_creation.wei_estimated_deploy_cost() *
            (1 / fixed_eth_conversion),
        )
    def test_estimate_safe_creation2(self):
        gas_price = self.safe_creation_service._get_configured_gas_price()

        number_owners = 4
        payment_token = None
        safe_creation_estimate = self.safe_creation_service.estimate_safe_creation2(
            number_owners, payment_token)
        self.assertGreater(safe_creation_estimate.gas, 0)
        self.assertEqual(safe_creation_estimate.gas_price, gas_price)
        self.assertGreater(safe_creation_estimate.payment, 0)
        self.assertEqual(safe_creation_estimate.payment_token, NULL_ADDRESS)
        estimated_payment = safe_creation_estimate.payment

        number_owners = 8
        payment_token = None
        safe_creation_estimate = self.safe_creation_service.estimate_safe_creation2(
            number_owners, payment_token)
        self.assertGreater(safe_creation_estimate.gas, 0)
        self.assertEqual(safe_creation_estimate.gas_price, gas_price)
        self.assertGreater(safe_creation_estimate.payment, estimated_payment)
        self.assertEqual(safe_creation_estimate.payment_token, NULL_ADDRESS)

        payment_token = get_eth_address_with_key()[0]
        with self.assertRaisesMessage(InvalidPaymentToken, payment_token):
            self.safe_creation_service.estimate_safe_creation2(
                number_owners, payment_token)

        number_tokens = 1000
        owner = Account.create()
        erc20 = self.deploy_example_erc20(number_tokens, owner.address)
        number_owners = 4
        payment_token = erc20.address
        payment_token_db = TokenFactory(address=payment_token,
                                        fixed_eth_conversion=0.1)
        safe_creation_estimate = self.safe_creation_service.estimate_safe_creation2(
            number_owners, payment_token)
        self.assertGreater(safe_creation_estimate.gas, 0)
        self.assertEqual(safe_creation_estimate.gas_price, gas_price)
        self.assertGreater(safe_creation_estimate.payment, estimated_payment)
        self.assertEqual(safe_creation_estimate.payment_token, payment_token)
    def test_safe_multisig_tx_post_gas_token(self):
        # Create Safe ------------------------------------------------
        w3 = self.ethereum_client.w3
        safe_balance = w3.toWei(0.01, 'ether')
        owner_account = self.create_account()
        owner = owner_account.address
        threshold = 1

        safe_creation = self.deploy_test_safe(owners=[owner],
                                              threshold=threshold,
                                              initial_funding_wei=safe_balance)
        my_safe_address = safe_creation.safe_address
        self.assertEqual(self.w3.eth.getBalance(my_safe_address), safe_balance)
        SafeContractFactory(address=my_safe_address)

        # Get tokens for the safe
        safe_token_balance = int(1e18)
        erc20_contract = self.deploy_example_erc20(safe_token_balance,
                                                   my_safe_address)

        # Safe prepared --------------------------------------------
        to = Account.create().address
        value = safe_balance
        tx_data = None
        operation = SafeOperation.CALL.value
        refund_receiver = None
        nonce = 0
        gas_token = erc20_contract.address

        data = {
            "to": to,
            "value": value,
            "data": tx_data,
            "operation": operation,
            "gasToken": gas_token
        }

        # Get estimation for gas. Token does not exist
        response = self.client.post(reverse('v1:safe-multisig-tx-estimate',
                                            args=(my_safe_address, )),
                                    data=data,
                                    format='json')
        self.assertEqual(response.status_code,
                         status.HTTP_422_UNPROCESSABLE_ENTITY)
        self.assertEqual('InvalidGasToken: %s' % gas_token,
                         response.json()['exception'])

        # Create token
        token_model = TokenFactory(address=gas_token)
        response = self.client.post(reverse('v1:safe-multisig-tx-estimate',
                                            args=(my_safe_address, )),
                                    data=data,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        estimation_json = response.json()

        safe_tx_gas = estimation_json['safeTxGas'] + estimation_json[
            'operationalGas']
        data_gas = estimation_json['dataGas']
        gas_price = estimation_json['gasPrice']
        gas_token = estimation_json['gasToken']

        multisig_tx_hash = SafeTx(None,
                                  my_safe_address,
                                  to,
                                  value,
                                  tx_data,
                                  operation,
                                  safe_tx_gas,
                                  data_gas,
                                  gas_price,
                                  gas_token,
                                  refund_receiver,
                                  safe_nonce=nonce).safe_tx_hash

        signatures = [
            w3.eth.account.signHash(multisig_tx_hash, private_key)
            for private_key in [owner_account.key]
        ]
        signatures_json = [{
            'v': s['v'],
            'r': s['r'],
            's': s['s']
        } for s in signatures]

        data = {
            "to": to,
            "value": value,
            "data": tx_data,
            "operation": operation,
            "safe_tx_gas": safe_tx_gas,
            "data_gas": data_gas,
            "gas_price": gas_price,
            "gas_token": gas_token,
            "nonce": nonce,
            "signatures": signatures_json
        }

        response = self.client.post(reverse('v1:safe-multisig-txs',
                                            args=(my_safe_address, )),
                                    data=data,
                                    format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        tx_hash = response.json()['transactionHash'][2:]  # Remove leading 0x
        safe_multisig_tx = SafeMultisigTx.objects.get(
            ethereum_tx__tx_hash=tx_hash)
        self.assertEqual(safe_multisig_tx.to, to)
        self.assertEqual(safe_multisig_tx.value, value)
        self.assertEqual(safe_multisig_tx.data, tx_data)
        self.assertEqual(safe_multisig_tx.operation, operation)
        self.assertEqual(safe_multisig_tx.safe_tx_gas, safe_tx_gas)
        self.assertEqual(safe_multisig_tx.data_gas, data_gas)
        self.assertEqual(safe_multisig_tx.gas_price, gas_price)
        self.assertEqual(safe_multisig_tx.gas_token, gas_token)
        self.assertEqual(safe_multisig_tx.nonce, nonce)
Beispiel #11
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())
Beispiel #12
0
    def test_safe_multisig_tx_estimates(self):
        my_safe_address = get_eth_address_with_invalid_checksum()
        response = self.client.post(
            reverse("v1:safe-multisig-tx-estimates", args=(my_safe_address, )),
            data={},
            format="json",
        )
        self.assertEqual(response.status_code,
                         status.HTTP_422_UNPROCESSABLE_ENTITY)

        my_safe_address, _ = get_eth_address_with_key()
        response = self.client.post(
            reverse("v1:safe-multisig-tx-estimates", args=(my_safe_address, )),
            data={},
            format="json",
        )
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

        initial_funding = self.w3.toWei(0.0001, "ether")

        safe = self.deploy_test_safe(number_owners=3,
                                     threshold=2,
                                     initial_funding_wei=initial_funding)
        my_safe_address = safe.address

        to = Account.create().address
        tx = {
            "to": to,
            "value": initial_funding // 2,
            "data": "0x",
            "operation": 1
        }
        response = self.client.post(
            reverse("v1:safe-multisig-tx-estimates", args=(my_safe_address, )),
            data=tx,
            format="json",
        )
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        # Use not existing Safe
        non_existing_safe_address = Account.create().address
        response = self.client.post(
            reverse("v1:safe-multisig-tx-estimates",
                    args=(non_existing_safe_address, )),
            data=tx,
            format="json",
        )
        self.assertEqual(response.status_code,
                         status.HTTP_422_UNPROCESSABLE_ENTITY)
        self.assertIn("SafeDoesNotExist", response.data["exception"])

        # Add to database and test
        SafeContractFactory(address=my_safe_address)
        response = self.client.post(
            reverse("v1:safe-multisig-tx-estimates", args=(my_safe_address, )),
            data=tx,
            format="json",
        )
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        response = response.json()
        self.assertGreater(int(response["safeTxGas"]), 0)
        self.assertEqual(response["operationalGas"], "0")
        self.assertIsNone(response["lastUsedNonce"])
        self.assertEqual(len(response["estimations"]), 1)
        estimation = response["estimations"][0]
        self.assertGreater(int(estimation["baseGas"]), 0)
        self.assertGreater(int(estimation["gasPrice"]), 0)
        self.assertEqual(estimation["gasToken"], NULL_ADDRESS)

        valid_token = TokenFactory(address=Account.create().address,
                                   gas=True,
                                   fixed_eth_conversion=2)
        response = self.client.post(
            reverse("v1:safe-multisig-tx-estimates", args=(my_safe_address, )),
            data=tx,
            format="json",
        )
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        response = response.json()
        self.assertGreater(int(response["safeTxGas"]), 0)
        self.assertEqual(response["operationalGas"], "0")
        self.assertIsNone(response["lastUsedNonce"])
        self.assertEqual(len(response["estimations"]), 2)
        estimation_ether = response["estimations"][0]
        self.assertGreater(int(estimation_ether["baseGas"]), 0)
        self.assertGreater(int(estimation_ether["gasPrice"]), 0)
        self.assertEqual(estimation_ether["gasToken"], NULL_ADDRESS)
        estimation_token = response["estimations"][1]
        self.assertGreater(int(estimation_token["baseGas"]),
                           int(estimation_ether["baseGas"]))
        self.assertAlmostEqual(
            int(estimation_token["gasPrice"]),
            int(estimation_ether["gasPrice"]) // 2,
            delta=1.0,
        )
        self.assertEqual(estimation_token["gasToken"], valid_token.address)