What it does:
Pools capital from donors and institutions to fund medical research projects through transparent, community-governed decision-making.
Why it matters:
Reduces bias in research funding, increases accountability, and ensures capital is allocated to scientifically valuable and socially impactful studies.
How it works:
Donors contribute funds to the research pool
Researchers submit funding proposals
Proposal details and requested budgets are stored on-chain
DAO members vote on which projects receive funding
Approved funds are released to researchers
Spending and milestones are transparently tracked
Unused funds can be reclaimed or reallocated
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title MedicalResearchFundingDAO
* @author Nam
* @notice DAO for funding medical research projects
*/
contract MedicalResearchFundingDAO {
// -------------------- DAO CORE --------------------
address public admin;
uint256 public proposalCount;
// -------------------- STRUCTS --------------------
struct Proposal {
address researcher;
string metadataHash; // IPFS research proposal
uint256 requestedAmount;
uint256 votesFor;
uint256 votesAgainst;
bool executed;
uint256 deadline;
}
// -------------------- STORAGE --------------------
mapping(uint256 => Proposal) public proposals;
mapping(uint256 => mapping(address => bool)) public hasVoted;
mapping(address => uint256) public votingPower; // donation-based
// -------------------- EVENTS --------------------
event Funded(address indexed donor, uint256 amount);
event ProposalSubmitted(uint256 indexed proposalId, address researcher);
event VoteCast(uint256 indexed proposalId, address voter, bool support);
event FundsReleased(uint256 indexed proposalId, uint256 amount);
// -------------------- MODIFIERS --------------------
modifier onlyAdmin() {
require(msg.sender == admin, "Not admin");
_;
}
modifier proposalActive(uint256 _id) {
require(block.timestamp 0, "No funds sent");
votingPower[msg.sender] += msg.value;
emit Funded(msg.sender, msg.value);
}
// -------------------- PROPOSALS --------------------
/**
* @notice Submit a research proposal
*/
function submitProposal(
string calldata _metadataHash,
uint256 _requestedAmount,
uint256 _votingDuration
)
external
{
require(_requestedAmount > 0, "Invalid amount");
require(_votingDuration > 0, "Invalid duration");
proposalCount += 1;
proposals[proposalCount] = Proposal({
researcher: msg.sender,
metadataHash: _metadataHash,
requestedAmount: _requestedAmount,
votesFor: 0,
votesAgainst: 0,
executed: false,
deadline: block.timestamp + _votingDuration
});
emit ProposalSubmitted(proposalCount, msg.sender);
}
// -------------------- VOTING --------------------
/**
* @notice Vote on a proposal
*/
function vote(
uint256 _proposalId,
bool _support
)
external
proposalActive(_proposalId)
{
require(votingPower[msg.sender] > 0, "No voting power");
require(!hasVoted[_proposalId][msg.sender], "Already voted");
hasVoted[_proposalId][msg.sender] = true;
if (_support) {
proposals[_proposalId].votesFor += votingPower[msg.sender];
} else {
proposals[_proposalId].votesAgainst += votingPower[msg.sender];
}
emit VoteCast(_proposalId, msg.sender, _support);
}
// -------------------- EXECUTION --------------------
/**
* @notice Release funds if proposal passes
*/
function releaseFunds(uint256 _proposalId)
external
{
Proposal storage p = proposals[_proposalId];
require(!p.executed, "Already executed");
require(block.timestamp > p.deadline, "Voting not ended");
require(p.votesFor > p.votesAgainst, "Proposal rejected");
require(address(this).balance >= p.requestedAmount, "Insufficient funds");
p.executed = true;
payable(p.researcher).transfer(p.requestedAmount);
emit FundsReleased(_proposalId, p.requestedAmount);
}
// -------------------- TREASURY --------------------
receive() external payable {}
}
Build and Grow By Nam Le Thanh