New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ERC 1630 - Hashed Time-Locked Contract Standard #1630

wants to merge 6 commits into
base: master


None yet
3 participants

mattBlackDesign commented Nov 29, 2018

eip: 1630
title: Hashed Time-Locked Contracts
author: Matthew Black, TingWei Liu, Liquality Team
status: Draft
discussions-to: #1631
type: Standards Track
category: ERC
created: 2018-11-28

Simple Summary

A standard EVM script for generalized payments that acknowledges receiving the payment prior to a deadline.


A Hashed Time-Lock Contract (HTLC) is a script that permits a designated party (the "seller") to spend funds by disclosing the preimage of a hash. It also permits a second party (the "buyer") to spend the funds after a timeout is reached, in a refund situation.


HTLC transactions are a safe and cheap method of exchanging secrets for money over the blockchain, due to the ability to recover funds from an uncooperative counterparty, and the opportunity that the possessor of a secret has to receive the funds before such a refund can occur.

HTLC's enable cross-chain atomic swaps


msg.sender: is always the address where the current (external) function call came from.
buyer: entity that receives funds from seller once the seller reveals the secret
seller: entity that contributes funds to the buyer by revealing the secret or refunds after expiration
secret: random number chosen by the seller, revealed to allow the buyer to redeem the funds
secretHash: hash of the secret, used in the construction of HTLC
expiration: timestamp the determines when seller and buyer can redeem
now: current block timestamp



The msg.sender, transfers funds to the smart contract while deploying

constructor (bytes32 _secretHash, uint256 _expiration, address _buyer) public payable {



The msg.sender, transfer funds from the contract to the buyer

SHOULD throw if hash of secret

SHOULD throw if now is greater than expiration

Note secret can be any bytesize, but that should be specified by the two parties before the HTLC is initiated. The recommended size is 32 bytes

function claim (bytes32 _secret) public {


The msg.sender, transfer funds from the contract to the seller

SHOULD throw if now less than or equal to expiration

function refund () public {


ERC 1630 is compatible with BIP 199 for atomic swaps with Bitcoin and other HTLC compatible chains.


This implementation is a simple example of a HTLC using Solidity

contract ETHSwap {
  bytes32 secretHash;
  uint256 expiration;
  address buyer;
  address seller;

  constructor (bytes32 _secretHash, uint256 _expiration, address _buyer) public payable {
    secretHash = _secretHash;
    expiration = _expiration;
    buyer = _buyer;
    seller = msg.sender;

  function claim (bytes32 _secretHash) public {
    require(sha256(_secretHash) == secretHash);
    require(now <= expiration);

  function expire () public {
    require(now > expiration);

Note other hash functions can also be used, such as keccak256, ripemd160. However both parties should specify the hash function to be used before the HTLC is initialized.

Also if the HTLC is being used for the purpose of atomic swaps, both parties should ensure that the hash function specified is available on both chains (i.e. keccak256 is not available on Bitcoin)

Optimized Implementation

This is an optimized HTLC with significant gas saving features

Liquality Atomic Swaps

// Constructor
PUSH1 {dataSize}
PUSH1 0b
PUSH1 00
PUSH1 00

// Contract
PUSH1 20

// Get secret
PUSH1 00

// SHA256
PUSH1 21
PUSH1 00
PUSH1 02
PUSH1 48

// Validate with secretHash
PUSH32 {secretHashEncoded}
PUSH1 21
AND (to make sure CALL succeeded)
// Redeem if secret is valid
PUSH1 {redeemDestinationEncoded}

// Check time lock
// Refund if timelock passed
PUSH1 {refundDestinationEncoded}


// Redeem self destruct
PUSH20 {recipientAddressEncoded}

// Refund self destruct
PUSH20 {refundAddressEncoded}

Optimized Implementation Definitions


112 + expiration size

112 is the size of the contract in bytes after the constructor


hash of secret generated by seller


66 + expiration size

66 is the number of bytes between Contract and Redeem self destruct


89 + expiration size

89 is the number of bytes between Contract and Refund self destruct


bytecode length of expiration


expiration time encoded hex


buyer address


seller address

Optimized Implementation Rationale


deploys the contract, using the datasize which is the bytecode size of the rest of the contract


compute (Keccak-256) hash of contract address

Get secret

copy input data of secret in the current environment to memory

SHA 256

hashes the secret in memory

Validate with SecretHash

checks if secretHash is equal to hash of secret provided

Redeem if secret is valid

jump to the redeem self destruct section of the contract

Check timelock

check block's timestamp is greater than expiration

Refund if timelock passed

jump to the refund self destruct section of the contract

Redeem self destruct

pushes buyer address to the stack, which is passed to SELFDESTRUCT which sends funds to the buyer, and destroys the contract

Refund self destruct

pushes seller address to the stack, which is passed to SELFDESTRUCT which sends funds to the seller, and destroys the contractal


Copyright and related rights waived via CC0.

mattBlackDesign added some commits Nov 29, 2018

@mattBlackDesign mattBlackDesign force-pushed the mattBlackDesign:EIP-1630 branch from 7e02106 to 2415935 Nov 29, 2018


This comment has been minimized.


nicksavers commented Nov 30, 2018

Hi @mattBlackDesign thanks for the proposal

  • Where is the discussions-to field?
  • I suppose Rational should be Rationale?
  • Implementation Definitions and Rationale could use some better formatting.
  • Compatibility isn't rather uninformative. It's nice to see a reference, but what should we conclude from that? There is a category called Backwards Compatibility in the EIP template, is that what you were going for?

This comment has been minimized.

mattBlackDesign commented Nov 30, 2018

Thanks for the comments @nicksavers

  • discussions-to field added with link to ERC 1630 Discussion
  • Rationale typo fixed
  • Improved formatting for Implementation Definitions and Rationale
  • The compatibility example refers to atomic swaps. Added some more details to understand Compatibility
  • Added Solidity example

@mattBlackDesign mattBlackDesign changed the title from ERC 1630 to ERC 1630 - Hashed Time-Locked Contract Standard Nov 30, 2018

mattBlackDesign added some commits Nov 30, 2018


This comment has been minimized.

vietlq commented Dec 4, 2018

Great stuff! Please avoid the word “suicide” for mental health benefit. Many EIPs and the EVM opcode changed terminology for that matter.


This comment has been minimized.

mattBlackDesign commented Dec 5, 2018

Thanks for the heads up @vietlq. Removed suicide from the EIP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment