HomeKaleido ServicesTokensAnatomy of a Hashed Time Lock Contract (HTLC)

Anatomy of a Hashed Time Lock Contract (HTLC)

At the heart of Kaleido’s Token Swap service is the Hashed Timelock Contract (HTLC). It can be viewed as a safety deposit box that temporarily holds the tokens offered for swap. The lock box allows the designated swap counterparty to claim the tokens after presenting the required credentials. It also supports refunding in case the swap deal falls apart.

Let’s take a look at how things work under the covers.

To support the secure and atomic trades between two parties without having to assume that the parties will behave honestly and fulfill their duties, the HTLC contract must have the following properties:

  • As with all Ethereum smart contracts, the HTLC contract can hold token balances. A swap is created by first depositing the offered tokens into the contract’s lock box. The lock box is told about the intended beneficiary of the tokens, so that only that particular account can claim the tokens.
  • The contract safeguards the tokens with a hash lock. In order to get the contract to release the deposited funds, not only must the designated beneficiary be the signer of the claim() transaction, but the transaction must also present the original secret that produces the hash value used by the hash lock.
  • The contract also supports refunds with a time lock. It is a timeout period to signal to the beneficiary when to make the claim. If the timeout expires, the swap initiator will be able to call refund() to get the tokens back. So the beneficiary is incentivized to make the claim before the timeout expires.
  • A single deployed HTLC contract can keep track of multiple concurrent swaps. In fact, in a Kaleido environment all ERC20 token swaps are supported by the same HTLC contract instance, and likewise for all ERC721 swaps.
  • It is possible to swap both types of ERC20 and ERC721 tokens, including cross-type swaps:
    • ERC20 tokens <=> ERC20 tokens
    • ERC721 token <=> ERC721 token
    • ERC20 tokens <=> ERC721 token

ERC20 HTLC contract:

  • Events:
    • HTLCERC20New
      • bytes32 indexed contractId
      • address indexed sender
      • address indexed receiver
      • address tokenContract
      • uint256 amount
      • bytes32 hashlock
      • uint256 timelock
    • HTLCERC20Withdraw
      • bytes32 indexed contractId
    • HTLCERC20Refund
      • bytes32 indexed contractId
  • Functions:
    • newContract(address _receiver, bytes32 _hashlock, uint256 _timelock, address _tokenContract, uint256 _amount)
      • returns (bytes32 contractId)
    • withdraw(bytes32 _contractId, bytes32 _preimage
      • returns (bool)
    • refund(bytes32 _contractId)
      • returns (bool)
    • getContract(bytes32 _contractId) public view
      • returns (address sender, address receiver, address tokenContract, uint256 amount, bytes32 hashlock, uint256 timelock, bool withdrawn, bool refunded, bytes32 preimage )

HashedTimelockERC721

  • Events:
    • HTLCERC721New
      • bytes32 indexed contractId
      • address indexed sender
      • address indexed receiver
      • address tokenContract
      • uint256 tokenId
      • bytes32 hashlock
      • uint256 timelock
    • HTLCERC721Withdraw
      • bytes32 indexed contractId
    • HTLCERC721Refund
      • bytes32 indexed contractId
  • Functions:
    • newContract(address _receiver, bytes32 _hashlock, uint256 _timelock, address _tokenContract, uint256 _tokenId)
      • returns (bytes32 contractId)
    • withdraw(bytes32 _contractId, bytes32 _preimage
      • returns (bool)
    • refund(bytes32 _contractId)
      • returns (bool)
    • getContract(bytes32 _contractId) public view
      • returns (address sender, address receiver, address tokenContract, uint256 tokenId, bytes32 hashlock, uint256 timelock, bool withdrawn, bool refunded, bytes32 preimage )