From c7af78deaa96b6e502bd0535d9377a932593b6aa Mon Sep 17 00:00:00 2001 From: Ladd Hoffman Date: Tue, 5 Mar 2024 10:15:31 -0600 Subject: [PATCH] Progress on validation pool --- ethereum/contracts/DAO.sol | 46 +++++++++++++++++++++++++++++++++--- ethereum/contracts/Work1.sol | 5 ++-- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/ethereum/contracts/DAO.sol b/ethereum/contracts/DAO.sol index 991ed44..6dd115f 100644 --- a/ethereum/contracts/DAO.sol +++ b/ethereum/contracts/DAO.sol @@ -7,7 +7,7 @@ import "./ReputationHolder.sol"; struct Stake { bool inFavor; uint256 amount; - address worker; + address sender; } enum ValidationPoolStatus { @@ -19,6 +19,13 @@ struct ValidationPool { mapping(uint => Stake) stakes; uint stakeCount; ValidationPoolStatus status; + uint duration; + uint endTime; +} + +struct StakeData { + uint validationPoolIndex; + bool inFavor; } /// This contract must manage validation pools and reputation, @@ -30,11 +37,24 @@ contract DAO is ERC721("Reputation", "REP"), ReputationHolder { mapping(uint => ValidationPool) validationPools; uint validationPoolCount; + event ValidationPoolInitiated(uint validationPoolIndex); + /// Inspect the value of a given reputation NFT function valueOf(uint256 tokenId) public view returns (uint256 value) { value = tokenValues[tokenId]; } + /// 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); + } + /// Internal function to mint a new reputation NFT function mint() internal returns (uint256 tokenId) { // Generate a new (sequential) ID for the token @@ -56,15 +76,35 @@ contract DAO is ERC721("Reputation", "REP"), ReputationHolder { } /// Accept fee to initiate a validation pool - function initiateValidationPool() public {} + function initiateValidationPool(uint duration) public { + uint validationPoolIndex = validationPoolCount++; + ValidationPool storage pool = validationPools[validationPoolIndex]; + pool.duration = duration; + pool.endTime = block.timestamp + duration; + emit ValidationPoolInitiated(validationPoolIndex); + } /// Accept reputation stakes toward a validation pool function onERC721Received( address, address from, uint256 tokenId, - bytes calldata + bytes calldata data ) public override returns (bytes4) { + // `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); return super.onERC721Received.selector; } + + /// Evaluate outcome of a validation pool + function evaluateOutcome( + uint validationPoolIndex + ) public returns (bool outcome) {} } diff --git a/ethereum/contracts/Work1.sol b/ethereum/contracts/Work1.sol index 3720969..ec6015b 100644 --- a/ethereum/contracts/Work1.sol +++ b/ethereum/contracts/Work1.sol @@ -51,7 +51,8 @@ contract Work1 is ReputationHolder { AvailabilityStake storage stake = stakes[stakeCount++]; stake.worker = from; stake.tokenId = tokenId; - stake.amount = dao.valueOf(tokenId); + stake.amount = dao.verifiedValueOf(from, tokenId); + // TODO: use `data` parameter to include stake options such as duration return super.onERC721Received.selector; } @@ -67,7 +68,7 @@ contract Work1 is ReputationHolder { for (uint i = 0; i < stakeCount; i++) { if (stakes[i].assigned) continue; acc += stakes[i].amount; - if (acc >= select) return i; + if (acc > select) return i; } revert("Failed to select worker"); }