Is there a default and max TTL for transactions?

I haven’t been able to find info on the above question… so is there a default and a max TTL that we can set for our transactions?

And if there’s no default, is it still possible to cancel transactions while they are still sitting in the mempool waiting to be written to a block?

I think most wallet apps set something. At least, I have to confirm something about TTL on my Ledger, when confirming the transactions. The protocol itself does not have a default, as far as I know. If I do not set --invalid-hereafter in cardano-cli transaction build, the transaction will be valid forever (with some restrictions below).

Depends on the service used. For example, in the Blockfrost API (the one used by Nami), I do not see any cancellation feature: https://docs.blockfrost.io/

But: If other transactions (through other channels) were already successful later on, the chances will be very high, that the transaction stuck in the mempool will fail, because its inputs were already used by these other successful transactions.

You could also provoke this by once sending everything to yourself. This will use all the UTxOs (unspent transaction outputs; everything you have in your wallet once came through a transaction and now sits at the output of that transaction, until it is sent further) and then the stuck transaction (that also had to have one or more of these UTxOs as inputs) cannot succeed anymore.

Yeah, this is really what I’d like to find out for sure. I’d like to know for certain if this is really the case.

This will be hard to do successfully. Unlike in EVM-compatible chains where we can set higher transaction fees to prioritize trxs, here on Cardano, we can’t do that. Nodes process transactions in the order they are submitted.

You could go through the code of your favourite wallet. Couldn’t do a full code review, but:

Both, Nami and Yoroi seem to set 7200 seconds, 2 hours as their default.

Yes … and no. In the Nami/SundaeSwap situation, a lot of people switched to ccvault or other wallet apps, because of the total congestion of Nami/Blockfrost. When they successfully did a transaction there (which did not use the congested Blockfrost mempool, but totally different nodes to submit), that transaction got processed first, potentially taking away the UTxO(s) of the transaction stuck in Blockfrost.

Based on this – 2 hours TTL and successful transactions taking away UTxOs – most of the transactions stuck in these mempools the past weekend, should have failed eventually.

Sorry, I wasn’t clear enough - what I mean is the blockchain protocol default, not the wallet app’s default. But thank you for these references.

Yep, I see… this makes sense. But not really a reliable way to “cancel” pending transactions.

Probably, because nobody designed it to be for cancelling. On normal days, there should not really be time to cancel, so why even designing a feature for that?

(If it is pending in the mempool, before even reaching a block producing node, it is not a matter of the protocol to cancel it. Could make sense to build cancelling into the API of such a service.)

I’m not really interested in discussing design motivations in this particular case. Just wanted to know what’s possible in the current design. Because I’m currently working on an app that could use such info.

That’s just it. :grin:

1 Like

Ah, okay. I researched until the command line tools.

While https://github.com/input-output-hk/cardano-node/blob/master/doc/reference/building-and-signing-tx.md makes it sound like you have to set --invalid-hereafter to something (then there would not have to be a default, because every transaction would have to choose), the examples in https://developers.cardano.org/docs/native-tokens/minting/ do not set one at all, while the examples in https://developers.cardano.org/docs/native-tokens/minting-nfts/ do (for NFTs it has to be set, because it needs to match the minting policy). Note that examples with a TTL years in the future seem to work.

To know, what exactly happens, when nothing is set (and if there perhaps is a maximum in addition to the set invalid-hereafter parameter), you might need to dust off your Haskell skills. :grinning: