dgf-prototype/ethereum/contracts/DAO.sol

111 lines
3.5 KiB
Solidity
Raw Normal View History

2024-03-04 19:33:06 -06:00
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.24;
import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "./ReputationHolder.sol";
2024-03-04 19:54:48 -06:00
struct Stake {
bool inFavor;
uint256 amount;
2024-03-05 10:15:31 -06:00
address sender;
2024-03-04 19:54:48 -06:00
}
enum ValidationPoolStatus {
Open,
Closed
}
struct ValidationPool {
mapping(uint => Stake) stakes;
uint stakeCount;
ValidationPoolStatus status;
2024-03-05 10:15:31 -06:00
uint duration;
uint endTime;
}
struct StakeData {
uint validationPoolIndex;
bool inFavor;
2024-03-04 19:54:48 -06:00
}
2024-03-04 19:33:06 -06:00
/// This contract must manage validation pools and reputation,
/// because otherwise there's no way to enforce appropriate permissions on
/// transfer of value between reputation NFTs.
contract DAO is ERC721("Reputation", "REP"), ReputationHolder {
2024-03-04 19:54:48 -06:00
mapping(uint256 tokenId => uint256) tokenValues;
uint256 nextTokenId;
mapping(uint => ValidationPool) validationPools;
uint validationPoolCount;
2024-03-04 19:33:06 -06:00
2024-03-05 10:15:31 -06:00
event ValidationPoolInitiated(uint validationPoolIndex);
2024-03-04 19:33:06 -06:00
/// Inspect the value of a given reputation NFT
function valueOf(uint256 tokenId) public view returns (uint256 value) {
2024-03-04 19:54:48 -06:00
value = tokenValues[tokenId];
2024-03-04 19:33:06 -06:00
}
2024-03-05 10:15:31 -06:00
/// Confirm ownership of a token and return its value.
/// This should be used when receiving an NFT transfer, because otherwise
/// someone could send any NFT with a tokenId matching one of ours.
function verifiedValueOf(
address owner,
uint256 tokenId
) public view returns (uint256 value) {
require(ownerOf(tokenId) == owner);
value = valueOf(tokenId);
}
2024-03-04 19:33:06 -06:00
/// Internal function to mint a new reputation NFT
function mint() internal returns (uint256 tokenId) {
// Generate a new (sequential) ID for the token
2024-03-04 19:54:48 -06:00
tokenId = nextTokenId++;
2024-03-04 19:33:06 -06:00
// Mint the token, initially to be owned by the current contract.
_mint(address(this), tokenId);
}
/// Internal function to transfer value from one reputation token to another
function transferValueFrom(
uint256 fromTokenId,
uint256 toTokenId,
uint256 amount
) internal {
require(amount >= 0);
require(valueOf(fromTokenId) >= amount);
2024-03-04 19:54:48 -06:00
tokenValues[fromTokenId] -= amount;
tokenValues[toTokenId] += amount;
}
/// Accept fee to initiate a validation pool
2024-03-05 10:15:31 -06:00
function initiateValidationPool(uint duration) public {
uint validationPoolIndex = validationPoolCount++;
ValidationPool storage pool = validationPools[validationPoolIndex];
pool.duration = duration;
pool.endTime = block.timestamp + duration;
emit ValidationPoolInitiated(validationPoolIndex);
}
2024-03-04 19:54:48 -06:00
/// Accept reputation stakes toward a validation pool
function onERC721Received(
address,
address from,
uint256 tokenId,
2024-03-05 10:15:31 -06:00
bytes calldata data
2024-03-04 19:54:48 -06:00
) public override returns (bytes4) {
2024-03-05 10:15:31 -06:00
// `data` needs to encode the target validation pool, and the for/again boolean
StakeData memory stakeParameters = abi.decode(data, (StakeData));
ValidationPool storage pool = validationPools[
stakeParameters.validationPoolIndex
];
Stake storage stake = pool.stakes[pool.stakeCount++];
stake.sender = from;
stake.inFavor = stakeParameters.inFavor;
stake.amount = verifiedValueOf(from, tokenId);
2024-03-04 19:54:48 -06:00
return super.onERC721Received.selector;
2024-03-04 19:33:06 -06:00
}
2024-03-05 10:15:31 -06:00
/// Evaluate outcome of a validation pool
function evaluateOutcome(
uint validationPoolIndex
) public returns (bool outcome) {}
2024-03-04 19:33:06 -06:00
}