add post separate from propose
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 38s Details

This commit is contained in:
Ladd Hoffman 2024-04-28 16:51:35 -05:00
parent 8e272bf2e8
commit 37fd387cf3
8 changed files with 163 additions and 25 deletions

View File

@ -16,7 +16,6 @@ contract Availability is IAcceptAvailability, DAOContract {
uint public stakeCount;
event AvailabilityStaked(uint stakeIndex);
event WorkAssigned(uint requestIndex, uint stakeIndex);
constructor(DAO dao) DAOContract(dao) {}
@ -77,10 +76,9 @@ contract Availability is IAcceptAvailability, DAOContract {
}
/// Assign a random available worker
function assignWork(uint requestIndex) internal returns (uint stakeIndex) {
function assignWork() internal returns (uint stakeIndex) {
stakeIndex = randomWeightedSelection();
AvailabilityStake storage stake = stakes[stakeIndex];
stake.assigned = true;
emit WorkAssigned(requestIndex, stakeIndex);
}
}

View File

@ -59,22 +59,17 @@ contract Proposals is DAOContract, IOnValidate {
// TODO receive : we want to be able to accept refunds from validation pools
/// Submit a post as a proposal. DAO.addPost should be called before this.
function propose(
string calldata contentId,
address author,
string calldata postId,
uint[3] calldata durations,
bool callbackOnAccepted,
bytes calldata callbackData
) external payable returns (uint proposalIndex) {
// TODO: Take citations as a parameter
Citation[] memory emptyCitations;
Author[] memory authors = new Author[](1);
authors[0] = Author(1000000, author);
dao.addPost(authors, contentId, emptyCitations);
proposalIndex = proposalCount++;
Proposal storage proposal = proposals[proposalIndex];
proposal.sender = msg.sender;
proposal.postId = contentId;
proposal.postId = postId;
proposal.startTime = block.timestamp;
proposal.referenda[0].duration = durations[0];
proposal.referenda[1].duration = durations[1];

View File

@ -5,10 +5,68 @@ import "./WorkContract.sol";
import "./Rollup.sol";
abstract contract RollableWorkContract is WorkContract {
Rollup immutable rollupContract;
constructor(
DAO dao,
Proposals proposalsContract,
uint price,
Rollup rollupContract_
) WorkContract(dao, proposalsContract, price) {}
) WorkContract(dao, proposalsContract, price) {
rollupContract = rollupContract_;
}
/// Accept work approval/disapproval from customer
function submitWorkApproval(
uint requestIndex,
bool approval
) external override {
WorkRequest storage request = requests[requestIndex];
require(
request.status == WorkStatus.EvidenceSubmitted,
"Status must be EvidenceSubmitted"
);
AvailabilityStake storage stake = stakes[request.stakeIndex];
request.status = WorkStatus.ApprovalSubmitted;
request.approval = approval;
emit WorkApprovalSubmitted(requestIndex, approval);
// Make work evidence post
Author[] memory authors = new Author[](1);
authors[0] = Author(1000000, stake.worker);
// TODO: send post and fee to rollup contract
dao.forwardAllowance(
stake.worker,
address(rollupContract),
stake.amount
);
payable(address(rollupContract)).transfer(request.fee);
rollupContract.addItem(
stake.worker,
stake.amount,
request.fee,
request.evidenceContentId
);
// dao.addPost(authors, request.evidenceContentId, request.citations);
// Initiate validation pool
uint poolIndex = dao.initiateValidationPool{value: request.fee}(
request.evidenceContentId,
POOL_DURATION,
[uint256(1), uint256(3)],
[uint256(1), uint256(2)],
100,
true,
false,
""
);
// We have an approval from stake.worker to transfer up to stake.amount
dao.delegatedStakeOnValidationPool(
poolIndex,
stake.worker,
stake.amount,
true
);
}
}

View File

@ -6,4 +6,77 @@ import "./Availability.sol";
contract Rollup is Availability {
constructor(DAO dao) Availability(dao) {}
struct BatchItem {
address worker;
uint stakeAmount;
uint fee;
string evidenceContentId;
}
mapping(uint => BatchItem) items;
uint itemCount;
address batchWorker;
uint batchWorkerStakeIndex;
function addItem(
address worker,
uint stakeAmount,
uint fee,
string calldata evidenceContentId
) public {
BatchItem storage item = items[itemCount++];
item.worker = worker;
item.stakeAmount = stakeAmount;
item.fee = fee;
item.evidenceContentId = evidenceContentId;
}
function submitBatch(
string calldata batchPostId,
uint poolDuration
) public {
if (batchWorker != address(0)) {
require(
msg.sender == batchWorker,
"Batch result must be submitted by current batch worker"
);
}
// initiate a validation pool for this batch
uint fee;
for (uint i = 0; i < itemCount; i++) {
fee += items[i].fee;
}
uint poolIndex = dao.initiateValidationPool{value: fee}(
batchPostId,
poolDuration,
[uint256(1), uint256(3)],
[uint256(1), uint256(2)],
100,
true,
false,
""
);
// Include all the availability stakes from the batched work
for (uint i = 0; i < itemCount; i++) {
dao.delegatedStakeOnValidationPool(
poolIndex,
items[i].worker,
items[i].stakeAmount,
true
);
}
// Include availability stakes from the batch worker
dao.delegatedStakeOnValidationPool(
poolIndex,
batchWorker,
stakes[batchWorkerStakeIndex].amount,
true
);
// Reset item count so we can start the next batch
itemCount = 0;
// Select the next worker
batchWorkerStakeIndex = assignWork();
batchWorker = stakes[batchWorkerStakeIndex].worker;
}
}

View File

@ -40,6 +40,7 @@ abstract contract WorkContract is Availability, IOnProposalAccepted {
uint constant POOL_DURATION = 20;
event WorkAssigned(uint requestIndex, uint stakeIndex);
event WorkEvidenceSubmitted(uint requestIndex);
event WorkApprovalSubmitted(uint requestIndex, bool approval);
event PriceChangeProposed(uint priceProposalIndex);
@ -61,8 +62,9 @@ abstract contract WorkContract is Availability, IOnProposalAccepted {
WorkRequest storage request = requests[requestIndex];
request.customer = msg.sender;
request.fee = msg.value;
request.stakeIndex = assignWork(requestIndex);
request.stakeIndex = assignWork();
request.requestContentId = requestContentId;
emit WorkAssigned(requestIndex, request.stakeIndex);
}
/// Accept work evidence from worker
@ -127,9 +129,11 @@ abstract contract WorkContract is Availability, IOnProposalAccepted {
);
}
/// Initiate a new proposal to change the price for this work contract.
/// This takes a postId; DAO.addPost should be called before or concurrently with this.
function proposeNewPrice(
uint newPrice,
string calldata contentId,
string calldata postId,
uint[3] calldata durations
) external payable {
uint priceProposalIndex = priceProposalCount++;
@ -139,13 +143,7 @@ abstract contract WorkContract is Availability, IOnProposalAccepted {
priceProposal.price = newPrice;
priceProposal.proposalIndex = proposalsContract.propose{
value: msg.value
}(
contentId,
msg.sender,
durations,
true,
abi.encode(priceProposalIndex)
);
}(postId, durations, true, abi.encode(priceProposalIndex));
emit PriceChangeProposed(priceProposalIndex);
}

View File

@ -24,4 +24,13 @@ contract Reputation is ERC20("Reputation", "REP") {
) public pure override returns (bool) {
revert("REP transfer is not allowed");
}
function forwardAllowance(
address owner,
address to,
uint256 amount
) public {
_spendAllowance(owner, msg.sender, amount);
_approve(owner, to, allowance(owner, to) + amount);
}
}

View File

@ -79,7 +79,8 @@ describe('Proposal', () => {
} = await loadFixture(deploy));
const emptyCallbackData = ethers.AbiCoder.defaultAbiCoder().encode([], []);
await proposals.propose('proposal-content-id', account1, [20, 20, 20], false, emptyCallbackData, { value: 100 });
await dao.addPost([{ authorAddress: account1, weightPPM: 1000000 }], 'proposal-content-id', []);
await proposals.propose('proposal-content-id', [20, 20, 20], false, emptyCallbackData, { value: 100 });
expect(await proposals.proposalCount()).to.equal(1);
proposal = await proposals.proposals(0);
expect(proposal.postId).to.equal('proposal-content-id');

View File

@ -28,7 +28,7 @@ const getProposalStatus = (proposal) => {
function Proposals() {
const {
provider, chainId, account, reputation,
provider, chainId, account, reputation, DAORef,
} = useContext(Web3Context);
const [proposals, dispatchProposal] = useList();
const proposalsContract = useRef();
@ -105,9 +105,15 @@ function Proposals() {
const onSubmitProposal = useCallback(async (post) => {
const web3 = new Web3(provider);
const emptyCallbackData = web3.eth.abi.encodeParameter('bytes', '0x00');
// First add a post for this proposal
await DAORef.current.methods.addPost(
[{ authorAddress: account, weightPPM: 1000000 }],
post.hash,
[], // TODO: Proposal can cite posts from matrix, semantic scholar, etc
);
// Now submit the post as a proposal
await proposalsContract.current.methods.propose(
post.hash,
account,
durations,
false,
emptyCallbackData,
@ -116,7 +122,7 @@ function Proposals() {
gas: 1000000,
value: 10000,
});
}, [provider, account, proposalsContract, durations]);
}, [provider, account, proposalsContract, durations, DAORef]);
const handleAttest = useCallback(async (proposalIndex) => {
await proposalsContract.current.methods.attest(proposalIndex, reputation).send({