HashLockedMilestoneEscrow
hashlockedmilestoneescrow · conditional-settlement · 1623 B runtime · funds-movement
scores
- usefulness: 80
- safety: 90
- liveness: 80
- authenticity: 100
- extensibility: 60
- bytecodeDiscipline: 90
- practical: 82
source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract HashLockedMilestoneEscrow {
error Unauthorized();
error InvalidState();
error TransferFailed();
address public immutable creator;
address public immutable agent;
uint256 public immutable share;
uint256 public immutable deadline;
bytes32[] private milestoneHashes;
uint256 public currentMilestone;
event MilestoneReleased(uint256 indexed index, bytes preimage, uint256 amount);
event Refunded(uint256 amount);
constructor(
address _agent,
bytes32[] memory _milestoneHashes,
uint256 _deadline
) payable {
if (_milestoneHashes.length == 0) revert InvalidState();
if (_deadline <= block.timestamp) revert InvalidState();
if (msg.value == 0) revert InvalidState();
if (msg.value % _milestoneHashes.length != 0) revert InvalidState();
creator = msg.sender;
agent = _agent;
share = msg.value / _milestoneHashes.length;
deadline = _deadline;
milestoneHashes = _milestoneHashes;
}
function reveal(bytes calldata preimage) external {
if (msg.sender != agent) revert Unauthorized();
if (currentMilestone >= milestoneHashes.length) revert InvalidState();
if (block.timestamp > deadline) revert InvalidState();
if (keccak256(preimage) != milestoneHashes[currentMilestone]) revert InvalidState();
uint256 amount = share;
currentMilestone++;
(bool ok, ) = payable(msg.sender).call{value: amount}("");
if (!ok) revert TransferFailed();
emit MilestoneReleased(currentMilestone - 1, preimage, amount);
}
function refund() external {
if (msg.sender != creator) revert Unauthorized();
if (block.timestamp <= deadline) revert InvalidState();
uint256 amount = share * (milestoneHashes.length - currentMilestone);
if (amount == 0) revert InvalidState();
currentMilestone = milestoneHashes.length;
(bool ok, ) = payable(msg.sender).call{value: amount}("");
if (!ok) revert TransferFailed();
emit Refunded(amount);
}
}published
published on testnet · 0xF672f6fd868550235280a90fc90be8654dF6227d · tx 0xae68d717977c3ba1… · base (84532) · testnet · source as deployed