HTLC的solidity代码

solidity实现HTLC合约

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract HTLC{
    
    

    struct LockHTLC {
    
    
        address payable sender;
        address payable receiver;
        uint amount;
        bytes32 hashlock; //即H=hash(s)
        uint timelock; //锁定的时间
        bool withdrawn;
        bool refunded;
        bytes preimage;
    }

    mapping (bytes32 => LockHTLC) contracts;

    string public version="1.0";


    event NewHTLCLog(bytes32 indexed htlcId,address indexed sender,address indexed receiver,uint amount,bytes32 hashlock,uint timelock);
    event HTLCWithdrawLog(bytes32 indexed htlcId);   
    event HTLCRefundLog(bytes32 indexed htlcId);
 

    //要求锁定资产大于0
    modifier fundsSent() {
    
    
        require(msg.value > 0, "msg.value must be > 0");
        _;
    }

    //要求解锁时间必须大于目前
    modifier futureTimelock(uint _time) {
    
    
        require(_time > block.timestamp, "timelock time must be in the future");
        _;
    }

    //要求合约必须存在
     modifier contractExists(bytes32 _htlcId) {
    
    
        require(haveContract(_htlcId), "htlcId does not exist");
        _;
    }

    //要求密钥匹配哈希锁
    modifier hashlockMatches(bytes32 _htlcId, bytes memory _x) {
    
    
        require(
            contracts[_htlcId].hashlock == sha256(abi.encodePacked(_x)),
            "hashlock hash does not match"
        );
        _;
    }

    //判断是否可以取
     modifier withdrawable(bytes32 _htlcId) {
    
    
        require(contracts[_htlcId].receiver == msg.sender, "withdrawable: not receiver");
        require(contracts[_htlcId].withdrawn == false, "withdrawable: already withdrawn");
        require(contracts[_htlcId].timelock > block.timestamp, "withdrawable: timelock time must be in the future");
        _;
    }

    //判断是否可以退回资产
    modifier refundable(bytes32 _htlcId) {
    
    
        require(contracts[_htlcId].sender == msg.sender, "refundable: not sender");
        require(contracts[_htlcId].refunded == false, "refundable: already refunded");
        require(contracts[_htlcId].withdrawn == false, "refundable: already withdrawn");
        require(contracts[_htlcId].timelock <= block.timestamp, "refundable: timelock not yet passed");
        _;
    }



    //新建一个HTLC实例,相当于资产锁定步骤(会传递接收人,哈希锁,时间锁,和转账金额msg.value)
    function newHTLC(address payable _receiver,bytes32 _hashlock, uint _timelock) external payable fundsSent futureTimelock(_timelock)  returns (bytes32 htlcId) {
    
    
        //计算HTLC实例的ID
        htlcId=sha256(abi.encodePacked(msg.sender,_receiver,msg.value,_hashlock,_timelock));

        //如果ID存在
        if(haveContract(htlcId)){
    
    
            //revert()函数用于在合约中显式地回滚交易,并将状态恢复到调用该函数之前的状态。与require类型
            revert("Contract already exists");
        }

        //创建并保存该HTLC实例
        contracts[htlcId]=LockHTLC(payable(msg.sender), _receiver, msg.value, _hashlock, _timelock,false,false,'0x0');

        emit NewHTLCLog(htlcId,msg.sender,_receiver,msg.value,_hashlock,_timelock);

    }

    //取钱,相当于解锁资产
    function withdraw(bytes32 _htlcId,bytes calldata _preimage) external contractExists(_htlcId) hashlockMatches(_htlcId,_preimage) withdrawable(_htlcId) returns (bool){
    
    
        
        //storage使得c是一个对存储在区块链上的数据进行直接引用的变量,而不是创建一个新的拷贝。这意味着对c的修改将直接影响到存储在区块链上的合约数据。
        LockHTLC storage c = contracts[_htlcId];
        c.preimage = _preimage;
        c.withdrawn = true;
        c.receiver.transfer(c.amount);
        emit HTLCWithdrawLog(_htlcId);
        return true;
    }

    //如果超时没有人解锁资产,资产锁定人可以将这些锁定的资产退回来
     function refund(bytes32 _htlcId) external contractExists(_htlcId) refundable(_htlcId) returns (bool){
    
    
        LockHTLC storage c = contracts[_htlcId];
        c.refunded = true;
        c.sender.transfer(c.amount);
        emit HTLCRefundLog(_htlcId);
        return true;
     }

    //获取一个HTLC实例的细节
     function getContract(bytes32 _htlcId)  public view  returns(address sender,address receiver,uint amount,bytes32 hashlock,uint timelock,bool withdrawn,bool refunded,bytes memory preimage){
    
    
         if (haveContract(_htlcId) == false){
    
    
            bytes memory _preimage = '0x0';
            return (address(0), address(0), 0, 0, 0, false, false,  _preimage);
        }
        LockHTLC storage c = contracts[_htlcId];
        return (
            c.sender,
            c.receiver,
            c.amount,
            c.hashlock,
            c.timelock,
            c.withdrawn,
            c.refunded,
            c.preimage
        );
     }
    //查询htlcID是否已经存在
    function haveContract(bytes32 _htlcId) internal view returns (bool exists){
    
    
        exists = (contracts[_htlcId].sender != address(0));
    }
}

猜你喜欢

转载自blog.csdn.net/qxjswl/article/details/133272577
今日推荐