Postconditions on transactions

You follow a link to a website on an influencer’s social media channel. The site promises to airdrop some tokens if you own a certain NFT. You pair your wallet with the dapp, sign a transaction to claim your airdrop and … all the assets in your wallet are gone. The influencer’s social media account was hacked, the link sent you to a malicious website and you signed away your assets when doing the transaction.

What can be done? In theory, you could inspect the contract’s code before interacting with it, but who can reliably do that on any reasonable time frame? It’s also easy to obfuscate malicious behavior.

You could rely on trusted lists of safe websites and safe contracts, and those lists could be known to wallets, but this create enormous pressure on the list maintainers to verify and approve contracts.

You could try and simulate what the transaction will do, but a sophisticated attacker will create a contract with a switch to trigger the malicious behavior, and inject a transaction that turns on the switch right before your transaction. The simulation will make the contract appear innocuous, but it will still behave maliciously when the transaction is included in the block.

One solution to this conundrum is to enable postconditions on transactions. Interacting with a smart contract can trigger all sorts of side effects, but attackers primarily care about one: take your assets.

Every transaction in Tezos produces a receipt, which describes the changes to the ledger caused by the transaction. A post-condition would be a bit of Michelson code that is triggered after the transaction as completed and takes the receipt as input. The postcondition can then either succeed or fail. If it fails, the entire transaction is rolled back.

A typical postcondition would be to verify that none of the effects involve an allowance for an asset changing, or an asset changing hands. A dapp that does require an asset to change hand would propose to the wallets a postcondition that relaxes those conditions. The wallet would then be able to warn the user that the dapp has asked to authorize moving up to quantity qa and qb of assets A and B.

This can only be done with a protocol change, it’s not something you can build with just smart-contracts.

I think it would be a nice feature as people would be able to interact with smart-contracts without needing to trust their behavior as much.

This isn’t a silver bullet, there are state changes user care about that might not be caught in the “default” post-conditions. For example, if you have an NFT for sale in a marketplace, a malicious website could trick you into lowering the asking price a lot, and that wouldn’t look like an asset changing hands. It’s also something that would require a fair bit of standardization across wallets to be helpful.

Nonethless, it’s a unique feature that’s not available on any blockchain and that seems to solve a real pain point users are experiencing today.


Hey Arthur, with your proposed implementation, is it possible to have a transaction with a post condition, and for that post condition send another transaction with another post condition, etc?

If the above is possible, and the last post condition fails, do we roll back all the transactions triggered in all post conditions?

That would be very useful - I’ve personally spent many hours vetting airdrops and the like to avoid the situation you described, wishing I had a mechanism like this.

One nit: You say this would require a change to the protocol, but why couldn’t it be done at the wallet level? Here, the wallet would just add a final op to the op batch that asserts nothing bad happened. IIUC, the switch from BFS → DFS contract execution means we’d know the assert-op would always be the last op in the batch, making it the postcondition you described.

1 Like

This seems related to Monitors.


No, the post condition’s only effect is to either allow or disallow the transaction. You could do what you describe but I think it would add a lot of complexity.

Because that transaction would have to iterate over all possible assets you might own and check their balance, it wouldn’t complete in time.

1 Like

You mentioned this in the recent AMA and I thought it was super interesting. Would be a fantastic addition to set Tezos apart and generate trust in the ecosystem. Not only for NFTs, but also DeFi.

This would be a great feature. How does it look in practice? A condition that says “no NFT asset will change hands” would have to check all assets in your wallet? But what does that look like for a user that holds thousands of NFTs in their wallet across a variety of standard (OBJKT) and non standard FA2 contracts?

re: transaction insight, would it not be possible (at wallet level) to show the user the contract interaction in broad strokes and it’s actions (“transfer X token to Y address”, “set approval for X tokens”)? Shouldn’t this be easier since Michelson is stack based and easily parsed?

No, the postconditions applies to the transaction receipt which would contain explicit information about NFT leaving your wallet. The fact that it’s not practical to iterate over every possible asset is exactly why this proposal requires a protocol change.

Why not doing an HTTP(S)-like for “SECURE” mechanism ?
Like secure for secure website under a specific certificate, we do trust some certificate authorities.

In Tezos, we could whitelist some audit companies that sign a particular smart contract, then we can consider it as “SECURE”. Wallet should be able to display a secure icon when this kind of contract is called, either displaying a warning when a smart contract has not been audited by a trusted audit company.
Wallets should manage a default list of audited company public keys, also being possible for the user to add new ones

In Tezos, we could whitelist some audit companies that sign a particular smart contract, then we can consider it as “SECURE”

If a specific Tezos account chooses to trust a third party, that’s the business of that account (and by extension the account holder).

I wouldn’t want the protocol to automatically trust certain third parties by default as that will reduce decentralization and create risk, should any of those trusted parties be compromised.

Like I said, is owners’ wallet configuration, not the protocol

If I understand correctly, the post-condition is more lightweight to this secured-by-audit-companies mechanism. A security specifically required by certain scenario can be defined by a post-condition directly.

It depends for who :slight_smile:

On protocol is just to add a digital signature from a public auditor

On wallet side is to manage a list of known and trusted auditors

So it is quite different from the post condition but aim to resolve the same troubles

Indeed, transaction monitors provide a solution. We have a paper (under review) with impossibility results (therefore the protocol must change) and recommendations about different ways to add capabilities for transaction monitoring. We will arxive and share the paper as soon as possible.