Description:
Smart contract deployed on Ethereum with Factory features.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"contracts/HTLC.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/**
* @title HashedTimelockContract (HTLC)
* @dev Implementation of Hashed Timelock Contracts for atomic swaps
* @notice This contract enables trustless atomic swaps using hash locks and time locks
*/
contract HTLC {
struct LockContract {
address payable sender;
address payable receiver;
uint256 amount;
bytes32 hashlock;
uint256 timelock; // UNIX timestamp
bool withdrawn;
bool refunded;
bytes32 preimage;
}
mapping(bytes32 => LockContract) public contracts;
event LogHTLCNew(
bytes32 indexed contractId,
address indexed sender,
address indexed receiver,
uint256 amount,
bytes32 hashlock,
uint256 timelock
);
event LogHTLCWithdraw(bytes32 indexed contractId);
event LogHTLCRefund(bytes32 indexed contractId);
modifier contractExists(bytes32 _contractId) {
require(haveContract(_contractId), "Contract does not exist");
_;
}
modifier hashlockMatches(bytes32 _contractId, bytes32 _preimage) {
require(
contracts[_contractId].hashlock == sha256(abi.encodePacked(_preimage)),
"Hashlock does not match"
);
_;
}
modifier withdrawable(bytes32 _contractId) {
require(contracts[_contractId].receiver == msg.sender, "Withdrawable: not receiver");
require(contracts[_contractId].withdrawn == false, "Withdrawable: already withdrawn");
require(contracts[_contractId].refunded == false, "Withdrawable: already refunded");
require(contracts[_contractId].timelock > block.timestamp, "Withdrawable: timelock expired");
_;
}
modifier refundable(bytes32 _contractId) {
require(contracts[_contractId].sender == msg.sender, "Refundable: not sender");
require(contracts[_contractId].refunded == false, "Refundable: already refunded");
require(contracts[_contractId].withdrawn == false, "Refundable: already withdrawn");
require(contracts[_contractId].timelock <= block.timestamp, "Refundable: timelock not expired");
_;
}
/**
* @dev Create a new HTLC
* @param _receiver The recipient address
* @param _hashlock The hash lock (sha256)
* @param _timelock The time lock (UNIX timestamp)
* @return contractId The unique identifier for this contract
*/
function newContract(
address payable _receiver,
bytes32 _hashlock,
uint256 _timelock
) external payable returns (bytes32 contractId) {
require(msg.value > 0, "Amount must be greater than 0");
require(_timelock > block.timestamp, "Timelock must be in the future");
require(_receiver != address(0), "Invalid receiver address");
contractId = keccak256(
abi.encodePacked(
msg.sender,
_receiver,
msg.value,
_hashlock,
_timelock
)
);
// Reject if a contract already exists with the same parameters
require(!haveContract(contractId), "Contract already exists");
contracts[contractId] = LockContract(
payable(msg.sender),
_receiver,
msg.value,
_hashlock,
_timelock,
false,
false,
0x0
);
emit LogHTLCNew(
contractId,
msg.sender,
_receiver,
msg.value,
_hashlock,
_timelock
);
}
/**
* @dev Withdraw funds from an HTLC
* @param _contractId The contract identifier
* @param _preimage The preimage of the hashlock
*/
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;
}
/**
* @dev Refund funds from an expired HTLC
* @param _contractId The contract identifier
*/
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;
}
/**
* @dev Get contract details
* @param _contractId The contract identifier
*/
function getContract(bytes32 _contractId)
external
view
returns (
address sender,
address receiver,
uint256 amount,
bytes32 hashlock,
uint256 timelock,
bool withdrawn,
bool refunded,
bytes32 preimage
)
{
if (!haveContract(_contractId)) {
return (address(0), address(0), 0, 0, 0, false, false, 0);
}
LockContract storage c = contracts[_contractId];
return (
c.sender,
c.receiver,
c.amount,
c.hashlock,
c.timelock,
c.withdrawn,
c.refunded,
c.preimage
);
}
/**
* @dev Check if a contract exists
* @param _contractId The contract identifier
*/
function haveContract(bytes32 _contractId) internal view returns (bool exists) {
exists = (contracts[_contractId].sender != address(0));
}
}
"
}
},
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}
}}
Submitted on: 2025-10-10 13:27:45
Comments
Log in to comment.
No comments yet.