Skip to content

Latest commit

 

History

History
 
 

README.md

HTLC 介绍

哈希锁定, 全称为哈希时间锁定合约, 英文为 HTLC(Hash TimeLock Contract), 是解决跨链的一种技术方案. 指在智能合约的基础上, 让双方先锁定资产, 如果都在规定的时间内输入正确哈希值的原值, 即可完成交易.
哈希锁定的实现的两个条件, 一个是哈希锁, 一个是时间锁, 必须同时满足这两个条件, 才能完成交易, 如果不能满足条件, 代币会自动返回, 不收手续费.

原理介绍

小白生成随机数, 并发送 Hash 给小黑, 同时小白在它链 A 上锁定币, 设定交易的时间, 小黑收到 Hash 后, 在它链 B 上锁定币, 也设置时间限制. 小白看到小黑的锁定后, 在规定时间内, 发送包含之前的随机数的认领协议给小黑, 小黑收到后在规定时间内给出哈希值后, 锁定的数字货币立即释放, 完成交易.

哈希锁定有什么优缺点

哈希锁定的优点: 实现了跨链资产的交换, 可以不用公证人. 哈希锁定的缺点: 没有实现跨链资产的转移, 更不能实现跨链合约的执行.

合约主要功能解析

HashedTimelock

  • newContract
    开启一个 Hash 时间锁, 同时存入 ETH, 付款人各自在不同的链上调用, _receiver 需要传入收款人的地址.
    /**
     * @dev Sender sets up a new hash time lock contract depositing the ETH and
     * providing the reciever lock terms.
     *
     * @param _receiver Receiver of the ETH.
     * @param _hashlock A sha-2 sha256 hash hashlock.
     * @param _timelock UNIX epoch seconds time that the lock expires at.
     *                  Refunds can be made after this time.
     * @return contractId Id of the new HTLC. This is needed for subsequent
     *                    calls.
     */
function newContract(address payable _receiver, bytes32 _hashlock, uint _timelock)
        external
        payable
        fundsSent
        futureTimelock(_timelock)
        returns (bytes32 contractId)
    {
        contractId = sha256(
            abi.encodePacked(
                msg.sender,
                _receiver,
                msg.value,
                _hashlock,
                _timelock
            )
        );

        // Reject if a contract already exists with the same parameters. The
        // sender must change one of these parameters to create a new distinct
        // contract.
        if (haveContract(contractId))
            revert("Contract already exists");

        contracts[contractId] = LockContract(
            msg.sender,
            _receiver,
            msg.value,
            _hashlock,
            _timelock,
            false,
            false,
            0x0
        );

        emit LogHTLCNew(
            contractId,
            msg.sender,
            _receiver,
            msg.value,
            _hashlock,
            _timelock
        );
    }
  • withdraw
    收款人调用. 传入 contractID 和 Hash 对应的原始值后面, 收款人就可以收到对应的款项.
    /**
     * @dev Called by the receiver once they know the preimage of the hashlock.
     * This will transfer the locked funds to their address.
     *
     * @param _contractId Id of the HTLC.
     * @param _preimage sha256(_preimage) should equal the contract hashlock.
     * @return bool true on success
     */
function withdraw(bytes32 _contractId, bytes32 _preimage)
        external
        contractExists(_contractId)
        hashlockMatches(_contractId, _preimage)
        withdrawable(_contractId)
        returns (bool)
    {
        LockContract storage c = contracts[_contractId];
        c.preimage = _preimage;
        c.withdrawn = true;
        c.receiver.transfer(c.amount);
        emit LogHTLCWithdraw(_contractId);
        return true;
    }
  • refund
    付款人调用. 当收款人在规定的时间内没有调用 withdraw 提取款项时, 收款人可以调用这个 refund 方法把款项取回.
    /**
     * @dev Called by the sender if there was no withdraw AND the time lock has
     * expired. This will refund the contract amount.
     *
     * @param _contractId Id of HTLC to refund from.
     * @return bool true on success
     */
    function refund(bytes32 _contractId)
        external
        contractExists(_contractId)
        refundable(_contractId)
        returns (bool)
    {
        LockContract storage c = contracts[_contractId];
        c.refunded = true;
        c.sender.transfer(c.amount);
        emit LogHTLCRefund(_contractId);
        return true;
    }

HashedTimelockERC20 和 HashedTimelockERC721

这两个合约功能和 HashedTimelock 功能相同, 区别在于 HashedTimelock 存入的是 ETH, HashedTimelockERC20 和 HashedTimelockERC721 存入是 ERC20 和 ERC721, 同时在存入前需要预先授权 approve 给 HashedTimelockERC20 和 HashedTimelockERC721 合约.

测试步骤

  • 安装依赖
yarn
  • 测试 HashedTimelock
npx hardhat test/HashedTimelock.js

参考文档