Transforming An Ethereum Smart Contract into Bitcoin Transactions

Bitcoin currently has no smart contract capability. The Ethereum blockchain was designed with smart contracts in mind. These smart contracts are most often written in Solidity. Now, say you want to write a smart contract in Bitcoin, an easy way to do it, is to first write it in Solidity, as it has the right abstractions, and then transform it systematically to Ethereum.

This cannot be done easily to any contract, as Solidity has a rich set of types, including arrays and mappings. But, since our smart contract targets Bitcoin, our Solidity abstraction will concern payments in Ether. And for such a contract, a systematic transformation can work.

State in Bitcoin

To understand how to transform our smart contract into Bitcoin, we have to consider the fundamental difference between Bitcoin and Ethereum in the handling of the blockchain state. Bitcoin does not really have a concept of a state. Everything in Bitcoin is just the chaining of transitions channeling the output of one (UTXO - unspent transaction output) to the input of another.

Data Recording Output (RETURN) can store up to 80 bytes on the blockchain as a transaction output, but cannot be considered a blockchain state. On the other hand, Ethereum stores an explicit blockchain state with each block. Transactions transform the state of smart contracts.

Transform Contract State into UXTO

The key to transforming a Solidity smart contract into Bitcoin transactions is to consider each public function of the contract as a Bitcoin transaction. Such a function assumes a certain contract state and transforms it into a new state.

A corresponding Bitcoin transaction works from the unspent outputs of previous transactions and yields a collection of unspent transactions. So we need to represent the state of the smart contract with a collection of addresses and their unspent transaction outputs. But which addresses should we use? It depends on the whose in control of the Ether after the contract function. If it is a single address it is simple. A transaction transfers the Bitcoin to that single address. If it is several addresses, we need to use a Bitcoin multisig address.

Conditions on Time

Contract functions involving the withdrawal of Ether usually have a timelock, of the form:

now < startTime + releaseTime

Which is often part of a modifier.

For Bitcoin, this will be expressed as a timelock, using CHECKSEQUENCEVERIFY, such as:

"30d" CHECKSEQUENCEVERIFY DROP

assuming 30d corresponds to startTime + expiryTime.

A Real-Estate Purchase Contract

As an example of such a transformation, consider a smart contract for purchasing real-estate. The lawyer handling the purchase creates the contract. A buyer deposits Ether to the contract. The seller can withdraw it after the buyer approved, or after a certain time period if approved by the lawyer.

contract RealEstatePurchase {



  address lawyer;

  address buyer;

  address seller;



  bool isApprovedByBuyer;

  bool isApprovedByLawyer;

  uint256 timeToApprove;

  uint256 startTime;



  constructor(uint256 _timeToDeliver, address _buyer,

    address _seller, _timeToApprove){

    timeToApprove = _timeToApprove;

    startTime = now;

    lawyer = msg.sender;

    buyer = _buyer;

    seller = _seller;

  }



  function approve() public {

    if (msg.sender == buyer) {

      isApprovedByBuyer = true;

    } else if (msg.sender == lawyer) {

      isApprovedByLawyer = true;

    }

  }



  function() payable public {

  }



  function withdraw() public {

    require(msg.sender == seller);

    if (isApprovedByBuyer ||

       now > startTime + timeToApprove && isApprovedByLawyer) {

         require(buyer.transfer(this.balance));

    }

  }

}

The Transformation

  1. Create a 2-of-3 multisig address using CreateMultiSig for the owner, buyer, and lawyer

  2. Represent approval by buyer with:

    2 < buyer Pubkey > < seller Pubkey> CHECKMULTISIG
    
  3. Represent the condition on time with a timelock together with approval with:

    < startTime + timeToApprove days > CHECKSEQUENCEVERIFY DROP 2 < seller Pubkey > < lawyer Pubkey> CHECKMULTISIG

  4. Build a redeem script combining items 2 and 3:

    IF
    
      2 < buyer Pubkey > < seller Pubkey> CHECKMULTISIG
    
    ELSE
    
      < startTime + timeToApprove days > CHECKSEQUENCEVERIFY DROP
    
      2 < seller Pubkey > < owner Pubkey> CHECKMULTISIG
    
    ENDIF
    
  5. Now ask the buyer to pay to the multisig address from item 1 above.

If you consider the redeem script, it can be used in one of two ways:

  • With buyer approval,

    < buyer Pubkey > < seller Pubkey> T
    
  • With owner approval,

    < buyer Pubkey > < lawyer Pubkey> F
    

The Merging of Contract Functions

We condensed the smart contract functions into Bitcoin Script nested conditions. Such that each path of conditionals corresponds to one possible sequence of calls to the functions.

In the example, these sequences are:

  • Buyer calls approve and then seller calls withdraw

  • Lawyer calls approve and then after the required time passes, seller calls withdraw

The More General Case

Consider any payment smart contract to operate in alternating phases of deposit and withdraw. In Bitcoin, these will correspond to a first phase leaving unspent transaction outputs, and a second phase using these outputs under some conditions.

Represent the state of the smart contract after the first phase with a set of timelocks and multisig verification. Combine the set into a condition script expression.

So generalizing the above real-estate purchase, consider a smart contract for renting real-estate. Such a contract will necessarily involve multiple installments. With the option of canceling the withdrawal of an installment up to a certain time. So we have multiple phases of deposit and withdraw.

Binding the Multiple Bitcoin Transactions

For a smart contract with multiple phases, we would need a web 3 program to bind them, generating each transaction in turn. This works the same way a web3 program calls the different functions of a Solidity smart contract in sequence.

Conclusions

We have outlined how to transform a Solidity smart contract into Bitcoin. In future work, we intend to flash in full how to handle the alternating deposit and withdraw phases.