Post-Conditions


In Stacks, transactions can have post-conditions.

These offer additional security to ensure a transaction was executed as expected.

More precisely, adding post-conditions to a transaction can ensure that:

  • STX tokens were transferred from an address
  • FTs/NFTs were transferred from an address
Info

Post-conditions aren't perfect. They can't say anything about the end-state after a transaction. In other words, they can't guarantee the receipt of FTs/NFTs, since they only check for sending.

Here's an example of a post-condition using the Pc helper, where the principal must send 1000 uSTX, or else the transaction will abort:

1
import { Pc } from '@stacks/transactions';
2
3
const tx = await makeContractCall({
4
// ...
5
postConditions: [
6
Pc.principal('STB44HYPYAT2BB2QE513NSP81HTMYWBJP02HPGK6').willSendEq(1000).ustx(),
7
],
8
});

If you prefer to write the post-condition manually, you can do so using the following approach:

1
import { StxPostCondition, FungiblePostCondition, NonFungiblePostCondition } from '@stacks/transactions';
2
// STX post-condition
3
const stxPostCondition: StxPostCondition = {
4
type: 'stx-postcondition',
5
address: 'SP2JXKMSH007NPYAQHKJPQMAQYAD90NQGTVJVQ02B',
6
condition: 'gte', // 'eq' | 'gt' | 'gte' | 'lt' | 'lte'
7
amount: '100',
8
};
9
10
// Fungible token post-condition
11
const ftPostCondition: FungiblePostCondition = {
12
type: 'ft-postcondition',
13
address: 'SP2JXKMSH007NPYAQHKJPQMAQYAD90NQGTVJVQ02B',
14
condition: 'eq', // 'eq' | 'gt' | 'gte' | 'lt' | 'lte'
15
amount: '100',
16
asset: 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.my-ft-token::my-token',
17
};
18
19
// Non-fungible token post-condition
20
const nftPostCondition: NonFungiblePostCondition = {
21
type: 'nft-postcondition',
22
address: 'SP2JXKMSH007NPYAQHKJPQMAQYAD90NQGTVJVQ02B',
23
condition: 'sent', // 'sent' | 'not-sent'
24
asset: 'SP3D6PV2ACBPEKYJTCMH7HEN02KP87QSP8KTEH335.my-nft::my-asset',
25
assetId: Cl.uint(602),
26
};

Post-condition mode

In addition to the post-condition itself, we can also specify a mode for the transaction to verify asset transfers. The mode can be either Allow or Deny.

  • Allow means that the transaction can transfer any asset (assuming no conflicting post-conditions).
  • Deny means the transaction will fail if any asset transfers (not specified in the post-conditions) are attempted.

In either case, all post-conditions will still be checked. By default, transactions are set to Deny mode for additional security.