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

transfer calculate fee Bug #16

Open
LB6264 opened this issue Sep 17, 2021 · 21 comments
Open

transfer calculate fee Bug #16

LB6264 opened this issue Sep 17, 2021 · 21 comments

Comments

@LB6264
Copy link

LB6264 commented Sep 17, 2021

hello
My balance is 3.328735 ADA
Same input parameter: 3 ADA

Yoroi Wallet costs 0.328735 ADA

Val fee = feeCalculationService. CalculateFee (paymentTransaction detailsParams, null) to calculate the charge is: 0.176017 ADA

Is there a bug in calculating the handling fee
The end result is total transfer failure

@LB6264
Copy link
Author

LB6264 commented Sep 17, 2021

Sorry, I am a Chinese developer, my English is not good, with the help of translation sentences, I hope you can help answer

@satran004
Copy link
Member

satran004 commented Sep 18, 2021

Are you doing a simple ADA transfer transaction ? Is there any native token in the utxo ?

If it's just a ADA transfer, 0.176 ADA txn fee looks normal. 0.328 ADA is definitely more for only ADA transaction.

You may want to reproduce the same on testnet.

@LB6264
Copy link
Author

LB6264 commented Sep 22, 2021

{
"address": "addr1qxsjehae7esrs5xqhrqeph...............pjnh",
"amount": [{
"unit": "lovelace",
"quantity": "3328735"
}],
"stake_address": "stake1u8c3knx0cvma8hlz............m",
"type": "shelley",
"script": false
}

min_fee_a:44,
min_fee_b":155381,
size:469
fee:176017 = min_fee_a*size + min_fee_b
But the same address ,Yoroi Wallet costs 0.328735 ADA,
I don't know what the problem is

@LB6264
Copy link
Author

LB6264 commented Sep 22, 2021

9429c432d80b638677694d9605f465d
the same address ,Yoroi Wallet costs 0.328735 ADA,

@LB6264 LB6264 changed the title Bug transfer calculate fee Bug Sep 22, 2021
@LB6264
Copy link
Author

LB6264 commented Sep 22, 2021

{
"error": "Bad Request",
"message": ""transaction submit error ShelleyTxValidationError ShelleyBasedEraAlonzo (ApplyTxError [UtxowFailure (WrappedShelleyEraFailure (UtxoFailure (ValueNotConservedUTxO (Value 12475948 (fromList [(PolicyID {policyID = ScriptHash \"07309ed26f7636932617826b6991c7b6d8a7fa8fea66c5b9f020e687\"},fromList [(\"MYToken\",56)])])) (Value 37427844 (fromList [(PolicyID {policyID = ScriptHash \"07309ed26f7636932617826b6991c7b6d8a7fa8fea66c5b9f020e687\"},fromList [(\"MYToken\",168)])])))))])"",
"status_code": 400
}

Above is the transaction of error, doubt and poundage calculation

@satran004
Copy link
Member

It looks like mismatch in total input and total output amount. Not sure but may be due to min ada amount requirement in utxo (due to native tokens). You may want to add few ADA to the account (2 or 3 ADA enough) and try the transaction again.

It could be a bug due to some edge case.

Is it possible to provide the utxo inputs used in this transaction ? Please change the txn hash or address in the utxo and paste here. Keep the amount including native tokens as it is. It will help me to debug the issue.

@LB6264
Copy link
Author

LB6264 commented Sep 23, 2021

----------------------------------- [{"tx_hash":"f3c464be15a5e29a1a6d322c5cd040c87075d1cfc89d4b397568d14c0ba53cd9","tx_index":1,"output_index":1,"amount":[{"unit":"lovelace","quantity":"1452846"},{"unit":"07309ed26f7636932617826b6991c7b6d8a7fa8fea66c5b9f020e6874d59546f6b656e","quantity":"56"}],"block":"10974607187afacfeed5e3eaf4342e06bad0f26de438319eca18fa93f6a1541e","data_hash":null},{"tx_hash":"d60669420bc15d3f359b74f5177cd4035325c22f7a67cf96d466472acf145ecb","tx_index":0,"output_index":0,"amount":[{"unit":"lovelace","quantity":"10000000"}],"block":"eee6cd082d297f85406cff49f83aa3ebd1083dae3c8997ec03f4a17f49297bf6","data_hash":null}]

inputs

TransactionInput{transactionId=d60669420bc15d3f359b74f5177cd4035325c22f7a67cf96d466472acf145ecb, index=0}
TransactionInput{transactionId=f3c464be15a5e29a1a6d322c5cd040c87075d1cfc89d4b397568d14c0ba53cd9, index=1}

outputs

TransactionOutput{address='addr_test1qq68lmuklk4rntgnvgy3t5g86kfyvhqm877km7593t4cvkm4nyle5utujmjxgnvm84mlql6cm7l3qhtm7yr5datr8j7qcvunl0', value=10400000}
TransactionOutput{address='addr_test1qz3s0c370u8zzqn302nppuxl840gm6qdmjwqnxmqxme657ze964mar2m3r5jjv4qrsf62yduqns0tsw0hvzwar07qasqeamp0c', value=881273}

fee

0.171573 ADA

result

{"error":"Bad Request","message":""transaction submit error ShelleyTxValidationError ShelleyBasedEraAlonzo (ApplyTxError [UtxowFailure (WrappedShelleyEraFailure (UtxoFailure (OutputTooSmallUTxO [(Addr Testnet (KeyHashObj (KeyHash \"a307e23e7f0e2102717aa610f0df3d5e8de80ddc9c099b6036f3aa78\")) (StakeRefBase (KeyHashObj (KeyHash \"592eabbe8d5b88e92932a01c13a511bc04e0f5c1cfbb04ee8dfe0760\"))),Value 881273 (fromList [(PolicyID {policyID = ScriptHash \"07309ed26f7636932617826b6991c7b6d8a7fa8fea66c5b9f020e687\"},fromList [(\"MYToken\",56)])]),SNothing)])))])"","status_code":400}

The above is the input and output of parameters, please help me to check the specific error reason,thank you
There seems to be a problem with the combined payment, it is correct to input the quantity below 10ADA, but when it exceeds 10ADA, there is an error when it involves multiple accounts. I don't know if there is a Bug in the calculation rule of Cardano-client-lib, you need to help verify it according to the above parameters, thank you

@satran004
Copy link
Member

"when it exceeds 10ADA, there is an error when it involves multiple accounts"

So multiple senders and receivers ?

It could be a bug.

@satran004
Copy link
Member

Meanwhile, as a workaround, you may want to manually construct transaction (without TransactionHelper).
Here's a sample https://gist.github.com/satran004/979e3da6bc819e9fe0568f40c2887196

Alternatively, you can also provide your own UtxoSelectionStrategy if you still want to use higher level api like TransactionHelper
https://github.com/bloxbean/cardano-client-lib#utxoselectionstrategy

@LB6264
Copy link
Author

LB6264 commented Sep 27, 2021

Hello, I still haven't solved this problem. Could you fix the bug when I transferred ADA

@satran004
Copy link
Member

satran004 commented Sep 27, 2021

Hi @LB6264 , I just started looking into the utxos sample you sent earlier.
The 2nd output has value 881273 lovelace which is less than min ada required for an Utxo (~ 1 ada). That could be the reason for "OutputTooSmallUTxO". So looks like insufficient balance at sender address.

Also, the output (TransactionOutput) is missing the native token (unit: 07309ed26f7636932617826b6991c7b6d8a7fa8fea66c5b9f020e6874d59546f6b656e).

Can you please also attach your code sample where you are creating and posting the transaction ?

But in your 1st sample, the error message was different "ValueNotConservedUTxO".

Also, what do you mean by when multiple accounts involved ? Same mnemonic and multiple addresses at different indexes for the sender ?

BTW, by default the client-lib works with sender address at index 0 and only utxos specific to that address. It doesn't automatically scan all address at different indexes for the mnemonic. To use an address at different index, you have to use this constructor

Account(Network network, String mnemonic, int index)

@LB6264
Copy link
Author

LB6264 commented Sep 28, 2021

This problem is easily replicated, for example:

I have 10 Adas in the balance, and I want to transfer all 10 Adas. Cardano-client-lib is used, but I cannot get the expected result.

suspend fun signerTransaction(
sender: Account,
receiver: String,
amount: String,
ethToken: EthToken
): String {
LogCat.d("-------signerTransaction-----amount-----:$amount")
return withIO {
val paymentTransaction = PaymentTransaction()
paymentTransaction.sender = sender
paymentTransaction.receiver = receiver
if (ethToken.isTokenCoin()) {
paymentTransaction.amount = BigInteger.valueOf(amount.toLong())
paymentTransaction.unit = ethToken.tokenAddress
} else {
paymentTransaction.amount =
BigInteger.valueOf(MathHelper.mul(amount, ONE_ADA.toString()).toLong())
paymentTransaction.unit = LOVELACE
}

        //Calculate Time to Live
        val detailsParams = buildTransactionDetailsParams()
        //Calculate fee
        val fee = feeCalculationService.calculateFee(paymentTransaction, detailsParams, null)
        paymentTransaction.fee = fee
        LogCat.d("手续费:${paymentTransaction.fee}")
        val result: Result<TransactionResult> = transactionHelperService.transfer(
            paymentTransaction,
            detailsParams
        ) as Result<TransactionResult>

// LogCat.d("-----------------${result}")
// LogCat.d("-----------------${Numeric.toHexString(result.value.signedTxn)}")
val hash = result.value.transactionId
LogCat.d("--------交易---------$hash")
if (!waitForTransaction(hash)) {
withMain {
//保存到缓存
val info = TradeInfo()
info.timeStamp = (System.currentTimeMillis() / 1000).toString()
info.hash = hash
info.itemType = 1
info.inputsAddress.add(sender.baseAddress())
info.outputsAddress.add(receiver)
info.value = paymentTransaction.amount.toString()
info.fee = paymentTransaction.fee.toString().parseDouble()

                EthTradeAgent.saveConfirmTradeCache(ethToken, info)
            }
        }
        result.value.transactionId
    }

}

@LB6264
Copy link
Author

LB6264 commented Sep 29, 2021

testnet mnemonic:
cruise express sleep donate goat jeans thing wage lumber drill pudding fiction session weekend kite manage indicate any together news peanut basic poem ordinary

The balance 11.664970 ADA is enough, transfer 11ADA, there is also a mistake,See the picture below for details
e8cd027efe9be552ec8ce9c8ef6adda

@satran004
Copy link
Member

@LB6264 Thanks. Will check today.

@prediator
Copy link

prediator commented Sep 29, 2021

@satran004 i am facing similar issue.

Address:- addr_test1qrark97feve329u6n0w7xr73e5mu8llvs8nl83cu3x8k4peseqdyq0sxh5x6u50dsqkn8jzuymn2v64ztqr7g0auvpps697cqa

Using the same sample code provided in the cardano-client-examples to mint asset. I am not able to mint it. It throws ValueNotConservedUTxO

Keys keys = KeyGenUtil.generateKey();

VerificationKey vkey = keys.getVkey();
SecretKey skey = keys.getSkey();

ScriptPubkey scriptPubkey = ScriptPubkey.create(vkey);
String policyId = null;

policyId = scriptPubkey.getPolicyId();

assets.setMetaData(policyId);

MultiAsset multiAsset = new MultiAsset();
multiAsset.setPolicyId(policyId);
Asset asset = new Asset(HexUtil.encodeHexString(request.getName().getBytes(StandardCharsets.UTF_8)),
		BigInteger.ONE);
multiAsset.getAssets().add(asset);

MintTransaction mintTransaction = MintTransaction.builder().sender(sender)
		.receiver(request.getReceiverAddress()).mintAssets(Arrays.asList(multiAsset))
		.policyScript(scriptPubkey).policyKeys(Arrays.asList(skey)).build();

String meta = adaWalletService.buildNftJson(request, policyId);

Metadata metadata = JsonNoSchemaToMetadataConverter.jsonToCborMetadata(meta);

BigInteger fee = backendService.getFeeCalculationService().calculateFee(mintTransaction,
		TransactionDetailsParams.builder().ttl(adaWalletService.getTtl(backendService)).build(),
		metadata);

mintTransaction.setFee(fee);

Result<TransactionResult> result = backendService.getTransactionHelperService().mintToken(
		mintTransaction,
		TransactionDetailsParams.builder().ttl(adaWalletService.getTtl(backendService)).build(),
		metadata);

UTXO's

[
    {
        "tx_hash": "527aa2dcb78a5d64219960ecad7bc0c09aa38ee46ed54df73bde29baed1dea11",
        "tx_index": 0,
        "output_index": 0,
        "amount": [
            {
                "unit": "lovelace",
                "quantity": "3247042"
            },
            {
                "unit": "5572ae9a3540ddafd3c4fb8553cf77187f21123f003a27676d6fe25c54657374",
                "quantity": "1"
            },
            {
                "unit": "61a6c9c9bb5f44a0f7435f5de7972fea764cd59f6ae1630a2664710b54657374",
                "quantity": "1"
            }
        ],
        "block": "4906f9d49950715392688e3c7ed8995a4ed7e8e5d03b1ac409d4b94a8ebe44ad",
        "data_hash": null
    },
    {
        "tx_hash": "527aa2dcb78a5d64219960ecad7bc0c09aa38ee46ed54df73bde29baed1dea11",
        "tx_index": 1,
        "output_index": 1,
        "amount": [
            {
                "unit": "lovelace",
                "quantity": "1444443"
            },
            {
                "unit": "a8c6dadd99bd0cb546bbf02e4c5934962b71a7d8e5f482ef8a17727754657374",
                "quantity": "1"
            }
        ],
        "block": "4906f9d49950715392688e3c7ed8995a4ed7e8e5d03b1ac409d4b94a8ebe44ad",
        "data_hash": null
    },
    {
        "tx_hash": "ce2de0809604679ac8d1f569a734520222766c0e060ae93b47078aff90666f53",
        "tx_index": 0,
        "output_index": 0,
        "amount": [
            {
                "unit": "lovelace",
                "quantity": "1000000"
            }
        ],
        "block": "1d2758fd73de5a7ad76fbae627d714317def29e7f8b9a14115fb47b24679e58e",
        "data_hash": null
    },
    {
        "tx_hash": "5ea56fc0e95ced066af439a629aa72220768357daaee25c9fb368e759a3752e1",
        "tx_index": 0,
        "output_index": 0,
        "amount": [
            {
                "unit": "lovelace",
                "quantity": "1000000"
            }
        ],
        "block": "fcbd88856f1eed9431df5c14ae42cd153a9ee16b16c85d4ded3c83d76b638dd5",
        "data_hash": null
    }
]

@satran004
Copy link
Member

The balance 11.664970 ADA is enough, transfer 11ADA, there is also a mistake,See the picture below for details

@LB6264, Thanks for the account details. I tried it.

So, when you are sending out 11 ADA, there is not enough ADA for the change output which goes back to sender.

So for example, in this case, there are two transaction outputs :-

  1. receiver - 11 ADA
  2. change address (sender) - ~ 0.494970 ADA (after fee deduction)

Also, the input utxo has a native token, so the minimum amount needed in change address (#2) is around 1.4 ADA (protocol requirement). But as only 0.494 ADA available it fails. So any transfer above ~10.2 will fail.

But I think, there is also an issue in lib.

  1. During fee calculation, lib creates an actual transaction and computes the fee based on the txn size. But because of this edge scenario, fee computation fails with "Insufficient utxo amount error". I think, fee computation should happen without any error. So that, if you want to send all the ADA from an account, it can be computed in the calling application.

  2. Lib should provide a better way to send all the ADA from sender account to another (if there is no native token)

Currently, we have to keep minimum ~1.x ADA in sender acc. You can not make the sender account empty using client-lib.

You can check this address addr_test1qz3s0c370u8zzqn302nppuxl840gm6qdmjwqnxmqxme657ze964mar2m3r5jjv4qrsf62yduqns0tsw0hvzwar07qasqeamp0c

Let me think how we can fix this.

But as I had mentioned earlier, you can programmatically build Transaction using TransactionInput/Ouput lower level apis if you want better control. You don't need to go through higher level apis like TransactionHelper.
https://gist.github.com/satran004/979e3da6bc819e9fe0568f40c2887196

@satran004
Copy link
Member

@prediator please check the above comment if it applies to your issue.

Also, it looks like you have 3 tokens in that address. The min ada requirement increases with additional native tokens in utxo.

@LB6264
Copy link
Author

LB6264 commented Sep 30, 2021

@satran004 Thank you for your patient solution. I have tried to use programmatically build Transaction using TransactionInput/Ouput lower level apis, but there will be problems when calculating edge conditions and bringing native tokens. I hope you can fix this problem as soon as possible in lib.

@prediator
Copy link

@satran004

Thanks for the detail explanation.

Is there any way from the lib to get the exact minada required for a native tokens minting, so that we can prompt user to add sufficient ADA to the wallet.

satran004 added a commit that referenced this issue Sep 30, 2021
…iteria doesn't match. Fee calculation should be successful even if there is not enough utxos.
@satran004
Copy link
Member

satran004 commented Sep 30, 2021

@LB6264 I have done a partial fix for now. You need to build the project locally to try out the fix.

Fee calculation should not throw any error now. Also, if there is no native tokens available at sender address, you should be able to transfer all ADA from sender address to receiver. But for that you need to calculate the transfer amount in your application. First calculate the fee and then amount = balance - fee. Set the calculated amount in the PaymentTransaction.amount(). Please refer to the below code snippet.

Note: - But, if you are sending out partial ADA amount, make sure the remaining amount at sender address is greater than minimum ADA amount (~1.4 ADA) after transfer.

But if you have one or more native tokens at the sender address, you first need to transfer out all native tokens and then only you can send out all remaining ADA. I will check if these two steps could be simplified.

Let me know if you find any issue. I will continue with more testing.

 PaymentTransaction paymentTransaction =
                PaymentTransaction.builder()
                        .sender(sender)
                        .receiver(receiver)
                        .amount(BigInteger.valueOf(0))  //Any amount just for fee calculation
                        .unit(LOVELACE)
                        .build();

        long ttl = blockService.getLastestBlock().getValue().getSlot() + 1000;
        TransactionDetailsParams detailsParams =
                TransactionDetailsParams.builder()
                        .ttl(ttl)
                        .build();

        BigInteger fee = feeCalculationService.calculateFee(paymentTransaction, detailsParams
                , null);

        paymentTransaction.setFee(fee);

        BigInteger balance = new BigInteger("11500000");
        BigInteger amtToTransfer = balance.subtract(paymentTransaction.getFee());
        paymentTransaction.setAmount(amtToTransfer); //Set the remaining amount after fee

        Result<TransactionResult> result = transactionHelperService.transfer(paymentTransaction, detailsParams);

@satran004
Copy link
Member

@satran004

Thanks for the detail explanation.

Is there any way from the lib to get the exact minada required for a native tokens minting, so that we can prompt user to add sufficient ADA to the wallet.

@prediator You can check MinAdaCalculator class. But you need to create TransactionOutput object manually.
Right now, there is no high level api using MintTransaction api.

https://github.com/bloxbean/cardano-client-lib/blob/master/src/main/java/com/bloxbean/cardano/client/common/MinAdaCalculator.java

Check the test cases for usage :

https://github.com/bloxbean/cardano-client-lib/blob/master/src/test/java/com/bloxbean/cardano/client/common/MinAdaCalculatorTest.java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants