Since the glorious years of Bitcoin has opened a new blockchain era with hundreds of different types of blockchain, typically ETH, NEO, TRON, … Each blockchain was born to improve a certain weakness of the tissue. old blockchain models such as increasing speed, increasing applicability, being programmable, saving resources. Unlocking the promising growth possibilities of blockchain adoption in our daily lives. However, it is development in that direction that leads to blockchains being isolated from each other. Although it is completely possible to put tokens on centralized exchanges for exchange, it is more centralized than accounts because such a management platform is so insecure. The community dreamed of a decentralized exchange where every blockchain platform could be exchanged without any third party intervening, so the Hashed TimeLock Contract was born.
Problem
What if two people want to exchange 2 items? Person A sends person B and person B sends person A. So what if person B receives it and then explodes? Another way is to ask a 3rd person, when both people A and B give the item to the 3rd person then the 3rd person will give it to both people B and A. But what if the third person took it and ran away? And the current situation, the way of trading in some centralized exchanges like Binance Okex is like that. That is why people want a decentralized floor for a long time. Surely some of you will be wondering, does not writing a smart contract on eth solve the 3rd person problem? . Yes, but what if the user wants to exchange between two different types of blockchain? And the hashed timelock contract is an answer to this question.
What is Hashed TimeLock Contract?
Hashed TimeLock Contract (HTLC) is a type of smart contract that is used to exchange different coins and tokens without the need for a third party or worrying about scam risks. By allowing transactions within a certain time limit. More specifically, the recipient of the HTLC transaction must confirm the payment by sending a piece of encryption key to authenticate within a specified timeframe (in block numbers). If the receiver declines or does not request payment, the amount will be returned to the original sender.
There are two important elements in HTLC: Hashlock and timelock:
Hashlock : The person who first creates one creates a secret and then uses an encryption function to hash out a code called a hashlock.
Timelock : is a function that restricts transactions to a specific time (calculated by the number of blocks).
Flow of operation
Our scenario will include two people Alice who holds Ethereum and Bob who holds Bitcoin. These two will exchange Eth and BTC without having to trust each other. This process includes two parties and four accounts, so the process will include:
Alice 2 accounts: An account that sends ETH and an account that receives BTC
Bob 2 accounts: Account sending BTC and account receiving ETH
The process will go as follows:
- Alice chooses a number or a random string of characters named secret and then uses a hash function to generate the hasklock
- Create a Lock on Eth contract, including necessary information such as hashlock, timelock, input amount, receiver, sender, …
- Send Bob that hashlock
- Bob also creates a Lock on BTC including the hachlock that Alice sent, timelock, input amount, receiver, sender, …
- Alice will use the secret to decrypt Bob’s Lock to receive BTC and the secret will be publicized on the network and Bob will know
- Bob uses the public secret to unlock Alice’s Lock and receive ETH
Demo
I will demo one-way code from ETH
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
pragma solidity <span class="token operator">^</span> <span class="token number">0.5</span> <span class="token number">.0</span> <span class="token punctuation">;</span> pragma experimental ABIEncoderV2 <span class="token punctuation">;</span> contract HashTimeLock <span class="token punctuation">{</span> <span class="token function">mapping</span> <span class="token punctuation">(</span> <span class="token parameter">bytes32</span> <span class="token operator">=></span> LockContract <span class="token punctuation">)</span> <span class="token keyword">public</span> contracts <span class="token punctuation">;</span> <span class="token comment">// / - WITHDRAWN</span> <span class="token comment">// INVALID - ACTIVE |</span> <span class="token comment">// - EXPIRED - REFUNDED</span> uint256 <span class="token keyword">public</span> constant <span class="token constant">INVALID</span> <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> <span class="token comment">// Uninitialized swap -> can go to ACTIVE</span> uint256 <span class="token keyword">public</span> constant <span class="token constant">ACTIVE</span> <span class="token operator">=</span> <span class="token number">1</span> <span class="token punctuation">;</span> <span class="token comment">// Active swap -> can go to WITHDRAWN or EXPIRED</span> uint256 <span class="token keyword">public</span> constant <span class="token constant">REFUNDED</span> <span class="token operator">=</span> <span class="token number">2</span> <span class="token punctuation">;</span> <span class="token comment">// Swap is refunded -> final state.</span> uint256 <span class="token keyword">public</span> constant <span class="token constant">WITHDRAWN</span> <span class="token operator">=</span> <span class="token number">3</span> <span class="token punctuation">;</span> <span class="token comment">// Swap is withdrawn -> final state.</span> uint256 <span class="token keyword">public</span> constant <span class="token constant">EXPIRED</span> <span class="token operator">=</span> <span class="token number">4</span> <span class="token punctuation">;</span> <span class="token comment">// Swap is expired -> can go to REFUNDED</span> struct LockContract <span class="token punctuation">{</span> uint256 inputAmount <span class="token punctuation">;</span> uint256 outputAmount <span class="token punctuation">;</span> uint256 expiration <span class="token punctuation">;</span> uint256 status <span class="token punctuation">;</span> bytes32 hashLock <span class="token punctuation">;</span> address payable sender <span class="token punctuation">;</span> address payable receiver <span class="token punctuation">;</span> string outputNetwork <span class="token punctuation">;</span> string outputAddress <span class="token punctuation">;</span> <span class="token punctuation">}</span> event <span class="token function">Withdraw</span> <span class="token punctuation">(</span> bytes32 indexed id <span class="token punctuation">,</span> bytes32 secret <span class="token punctuation">,</span> bytes32 hashLock <span class="token punctuation">,</span> address indexed sender <span class="token punctuation">,</span> address indexed receiver <span class="token punctuation">)</span> <span class="token punctuation">;</span> event <span class="token function">Refund</span> <span class="token punctuation">(</span> bytes32 indexed id <span class="token punctuation">,</span> bytes32 hashLock <span class="token punctuation">,</span> address indexed sender <span class="token punctuation">,</span> address indexed receiver <span class="token punctuation">)</span> <span class="token punctuation">;</span> event <span class="token function">NewContract</span> <span class="token punctuation">(</span> uint256 inputAmount <span class="token punctuation">,</span> uint256 outputAmount <span class="token punctuation">,</span> uint256 expiration <span class="token punctuation">,</span> bytes32 indexed id <span class="token punctuation">,</span> bytes32 hashLock <span class="token punctuation">,</span> address indexed sender <span class="token punctuation">,</span> address indexed receiver <span class="token punctuation">,</span> string outputNetwork <span class="token punctuation">,</span> string outputAddress <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">newContract</span> <span class="token punctuation">(</span> <span class="token parameter">uint256 outputAmount <span class="token punctuation">,</span> uint256 expiration <span class="token punctuation">,</span> bytes32 hashLock <span class="token punctuation">,</span> address payable receiver <span class="token punctuation">,</span> string calldata outputNetwork <span class="token punctuation">,</span> string calldata outputAddress</span> <span class="token punctuation">)</span> external payable <span class="token punctuation">{</span> address payable sender <span class="token operator">=</span> msg <span class="token punctuation">.</span> sender <span class="token punctuation">;</span> uint256 inputAmount <span class="token operator">=</span> msg <span class="token punctuation">.</span> value <span class="token punctuation">;</span> <span class="token function">require</span> <span class="token punctuation">(</span> expiration <span class="token operator">></span> block <span class="token punctuation">.</span> timestamp <span class="token punctuation">,</span> <span class="token string">'INVALID_TIME'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">require</span> <span class="token punctuation">(</span> inputAmount <span class="token operator">></span> <span class="token number">0</span> <span class="token punctuation">,</span> <span class="token string">'INVALID_AMOUNT'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> bytes32 id <span class="token operator">=</span> <span class="token function">sha256</span> <span class="token punctuation">(</span> abi <span class="token punctuation">.</span> <span class="token function">encodePacked</span> <span class="token punctuation">(</span> sender <span class="token punctuation">,</span> receiver <span class="token punctuation">,</span> inputAmount <span class="token punctuation">,</span> hashLock <span class="token punctuation">,</span> expiration <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">require</span> <span class="token punctuation">(</span> contracts <span class="token punctuation">[</span> id <span class="token punctuation">]</span> <span class="token punctuation">.</span> status <span class="token operator">==</span> <span class="token constant">INVALID</span> <span class="token punctuation">,</span> <span class="token string">"SWAP_EXISTS"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> contracts <span class="token punctuation">[</span> id <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">LockContract</span> <span class="token punctuation">(</span> inputAmount <span class="token punctuation">,</span> outputAmount <span class="token punctuation">,</span> expiration <span class="token punctuation">,</span> <span class="token constant">ACTIVE</span> <span class="token punctuation">,</span> hashLock <span class="token punctuation">,</span> sender <span class="token punctuation">,</span> receiver <span class="token punctuation">,</span> outputNetwork <span class="token punctuation">,</span> outputAddress <span class="token punctuation">)</span> <span class="token punctuation">;</span> emit <span class="token function">NewContract</span> <span class="token punctuation">(</span> inputAmount <span class="token punctuation">,</span> outputAmount <span class="token punctuation">,</span> expiration <span class="token punctuation">,</span> id <span class="token punctuation">,</span> hashLock <span class="token punctuation">,</span> sender <span class="token punctuation">,</span> receiver <span class="token punctuation">,</span> outputNetwork <span class="token punctuation">,</span> outputAddress <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">withdraw</span> <span class="token punctuation">(</span> <span class="token parameter">bytes32 id <span class="token punctuation">,</span> bytes32 secret</span> <span class="token punctuation">)</span> external <span class="token punctuation">{</span> LockContract storage c <span class="token operator">=</span> contracts <span class="token punctuation">[</span> id <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token function">require</span> <span class="token punctuation">(</span> c <span class="token punctuation">.</span> status <span class="token operator">==</span> <span class="token constant">ACTIVE</span> <span class="token punctuation">,</span> <span class="token string">"SWAP_NOT_ACTIVE"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">require</span> <span class="token punctuation">(</span> c <span class="token punctuation">.</span> expiration <span class="token operator">></span> block <span class="token punctuation">.</span> timestamp <span class="token punctuation">,</span> <span class="token string">"INVALID_TIME"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">require</span> <span class="token punctuation">(</span> c <span class="token punctuation">.</span> hashLock <span class="token operator">==</span> <span class="token function">sha256</span> <span class="token punctuation">(</span> abi <span class="token punctuation">.</span> <span class="token function">encodePacked</span> <span class="token punctuation">(</span> secret <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">,</span> <span class="token string">"INVALID_SECRET"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> c <span class="token punctuation">.</span> status <span class="token operator">=</span> <span class="token constant">WITHDRAWN</span> <span class="token punctuation">;</span> c <span class="token punctuation">.</span> receiver <span class="token punctuation">.</span> <span class="token function">transfer</span> <span class="token punctuation">(</span> c <span class="token punctuation">.</span> inputAmount <span class="token punctuation">)</span> <span class="token punctuation">;</span> emit <span class="token function">Withdraw</span> <span class="token punctuation">(</span> id <span class="token punctuation">,</span> secret <span class="token punctuation">,</span> c <span class="token punctuation">.</span> hashLock <span class="token punctuation">,</span> c <span class="token punctuation">.</span> sender <span class="token punctuation">,</span> c <span class="token punctuation">.</span> receiver <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">refund</span> <span class="token punctuation">(</span> <span class="token parameter">bytes32 id</span> <span class="token punctuation">)</span> external <span class="token punctuation">{</span> LockContract storage c <span class="token operator">=</span> contracts <span class="token punctuation">[</span> id <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token function">require</span> <span class="token punctuation">(</span> c <span class="token punctuation">.</span> status <span class="token operator">==</span> <span class="token constant">ACTIVE</span> <span class="token punctuation">,</span> <span class="token string">"SWAP_NOT_ACTIVE"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token function">require</span> <span class="token punctuation">(</span> c <span class="token punctuation">.</span> expiration <span class="token operator"><=</span> block <span class="token punctuation">.</span> timestamp <span class="token punctuation">,</span> <span class="token string">"INVALID_TIME"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> c <span class="token punctuation">.</span> status <span class="token operator">=</span> <span class="token constant">REFUNDED</span> <span class="token punctuation">;</span> c <span class="token punctuation">.</span> sender <span class="token punctuation">.</span> <span class="token function">transfer</span> <span class="token punctuation">(</span> c <span class="token punctuation">.</span> inputAmount <span class="token punctuation">)</span> <span class="token punctuation">;</span> emit <span class="token function">Refund</span> <span class="token punctuation">(</span> id <span class="token punctuation">,</span> c <span class="token punctuation">.</span> hashLock <span class="token punctuation">,</span> c <span class="token punctuation">.</span> sender <span class="token punctuation">,</span> c <span class="token punctuation">.</span> receiver <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">getStatus</span> <span class="token punctuation">(</span> <span class="token parameter">bytes32 <span class="token punctuation">[</span> <span class="token punctuation">]</span> memory ids</span> <span class="token punctuation">)</span> <span class="token keyword">public</span> view <span class="token function">returns</span> <span class="token punctuation">(</span> <span class="token parameter">uint256 <span class="token punctuation">[</span> <span class="token punctuation">]</span> memory</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> uint256 <span class="token punctuation">[</span> <span class="token punctuation">]</span> memory result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">uint256</span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">(</span> ids <span class="token punctuation">.</span> length <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token punctuation">(</span> uint256 index <span class="token operator">=</span> <span class="token number">0</span> <span class="token punctuation">;</span> index <span class="token operator"><</span> ids <span class="token punctuation">.</span> length <span class="token punctuation">;</span> index <span class="token operator">++</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> result <span class="token punctuation">[</span> index <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">getSingleStatus</span> <span class="token punctuation">(</span> ids <span class="token punctuation">[</span> index <span class="token punctuation">]</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> result <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">getSingleStatus</span> <span class="token punctuation">(</span> <span class="token parameter">bytes32 id</span> <span class="token punctuation">)</span> <span class="token keyword">public</span> view <span class="token function">returns</span> <span class="token punctuation">(</span> <span class="token parameter">uint256 result</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> LockContract memory tempContract <span class="token operator">=</span> contracts <span class="token punctuation">[</span> id <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> tempContract <span class="token punctuation">.</span> status <span class="token operator">==</span> <span class="token constant">ACTIVE</span> <span class="token operator">&&</span> tempContract <span class="token punctuation">.</span> expiration <span class="token operator"><</span> block <span class="token punctuation">.</span> timestamp <span class="token punctuation">)</span> <span class="token punctuation">{</span> result <span class="token operator">=</span> <span class="token constant">EXPIRED</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> result <span class="token operator">=</span> tempContract <span class="token punctuation">.</span> status <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Contract will include 3 main functions which are newContract , withdraw , refund and in addition 2 functions check status of Lock
- newContract: this is the function to create a Lock with the necessary parameters. After the creation is complete, it will create a NewContract public emit on the network
- withdraw: this is a function for receiving users to enter Lock id and secret. First check the time to see if the time has expired, then use the function sha256 hash and compare vs hashlock if it is correct, the transaction will be done and then public private key via emit.
- refund: This function is only run when the time is over but when the Lock vs the purpose is created for the creator to withdraw money
Contract will consist of 5 positions
- INVALID: This is the state in which contracts [id] already existed. Since the id is taken as the hash of sender, receiver, inputAmount, hashLock, expiration , it can still match. And if the same, it will not be able to create Lock
- ACTIVE: this is the state for which contracts [id] are valid.
- WITHDRAWN: after the receiver withdraws money, Lock will move to withdrawn
- EXPIRED: this is the status of the recipient who did not withdraw and has exceeded the specified time period (expiration)
- REFUNDED: Only if the contract is expired, the creator can go back and withdraw his money and after the withdrawal is completed, the Lock will be refunded.
In addition, there are 2 functions to check status as well as 3 emit to catch the events in the contract. The most important is that 2 emits are NewContract and withdrawn because newContract will public Id of Lock and withdrawn will public secret of the creator on the network.
summary
I just explained a bridge from eth, and the BTC side is likewise still needing 3 basic functions: newContract, withdraw and refund and comply with the rules of time as well as having public events on the network when someone. manipulation . In the next article I will write about Market Maker so that when combined, we have a decentralized floor vs heart, htlc.