Relationship Agreement Smart Contract
What it does:
Enables individuals to define, store, and enforce personal agreements or relationship commitments on-chain, optionally including shared responsibilities or milestone-based triggers.
Why it matters:
Creates transparency and accountability in personal agreements, reduces disputes, ensures enforceability, and allows optional automation of shared responsibilities or assets.
How it works:
-
Participants define agreement terms, milestones, or conditions on-chain
-
Smart contract stores immutable records of the agreement and participants’ consent
-
Conditional triggers can automate asset transfers, shared responsibilities, or notifications
-
Milestones can include events, date-based commitments, or mutual approvals
-
Integrates with tokenized assets, escrow payments, or shared wallets
-
Dashboards show agreement status, upcoming milestones, and fulfillment history
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title RelationshipAgreement
* @author Nam
* @notice Stores and enforces personal or relationship agreements on-chain
*/
contract RelationshipAgreement is Ownable {
struct Milestone {
string description;
uint256 dueDate; // timestamp
bool completed;
}
struct Agreement {
address participant1;
address participant2;
string terms;
Milestone[] milestones;
bool active;
}
mapping(uint256 => Agreement) public agreements;
uint256 public agreementCount;
mapping(address => bool) public authorizedValidators;
// -------------------- EVENTS --------------------
event ValidatorApproved(address validator);
event ValidatorRevoked(address validator);
event AgreementCreated(uint256 indexed agreementId, address participant1, address participant2);
event MilestoneCompleted(uint256 indexed agreementId, uint256 milestoneIndex);
// -------------------- VALIDATOR MANAGEMENT --------------------
function approveValidator(address _validator) external onlyOwner {
authorizedValidators[_validator] = true;
emit ValidatorApproved(_validator);
}
function revokeValidator(address _validator) external onlyOwner {
authorizedValidators[_validator] = false;
emit ValidatorRevoked(_validator);
}
modifier onlyValidator() {
require(authorizedValidators[msg.sender], "Not authorized validator");
_;
}
// -------------------- AGREEMENT MANAGEMENT --------------------
function createAgreement(address _participant2, string calldata _terms, string[] calldata _milestoneDescriptions, uint256[] calldata _dueDates) external {
require(_participant2 != address(0), "Invalid participant");
require(_milestoneDescriptions.length == _dueDates.length, "Mismatched milestones and dates");
agreementCount += 1;
Agreement storage a = agreements[agreementCount];
a.participant1 = msg.sender;
a.participant2 = _participant2;
a.terms = _terms;
a.active = true;
for (uint256 i = 0; i < _milestoneDescriptions.length; i++) {
a.milestones.push(Milestone({
description: _milestoneDescriptions[i],
dueDate: _dueDates[i],
completed: false
}));
}
emit AgreementCreated(agreementCount, msg.sender, _participant2);
}
// -------------------- MILESTONE MANAGEMENT --------------------
function completeMilestone(uint256 _agreementId, uint256 _milestoneIndex) external onlyValidator {
Agreement storage a = agreements[_agreementId];
require(a.active, "Agreement not active");
Milestone storage m = a.milestones[_milestoneIndex];
require(!m.completed, "Milestone already completed");
m.completed = true;
emit MilestoneCompleted(_agreementId, _milestoneIndex);
}
// -------------------- VIEW FUNCTIONS --------------------
function getMilestones(uint256 _agreementId) external view returns (Milestone[] memory) {
return agreements[_agreementId].milestones;
}
function isAgreementActive(uint256 _agreementId) external view returns (bool) {
return agreements[_agreementId].active;
}
}