2. 基于哈希时间锁的跨链原子交换
任务说明
本案例实现一个基于哈希时间锁(HTLC)的跨链原子交换合约。目标是在两条独立链(链A与链B)上分别部署HTLC合约,使Alice与Bob能够安全交换各自链上的代币,且保证整个过程要么双方都获得对方资产,要么双方都保留自己资产,不存在中间状态导致一方受损。
HTLC核心机制
HTLC通过哈希锁与时间锁两个条件约束资金提取:
- 哈希锁:资金提取方需提供与锁定哈希值匹配的原像(preimage)。该原像由发起方Alice生成,并作为两条链上合约共用的解锁密钥。
- 时间锁:若超时未提取,资金自动退还至原锁定人。两条链上的时间锁需设置不同时长,确保退款路径安全(链A先到期,链B后到期)。
合约实现(Solidity)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract HTLC {
enum State { ACTIVE, COMPLETED, REFUNDED }
address public sender;
address public receiver;
bytes32 public hashLock;
uint256 public timeLock;
uint256 public amount;
State public state;
event Locked(address indexed sender, address indexed receiver, uint256 amount, bytes32 hashLock);
event Claimed(address indexed claimer, bytes32 preimage);
event Refunded(address indexed sender);
constructor(address _receiver, bytes32 _hashLock, uint256 _timeLock) payable {
require(msg.value > 0, "Amount must be > 0");
require(_receiver != address(0), "Invalid receiver");
sender = msg.sender;
receiver = _receiver;
hashLock = _hashLock;
timeLock = _timeLock;
amount = msg.value;
state = State.ACTIVE;
emit Locked(sender, receiver, amount, hashLock);
}
// 接收方凭原像提取资金
function claim(bytes32 _preimage) external {
require(state == State.ACTIVE, "Not active");
require(msg.sender == receiver, "Only receiver can claim");
require(sha256(abi.encodePacked(_preimage)) == hashLock, "Invalid preimage");
state = State.COMPLETED;
emit Claimed(msg.sender, _preimage);
(bool sent, ) = receiver.call{value: amount}("");
require(sent, "Transfer failed");
}
// 超时后原锁定人取回资金
function refund() external {
require(state == State.ACTIVE, "Not active");
require(msg.sender == sender, "Only sender can refund");
require(block.timestamp > timeLock, "Timelock not expired");
state = State.REFUNDED;
emit Refunded(sender);
(bool sent, ) = sender.call{value: amount}("");
require(sent, "Transfer failed");
}
// 查询当前时间锁剩余时间(用于链下监控)
function getRemainingTime() external view returns (uint256) {
if (block.timestamp >= timeLock) return 0;
return timeLock - block.timestamp;
}
}
原子交换流程
以下时序图展示两条链上HTLC合约的完整交互过程:
部署与验证
前置条件:需要两条独立链环境(如以太坊测试链与比特币测试网,或两条EVM兼容链)。本案例以Solidity合约演示HTLC逻辑,实际跨链部署时需在两条链上分别执行。
// 部署脚本(使用ethers.js)
// 链A:Alice部署,锁定10 ETH给Bob,时间锁T1 = 当前时间 + 24小时
// 链B:Bob部署,锁定10 BTC给Alice,时间锁T2 = 当前时间 + 48小时
// 1. Alice生成原像
const preimage = crypto.randomBytes(32);
const hashLock = ethers.utils.sha256(preimage);
// 2. Alice在链A部署
const contractA = await HTLC.deploy(bobAddress, hashLock, T1, { value: parseEther("10") });
// 3. Bob验证链A合约参数后,在链B部署
const contractB = await HTLC.deploy(aliceAddress, hashLock, T2, { value: parseEther("10") });
// 4. Alice在链B上claim
await contractB.claim(preimage);
// 5. Bob从链B交易中获取preimage,在链A上claim
await contractA.claim(preimage);
验证方法:
- 部署后检查两条链上合约的
state均为ACTIVE,锁定金额正确; - Alice调用链B合约的
claim(preimage),交易成功后检查链B合约状态为COMPLETED,Alice余额增加; - Bob从链B的claim交易中提取preimage,调用链A合约的
claim(preimage),交易成功后检查链A合约状态为COMPLETED,Bob余额增加; - 若在T1后、T2前Bob未claim,Alice可调用链A合约的
refund()取回资金;若T2后Alice未claim,Bob可调用链B合约的refund()取回资金。
判定标准:两条链上的合约最终状态均为COMPLETED(正常交换)或均为REFUNDED(超时退款),不存在一条链COMPLETED而另一条链REFUNDED的不一致状态,即满足原子性。