diff --git a/EIPS/eip-1630.md b/EIPS/eip-1630.md new file mode 100644 index 00000000000000..44b3a847c9dfce --- /dev/null +++ b/EIPS/eip-1630.md @@ -0,0 +1,265 @@ +--- +eip: 1630 +title: Hashed Time-Locked Contracts +author: Matthew Black , TingWei Liu , Liquality Team +status: Draft +discussions-to: https://github.com/ethereum/EIPs/issues/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. + +## Abstract + +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. + +## Motivation + +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](https://en.bitcoin.it/wiki/Atomic_swap) + +## Definitions + +`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 + +## Specification + +### Constructor + +The `msg.sender`, transfers funds to the smart contract while deploying + +```solidity +constructor (bytes32 _secretHash, uint256 _expiration, address _buyer) public payable; +``` + +### Methods + +#### claim + +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 + +```solidity +function claim (bytes32 _secret) public; +``` + +#### refund + +The `msg.sender`, transfer funds from the contract to the `seller` + +SHOULD throw if `now` less than or equal to `expiration` + +```solidity +function refund () public; +``` + +## Backwards Compatibility + +ERC-1630 is compatible with [BIP 199](https://github.com/bitcoin/bips/blob/master/bip-0199.mediawiki) for [atomic swaps](https://en.bitcoin.it/wiki/Atomic_swap) with Bitcoin and other HTLC compatible chains. + +## Implementation + +This implementation is a simple example of a HTLC using Solidity + +```solidity +pragma solidity ^0.5.10; + +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 _secret) public { + require(sha256(abi.encodePacked(_secret)) == secretHash); + require(now <= expiration); + buyer.transfer(address(this).balance); + } + + function refund () public { + require(now > expiration); + seller.transfer(address(this).balance); + } +} +``` + +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](https://github.com/liquality/chainabstractionlayer/blob/master/src/providers/ethereum/EthereumSwapProvider.js#L8) + +``` +// Constructor +PUSH1 {dataSize} +DUP1 +PUSH1 0b +PUSH1 00 +CODECOPY +PUSH1 00 +RETURN + +// Contract +PUSH1 20 + +// Get secret +DUP1 +PUSH1 00 +DUP1 +CALLDATACOPY + +// SHA256 +PUSH1 21 +DUP2 +PUSH1 00 +DUP1 +PUSH1 02 +PUSH1 48 +CALL + +// Validate with secretHash +PUSH32 {secretHashEncoded} +PUSH1 21 +MLOAD +EQ +AND (to make sure CALL succeeded) +// Redeem if secret is valid +PUSH1 {redeemDestinationEncoded} +JUMPI + +// Check time lock +PUSH{expirationSize} +{expirationEncoded} +TIMESTAMP +GT +// Refund if timelock passed +PUSH1 {refundDestinationEncoded} +JUMPI + +INVALID + +// Redeem self destruct +JUMPDEST +PUSH20 {recipientAddressEncoded} +SELFDESTRUCT + +// Refund self destruct +JUMPDEST +PUSH20 {refundAddressEncoded} +SELFDESTRUCT +``` + +### Optimized Implementation Definitions + +#### dataSize + +`112` + expiration size + +`112` is the size of the contract in bytes after the constructor + +#### secretHash + +hash of secret generated by seller + +#### redeemDestination + +66 + expiration size + +66 is the number of bytes between Contract and Redeem self destruct + +#### refundDestination + +89 + expiration size + +89 is the number of bytes between Contract and Refund self destruct + +#### expirationSize + +bytecode length of expiration + +#### expiration + +expiration time encoded hex + +#### recipientAddress + +buyer address + +#### refundAddress + +seller address + +*** + +### Optimized Implementation Rationale + +#### Constructor + +deploys the contract, using the datasize which is the bytecode size of the rest of the contract + +#### 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 +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).