2024-03-26 18:28:38 -05:00
|
|
|
// SPDX-License-Identifier: Unlicense
|
|
|
|
pragma solidity ^0.8.24;
|
|
|
|
|
|
|
|
import "./DAO.sol";
|
2024-03-26 21:32:41 -05:00
|
|
|
import "hardhat/console.sol";
|
2024-03-26 18:28:38 -05:00
|
|
|
|
|
|
|
contract Proposals is DAOContract {
|
|
|
|
struct Attestation {
|
|
|
|
address sender;
|
|
|
|
uint amount;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum Stage {
|
|
|
|
Proposal,
|
|
|
|
Referendum0,
|
|
|
|
Referendum1,
|
|
|
|
Referendum100,
|
|
|
|
Closed
|
|
|
|
}
|
2024-03-26 21:32:41 -05:00
|
|
|
|
|
|
|
struct Referendum {
|
|
|
|
uint duration;
|
|
|
|
uint poolIndex;
|
|
|
|
}
|
|
|
|
|
2024-03-26 18:28:38 -05:00
|
|
|
struct Proposal {
|
|
|
|
address sender;
|
2024-03-26 21:32:41 -05:00
|
|
|
uint fee;
|
|
|
|
uint feeRemaining;
|
|
|
|
uint postIndex;
|
2024-03-26 18:28:38 -05:00
|
|
|
uint startTime;
|
|
|
|
Stage stage;
|
|
|
|
mapping(uint => Attestation) attestations;
|
|
|
|
uint attestationCount;
|
2024-03-26 21:32:41 -05:00
|
|
|
Referendum[3] referenda;
|
2024-03-26 18:28:38 -05:00
|
|
|
}
|
|
|
|
|
2024-03-26 21:32:41 -05:00
|
|
|
mapping(uint => Proposal) public proposals;
|
|
|
|
uint public proposalCount;
|
2024-03-26 18:28:38 -05:00
|
|
|
|
|
|
|
constructor(DAO dao) DAOContract(dao) {}
|
|
|
|
|
|
|
|
function propose(
|
2024-03-26 21:32:41 -05:00
|
|
|
uint postIndex,
|
|
|
|
uint referendum0Duration,
|
|
|
|
uint referendum1Duration,
|
|
|
|
uint referendum100Duration
|
|
|
|
) external payable returns (uint proposalIndex) {
|
2024-03-26 18:28:38 -05:00
|
|
|
proposalIndex = proposalCount++;
|
|
|
|
Proposal storage proposal = proposals[proposalIndex];
|
2024-03-26 21:32:41 -05:00
|
|
|
proposal.postIndex = postIndex;
|
2024-03-26 18:28:38 -05:00
|
|
|
proposal.startTime = block.timestamp;
|
2024-03-26 21:32:41 -05:00
|
|
|
proposal.referenda[0].duration = referendum0Duration;
|
|
|
|
proposal.referenda[1].duration = referendum1Duration;
|
|
|
|
proposal.referenda[2].duration = referendum100Duration;
|
|
|
|
proposal.fee = msg.value;
|
|
|
|
proposal.feeRemaining = proposal.fee;
|
2024-03-26 18:28:38 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
function attest(uint proposalIndex, uint amount) external {
|
|
|
|
// Since this is non-binding, non-encumbering, we only need to verify that
|
|
|
|
// the sender actually has the rep they claim to stake.
|
|
|
|
require(
|
|
|
|
dao.balanceOf(msg.sender) >= amount,
|
|
|
|
"Sender has insufficient REP balance"
|
|
|
|
);
|
|
|
|
Proposal storage proposal = proposals[proposalIndex];
|
|
|
|
uint attestationIndex = proposal.attestationCount++;
|
|
|
|
Attestation storage attestation = proposal.attestations[
|
|
|
|
attestationIndex
|
|
|
|
];
|
|
|
|
attestation.sender = msg.sender;
|
|
|
|
attestation.amount = amount;
|
|
|
|
}
|
|
|
|
|
2024-03-26 21:32:41 -05:00
|
|
|
// todo onValidate() {
|
|
|
|
|
|
|
|
// This callback will get proposalIndex
|
|
|
|
|
|
|
|
// todo }
|
|
|
|
|
2024-03-26 18:28:38 -05:00
|
|
|
function evaluateAttestation(uint proposalIndex) external returns (bool) {
|
|
|
|
Proposal storage proposal = proposals[proposalIndex];
|
|
|
|
require(
|
|
|
|
proposal.stage == Stage.Proposal,
|
|
|
|
"Attestation only pertains to Proposal stage"
|
|
|
|
);
|
|
|
|
uint totalAttestation;
|
|
|
|
for (uint i = 0; i < proposal.attestationCount; i++) {
|
|
|
|
totalAttestation += proposal.attestations[i].amount;
|
|
|
|
}
|
|
|
|
bool meetsAttestation = 10 * totalAttestation >= dao.totalSupply();
|
2024-03-26 21:32:41 -05:00
|
|
|
bool expired = block.timestamp > proposal.startTime + 365 days;
|
2024-03-26 18:28:38 -05:00
|
|
|
if (!meetsAttestation) {
|
2024-03-26 21:32:41 -05:00
|
|
|
if (expired) {
|
2024-03-26 18:28:38 -05:00
|
|
|
proposal.stage = Stage.Closed;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// Initiate validation pool
|
|
|
|
proposal.stage = Stage.Referendum0;
|
2024-03-26 21:32:41 -05:00
|
|
|
uint thisFee = proposal.fee / 3;
|
|
|
|
proposal.feeRemaining -= thisFee;
|
|
|
|
proposal.referenda[0].poolIndex = dao.initiateValidationPool{
|
|
|
|
value: thisFee
|
|
|
|
}(
|
|
|
|
proposal.postIndex, // uint postIndex,
|
|
|
|
proposal.referenda[0].duration, // uint duration,
|
|
|
|
1, // uint quorumNumerator,
|
|
|
|
3, // uint quorumDenominator,
|
|
|
|
0, // uint bindingPercent,
|
|
|
|
false, // bool redistributeLosingStakes,
|
|
|
|
false, // TODO bool callbackOnValidate : true,
|
|
|
|
"" // TODO bytes calldata callbackData : This should probably be proposalIndex
|
|
|
|
);
|
|
|
|
return true;
|
2024-03-26 18:28:38 -05:00
|
|
|
}
|
|
|
|
}
|