The content in this recipe has been pulled from the tutorial on post conditions. Post conditions are an additional safety feature built into the Stacks chain itself that help to protect end users.
Rather than being a function of Clarity smart contracts, they are implemented on the client side and meant to be an additional failsafe against malicious contracts.
Put simply, post conditions are a set of conditions that must be met before a user's transaction will execute. The primary goal behind post conditions is to limit the amount of damage that can be done to a user's assets due to a bug, intentional or otherwise.
So they are sent as part of the transaction when the user initiates it, meaning we need a frontend library to utilize them.
Whenever you are transferring an asset (fungible or non-fungible) from one address to another, you should take advantage of post conditions.
We're going to use Stacks.js to familiarize ourselves with them.
STX Post Condition
import { FungibleConditionCode, makeStandardSTXPostCondition, makeContractSTXPostCondition,} from"@stacks/transactions";// With a standard principalconstpostConditionAddress="SP2ZD731ANQZT6J4K3F5N8A40ZXWXC1XFXHVVQFKE";constpostConditionCode=FungibleConditionCode.GreaterEqual;constpostConditionAmount=12345n;conststandardSTXPostCondition=makeStandardSTXPostCondition( postConditionAddress, postConditionCode, postConditionAmount);// With a contract principalconstcontractAddress="SPBMRFRPPGCDE3F384WCJPK8PQJGZ8K9QKK7F59X";constcontractName="test-contract";constcontractSTXPostCondition=makeContractSTXPostCondition( contractAddress, contractName, postConditionCode, postConditionAmount);
Fungible Token Post Condition
import { FungibleConditionCode, createAssetInfo, makeStandardFungiblePostCondition,} from"@stacks/transactions";// With a standard principalconstpostConditionAddress="SP2ZD731ANQZT6J4K3F5N8A40ZXWXC1XFXHVVQFKE";constpostConditionCode=FungibleConditionCode.GreaterEqual;constpostConditionAmount=12345n;constassetAddress="SP62M8MEFH32WGSB7XSF9WJZD7TQB48VQB5ANWSJ";constassetContractName="test-asset-contract";constfungibleAssetInfo=createAssetInfo(assetAddress, assetContractName);conststandardFungiblePostCondition=makeStandardFungiblePostCondition( postConditionAddress, postConditionCode, postConditionAmount, fungibleAssetInfo);// With a contract principalconstcontractAddress="SPBMRFRPPGCDE3F384WCJPK8PQJGZ8K9QKK7F59X";constcontractName="test-contract";constassetAddress="SP62M8MEFH32WGSB7XSF9WJZD7TQB48VQB5ANWSJ";constassetContractName="test-asset-contract";constfungibleAssetInfo=createAssetInfo(assetAddress, assetContractName);constcontractFungiblePostCondition=makeContractFungiblePostCondition( contractAddress, contractName, postConditionCode, postConditionAmount, fungibleAssetInfo);
NFT Post Condition
import { NonFungibleConditionCode, createAssetInfo, makeStandardNonFungiblePostCondition, makeContractNonFungiblePostCondition, bufferCVFromString,} from"@stacks/transactions";// With a standard principalconstpostConditionAddress="SP2ZD731ANQZT6J4K3F5N8A40ZXWXC1XFXHVVQFKE";constpostConditionCode=NonFungibleConditionCode.Owns;constassetAddress="SP62M8MEFH32WGSB7XSF9WJZD7TQB48VQB5ANWSJ";constassetContractName="test-asset-contract";constassetName="test-asset";consttokenAssetName=bufferCVFromString("test-token-asset");constnonFungibleAssetInfo=createAssetInfo( assetAddress, assetContractName, assetName);conststandardNonFungiblePostCondition=makeStandardNonFungiblePostCondition( postConditionAddress, postConditionCode, nonFungibleAssetInfo, tokenAssetName);// With a contract principalconstcontractAddress="SPBMRFRPPGCDE3F384WCJPK8PQJGZ8K9QKK7F59X";constcontractName="test-contract";constcontractNonFungiblePostCondition=makeContractNonFungiblePostCondition( contractAddress, contractName, postConditionCode, nonFungibleAssetInfo, tokenAssetName);
Sample App
Here's a sample application that utilizes post conditions on the front end to secure user assets.