What it does:
Holds patient payments in escrow for telemedicine sessions and automatically releases funds to healthcare providers once the consultation is completed.
Why it matters:
Protects both patients and providers by ensuring fair payment, reducing disputes, and enforcing transparent, milestone-based healthcare service delivery.
How it works:
Telemedicine session terms are defined at deployment
Patient deposits consultation fee into escrow
Provider conducts the remote medical session
Provider marks session as completed
Patient confirms service completion or timeout triggers release
Escrow automatically pays the provider or refunds if conditions fail
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title TelemedicinePaymentEscrow
* @author Nam
* @notice Escrow contract for telemedicine consultation payments
*/
contract TelemedicinePaymentEscrow {
// -------------------- ROLES --------------------
address public patient;
address public provider;
// -------------------- PAYMENT TERMS --------------------
uint256 public consultationFee;
uint256 public sessionDeadline; // timestamp
uint256 public confirmationTimeout; // seconds
// -------------------- STATE --------------------
bool public funded;
bool public sessionCompleted;
bool public patientConfirmed;
bool public paid;
// -------------------- EVENTS --------------------
event Funded(address indexed patient, uint256 amount);
event SessionCompleted(address indexed provider);
event PatientConfirmed(address indexed patient);
event ProviderPaid(address indexed provider, uint256 amount);
event Refunded(address indexed patient, uint256 amount);
// -------------------- MODIFIERS --------------------
modifier onlyPatient() {
require(msg.sender == patient, "Not patient");
_;
}
modifier onlyProvider() {
require(msg.sender == provider, "Not provider");
_;
}
// -------------------- CONSTRUCTOR --------------------
constructor(
address _patient,
address _provider,
uint256 _consultationFee,
uint256 _sessionDuration,
uint256 _confirmationTimeout
) {
require(_patient != address(0), "Invalid patient");
require(_provider != address(0), "Invalid provider");
patient = _patient;
provider = _provider;
consultationFee = _consultationFee;
sessionDeadline = block.timestamp + _sessionDuration;
confirmationTimeout = _confirmationTimeout;
}
// -------------------- ESCROW FLOW --------------------
/**
* @notice Patient funds the escrow
*/
function fund() external payable onlyPatient {
require(!funded, "Already funded");
require(msg.value == consultationFee, "Incorrect fee");
funded = true;
emit Funded(msg.sender, msg.value);
}
/**
* @notice Provider marks session as completed
*/
function completeSession() external onlyProvider {
require(funded, "Not funded");
require(!sessionCompleted, "Already completed");
require(block.timestamp = sessionDeadline + confirmationTimeout,
"Confirmation window open"
);
require(!paid, "Already settled");
_releasePayment();
}
// -------------------- INTERNAL --------------------
function _releasePayment() internal {
require(!paid, "Already paid");
paid = true;
payable(provider).transfer(consultationFee);
emit ProviderPaid(provider, consultationFee);
}
// -------------------- REFUND LOGIC --------------------
/**
* @notice Refund patient if session not completed
*/
function refund() external onlyPatient {
require(funded, "Not funded");
require(!sessionCompleted, "Session completed");
require(block.timestamp > sessionDeadline, "Session still valid");
require(!paid, "Already settled");
paid = true;
payable(patient).transfer(consultationFee);
emit Refunded(patient, consultationFee);
}
}
Build and Grow By Nam Le Thanh