Pay to Contract Hash

Getting your Trinity Audio player ready...

This post was first published on Medium.

Bitcoin Smart Contract Limitations

Smart Contracts on Bitcoin have been shown to be more powerful and versatile than previously thought. Yet, there are still two grave limitations:

  1. A contract cannot support new features once deployed. For example, we could deploy a token contract, only to find out later it cannot be integrated into some new exchange or voting applications, due to lack of certain features. This greatly hinders its interoperability with third party applications and thus wide adoption.
  2. All supported features must be included in the token contract, implied by 1. Even if we would foresee all features the token needs to support when it is first conceived, only a few features are frequently used and most of the them are rarely, if not never, used. This causes contract size bloating.

Pay to Contract Hash

We propose a novel approach to address both limitations simultaneously, called Pay to Contract Hash (P2CH). We use NFT as an example to demonstrate how it works. It is also applicable to other crypto assets such as native bitcoins and fungible tokens.

In our previous NFT contract, we maintain a table mapping each token to its owner’s address. The owner possesses a private key that can authorizes the transfer of the token.

Figure 1: NFT 3 is Owned by a Contract
Figure 1: NFT 3 is Owned by a Contract

Under P2CH, the owner can also be a contract’s address, defined as the hash160 of its script. It appears the same as a regular bitcoin address, since they are both 20 bytes. The new NFT contract looks like the following:

Contract Pay2ContractHash

This is the same NFT contract as before, except for the else branch. It handles the transfer when a token is controlled by a contract, instead of a user’s private key. As Figure 2 shows, we need to ensure the contract is unlocked in another input of the same transaction, as we have done in inter-contract call. Line 20-22 get the id of the transaction containing the contract (tx1 in the diagram) and the output containing it (output 0). Line 24 validates the full transaction matches the txid. Line 26 parses the contract transaction to get the contract’s full script and hashes it and matches it against the owner “address” at Line 27.

Figure 2: Transfer Token Controlled by a Contract

Figure 2: Transfer Token Controlled by a Contract

A TokenSale contract example

One contract could be the following:

TokenSale Example

It can be spent if and only if a given address is paid a specific amount. Using this contract, we can sell a token at a given price atomically in three steps:

  1. Deploy TokenSale contract.
  2. Transfer a token to the hash of the above contract, i.e., hash160 of its locking script.
  3. Unlock both the token and TokenSale contract in a single transaction, as in Figure 2. The buyer will transfer the token from the contract to himself.

A full code example can be found here.


It is worth noting the contract can be arbitrary and can be developed by a third party independently. This means the token is infinitely extensible (limitation 1). Also it is compact and only handles P2CH that applies to any contract (limitation 2).

In addition, they are alternative ways to pattern match a contract. We use hash of the full contract script. Parts of the script can also be used, e.g., the code part of a stateful contract.


The idea comes from Chen Cheng of Sensible Contract.

Watch: CoinGeek New York presentation, Smart Contracts & Computation on Bitcoin

YouTube video

New to blockchain? Check out CoinGeek’s Blockchain for Beginners section, the ultimate resource guide to learn more about blockchain technology.