// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; contract LivenessBondEscrow { address public owner; address public counterparty; uint256 public deadline; uint256 public cancelTimestamp; uint256 public bond; uint256 public constant PING_INTERVAL = 1 days; uint256 public constant CANCEL_DELAY = 24 hours; event Pinged(address indexed owner, uint256 newDeadline); event CancellationRequested(address indexed owner, uint256 when); event Claimed(address indexed counterparty, uint256 amount); event Withdrawn(address indexed owner, uint256 amount); constructor(address _counterparty) payable { require(_counterparty != address(0)); require(_counterparty != msg.sender); require(msg.value > 0); owner = msg.sender; counterparty = _counterparty; bond = msg.value; deadline = block.timestamp + PING_INTERVAL; } modifier onlyOwner() { require(msg.sender == owner); _; } modifier onlyCounterparty() { require(msg.sender == counterparty); _; } function ping() external onlyOwner { require(block.timestamp <= deadline); deadline = block.timestamp + PING_INTERVAL; emit Pinged(msg.sender, deadline); } function requestCancellation() external onlyOwner { require(block.timestamp <= deadline); require(cancelTimestamp == 0); cancelTimestamp = block.timestamp; emit CancellationRequested(msg.sender, cancelTimestamp); } function claim(address payable recipient) external onlyCounterparty { require(block.timestamp > deadline); require(recipient != address(0)); uint256 amount = bond; require(amount > 0); bond = 0; (bool ok, ) = recipient.call{value: amount}(""); require(ok); emit Claimed(msg.sender, amount); } function withdraw(address payable recipient) external onlyOwner { require(cancelTimestamp != 0); require(block.timestamp >= cancelTimestamp + CANCEL_DELAY); require(block.timestamp <= deadline); require(recipient != address(0)); uint256 amount = bond; require(amount > 0); bond = 0; (bool ok, ) = recipient.call{value: amount}(""); require(ok); emit Withdrawn(msg.sender, amount); } }