What it does:
Enables users to create digital wills that automatically donate funds to chosen charities upon verification of death or predefined conditions.
Why it matters:
Ensures transparent, automated, and tamper-proof charitable giving, reduces reliance on intermediaries, and guarantees that donations are distributed as intended.
How it works:
Users create a will specifying charities and percentage allocations
Funds are deposited into the smart contract in advance
Verification (via oracles, legal services, or trusted signers) triggers fund distribution
Smart contract automatically splits and transfers funds to designated charities
Supports recurring charitable triggers or conditional donations
Integrates with Smart Will & Testament, Personal Data Vault, or Reputation-Based Governance
Dashboards show pending wills, executed donations, and fund allocations
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title SmartDonationWill
* @author Nam
* @notice Executes charitable donations automatically based on user-defined wills
*/
contract SmartDonationWill is Ownable {
struct Charity {
address payable charityAddress;
uint256 percentage; // 0-100
}
struct DonationWill {
address creator;
uint256 totalAmount;
Charity[] charities;
bool executed;
}
mapping(uint256 => DonationWill) public wills;
uint256 public willCount;
mapping(address => bool) public authorizedOracles;
// -------------------- EVENTS --------------------
event OracleApproved(address oracle);
event OracleRevoked(address oracle);
event WillCreated(uint256 indexed willId, address creator, uint256 totalAmount);
event WillExecuted(uint256 indexed willId);
// -------------------- ORACLE MANAGEMENT --------------------
function approveOracle(address _oracle) external onlyOwner {
authorizedOracles[_oracle] = true;
emit OracleApproved(_oracle);
}
function revokeOracle(address _oracle) external onlyOwner {
authorizedOracles[_oracle] = false;
emit OracleRevoked(_oracle);
}
modifier onlyOracle() {
require(authorizedOracles[msg.sender], "Not authorized oracle");
_;
}
// -------------------- WILL CREATION --------------------
function createWill(address[] calldata _charities, uint256[] calldata _percentages) external payable {
require(_charities.length == _percentages.length, "Mismatch lengths");
uint256 totalPercent = 0;
for (uint256 i = 0; i 0, "Must deposit funds");
willCount += 1;
DonationWill storage w = wills[willCount];
w.creator = msg.sender;
w.totalAmount = msg.value;
w.executed = false;
for (uint256 i = 0; i < _charities.length; i++) {
w.charities.push(Charity({
charityAddress: payable(_charities[i]),
percentage: _percentages[i]
}));
}
emit WillCreated(willCount, msg.sender, msg.value);
}
// -------------------- EXECUTION --------------------
function executeWill(uint256 _willId) external onlyOracle {
DonationWill storage w = wills[_willId];
require(!w.executed, "Already executed");
for (uint256 i = 0; i < w.charities.length; i++) {
Charity storage c = w.charities[i];
uint256 amount = (w.totalAmount * c.percentage) / 100;
c.charityAddress.transfer(amount);
}
w.executed = true;
emit WillExecuted(_willId);
}
// -------------------- VIEW FUNCTIONS --------------------
function getWillCharities(uint256 _willId) external view returns (Charity[] memory) {
return wills[_willId].charities;
}
}
Build and Grow By Nam Le Thanh