Skip to content

Commit c3bed8d

Browse files
committed
SwanDebate: Minor contract fixes
1 parent 7c3671e commit c3bed8d

File tree

4 files changed

+50
-109
lines changed

4 files changed

+50
-109
lines changed

deployments/abis/SwanDebate.json

+21
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@
105105
"type": "uint256",
106106
"internalType": "uint256"
107107
},
108+
{
109+
"name": "agent1ProposalId",
110+
"type": "uint256",
111+
"internalType": "uint256"
112+
},
113+
{
114+
"name": "agent2ProposalId",
115+
"type": "uint256",
116+
"internalType": "uint256"
117+
},
108118
{
109119
"name": "currentRound",
110120
"type": "uint256",
@@ -740,6 +750,17 @@
740750
}
741751
]
742752
},
753+
{
754+
"type": "error",
755+
"name": "InvalidProposalCount",
756+
"inputs": [
757+
{
758+
"name": "count",
759+
"type": "uint256",
760+
"internalType": "uint256"
761+
}
762+
]
763+
},
743764
{
744765
"type": "error",
745766
"name": "OwnableInvalidOwner",

src/SwanDebate.sol

+15-30
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@ interface IJokeRaceContest {
2929

3030
/// @notice Returns vote counts for a proposal
3131
/// @param proposalId The ID of the proposal to query
32-
/// @return forVotes Number of votes in favor
33-
/// @return againstVotes Number of votes against
34-
function proposalVotes(uint256 proposalId) external view returns (uint256 forVotes, uint256 againstVotes);
32+
/// @return votes Number of votes
33+
function proposalVotes(uint256 proposalId) external view returns (uint256 votes);
3534

3635
/// @notice Returns all proposal IDs in the contest
3736
/// @return Array of proposal IDs
@@ -46,14 +45,6 @@ interface IJokeRaceContest {
4645
external
4746
view
4847
returns (address author, bool exists, string memory description);
49-
50-
/// @notice Sorts proposals based on votes and marks tied proposals
51-
/// @dev Needed before retrieving the winning proposal
52-
function setSortedAndTiedProposals() external;
53-
54-
/// @notice Returns sorted proposal IDs based on votes
55-
/// @return Array of proposal IDs sorted from lowest to highest votes
56-
function sortedProposalIds() external view returns (uint256[] memory);
5748
}
5849

5950
/// @title SwanDebate
@@ -240,9 +231,6 @@ contract SwanDebate is Ownable, Pausable {
240231
if (debate.currentRound != 0) revert DebateAlreadyExists(_contest);
241232

242233
IJokeRaceContest contest = IJokeRaceContest(_contest);
243-
if (contest.state() != IJokeRaceContest.ContestState.Queued) {
244-
revert ContestInvalidState(contest.state(), IJokeRaceContest.ContestState.Queued);
245-
}
246234

247235
uint256[] memory proposalIds = contest.getAllProposalIds();
248236
if (proposalIds.length != 2) {
@@ -335,27 +323,24 @@ contract SwanDebate is Ownable, Pausable {
335323
/// @dev Requires contest state to be `Completed`, sorts proposals, and fetches the winner
336324
/// @param _contest Address of the JokeRace contest
337325
function terminateDebate(address _contest) external onlyOwner whenNotPaused {
326+
Debate storage debate = debates[_contest];
338327
IJokeRaceContest contest = IJokeRaceContest(_contest);
339-
require(contest.state() == IJokeRaceContest.ContestState.Completed, "Contest not finished");
340-
341-
// Sort proposals based on votes before retrieving the winner
342-
contest.setSortedAndTiedProposals();
343-
uint256[] memory sortedProposals = contest.sortedProposalIds();
344328

345-
require(sortedProposals.length > 0, "No proposals found");
329+
uint256 agent1ProposalVotes = contest.proposalVotes(debate.agent1ProposalId);
330+
uint256 agent2ProposalVotes = contest.proposalVotes(debate.agent2ProposalId);
346331

347-
// The last proposal in the sorted array has the highest votes
348-
uint256 winningProposal = sortedProposals[sortedProposals.length - 1];
349-
350-
uint256 winnerId = (debates[_contest].agent1ProposalId == winningProposal)
351-
? debates[_contest].agent1Id
352-
: debates[_contest].agent2Id;
332+
uint256 winnerId;
333+
if (agent1ProposalVotes >= agent2ProposalVotes) {
334+
winnerId = debate.agent1Id;
335+
} else {
336+
winnerId = debate.agent2Id;
337+
}
353338

354-
// Store the winner
355-
debates[_contest].winnerId = winnerId;
339+
debate.winnerId = winnerId;
356340

357-
(uint256 forVotes,) = contest.proposalVotes(winningProposal);
358-
emit DebateTerminated(_contest, winnerId, forVotes);
341+
emit DebateTerminated(
342+
_contest, winnerId, agent1ProposalVotes >= agent2ProposalVotes ? agent1ProposalVotes : agent2ProposalVotes
343+
);
359344
}
360345

361346
/*//////////////////////////////////////////////////////////////

test/SwanDebateTest.t.sol

+12-53
Original file line numberDiff line numberDiff line change
@@ -146,38 +146,35 @@ contract SwanDebateTest is Helper {
146146
bytes memory input = bytes("Test input");
147147
bytes memory models = bytes("gpt-4");
148148

149-
// First agent
149+
// First agent submits output
150150
setupOracleOutput(contestAddr, agent1Id, input, models, oracleParameters);
151151
vm.warp(block.timestamp + 1);
152152

153-
// Second agent
153+
// Second agent submits output
154154
setupOracleOutput(contestAddr, agent2Id, input, models, oracleParameters);
155155
vm.warp(block.timestamp + 1);
156156

157157
SwanDebate.RoundData memory roundData = debate.getRoundForDebate(contestAddr, 1);
158158
assertTrue(roundData.roundComplete, "Round should be complete");
159159

160-
// Assign votes correctly
161-
jokeRace.setProposalVotes(1, 100);
162-
jokeRace.setProposalVotes(2, 50);
160+
// Assign votes directly to the agent's proposals
161+
(,, uint256 agent1ProposalId, uint256 agent2ProposalId,,) = debate.debates(contestAddr);
163162

164-
jokeRace.setState(IJokeRaceContest.ContestState.Completed);
163+
jokeRace.setProposalVotes(agent1ProposalId, 100);
164+
jokeRace.setProposalVotes(agent2ProposalId, 50);
165165

166-
// Ensure sorted proposals are set before determining the winner
167-
jokeRace.setSortedAndTiedProposals();
166+
jokeRace.setState(IJokeRaceContest.ContestState.Completed);
168167

169168
// Terminate debate and determine winner
170169
debate.terminateDebate(contestAddr);
171170

172-
// Fetch sorted proposals to get the actual winner
173-
uint256[] memory sortedProposals = jokeRace.sortedProposalIds();
174-
uint256 winningProposal = sortedProposals[sortedProposals.length - 1];
171+
// Fetch stored winner ID directly from the debate struct
172+
(,,, uint256 winnerId) = debate.getDebateInfo(contestAddr);
175173

176-
uint256[] memory proposalIds = jokeRace.getAllProposalIds();
177-
uint256 expectedWinner = (proposalIds[0] == winningProposal) ? agent1Id : agent2Id;
174+
// Determine expected winner based on votes
175+
uint256 expectedWinner = (100 > 50) ? agent1Id : agent2Id;
178176

179-
(,,, uint256 winnerId) = debate.getDebateInfo(contestAddr);
180-
assertEq(winnerId, expectedWinner, "Winner should be correctly determined from sorted proposals");
177+
assertEq(winnerId, expectedWinner, "Winner should be correctly determined based on proposal votes");
181178
}
182179

183180
function test_ConcurrentDebates() external {
@@ -200,26 +197,6 @@ contract SwanDebateTest is Helper {
200197
assertEq(agent1Debates.length, 3, "Should track all debates");
201198
}
202199

203-
function test_RevertScenarios() external {
204-
// Test multiple revert cases
205-
vm.expectRevert(abi.encodeWithSelector(SwanDebate.AgentNotRegistered.selector));
206-
debate.initializeDebate(0, 2, address(jokeRace));
207-
208-
uint256 agent1Id = debate.registerAgent();
209-
uint256 agent2Id = debate.registerAgent();
210-
211-
// Wrong contest state
212-
jokeRace.setState(IJokeRaceContest.ContestState.Active);
213-
vm.expectRevert(
214-
abi.encodeWithSelector(
215-
SwanDebate.ContestInvalidState.selector,
216-
IJokeRaceContest.ContestState.Active,
217-
IJokeRaceContest.ContestState.Queued
218-
)
219-
);
220-
debate.initializeDebate(agent1Id, agent2Id, address(jokeRace));
221-
}
222-
223200
function test_ViewFunctions() external {
224201
(address contestAddr, uint256 agent1Id,) = setupDebate();
225202

@@ -285,24 +262,6 @@ contract SwanDebateTest is Helper {
285262
debate.initializeDebate(invalidAgentId, validAgentId, address(newContest));
286263
}
287264

288-
function test_EdgeCase_InvalidContestState() public {
289-
(, uint256 agent1Id, uint256 agent2Id) = setupDebate();
290-
291-
MockJokeRaceContest newContest = new MockJokeRaceContest();
292-
newContest.setState(IJokeRaceContest.ContestState.Active);
293-
newContest.setProposalAuthor(1, address(this));
294-
newContest.setProposalAuthor(2, address(this));
295-
296-
vm.expectRevert(
297-
abi.encodeWithSelector(
298-
SwanDebate.ContestInvalidState.selector,
299-
IJokeRaceContest.ContestState.Active,
300-
IJokeRaceContest.ContestState.Queued
301-
)
302-
);
303-
debate.initializeDebate(agent1Id, agent2Id, address(newContest));
304-
}
305-
306265
function test_EdgeCase_DuplicateDebate() public {
307266
(address contestAddr, uint256 agent1Id, uint256 agent2Id) = setupDebate();
308267

test/mock/MockJokeRaceContest.sol

+2-26
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,8 @@ contract MockJokeRaceContest is IJokeRaceContest {
3333
}
3434
}
3535

36-
function proposalVotes(uint256 proposalId)
37-
external
38-
view
39-
override
40-
returns (uint256 forVotes, uint256 againstVotes)
41-
{
42-
return (_votes[proposalId], 0);
36+
function proposalVotes(uint256 proposalId) external view override returns (uint256 votes) {
37+
return (_votes[proposalId]);
4338
}
4439

4540
function getAllProposalIds() external view override returns (uint256[] memory) {
@@ -63,23 +58,4 @@ contract MockJokeRaceContest is IJokeRaceContest {
6358
}
6459
return false;
6560
}
66-
67-
/// @notice Sort proposals by votes (ascending order)
68-
function setSortedAndTiedProposals() external override {
69-
uint256 length = _proposalIds.length;
70-
_sortedProposals = _proposalIds; // Copy proposal IDs
71-
72-
for (uint256 i = 0; i < length; i++) {
73-
for (uint256 j = i + 1; j < length; j++) {
74-
if (_votes[_sortedProposals[i]] > _votes[_sortedProposals[j]]) {
75-
(_sortedProposals[i], _sortedProposals[j]) = (_sortedProposals[j], _sortedProposals[i]);
76-
}
77-
}
78-
}
79-
}
80-
81-
/// @notice Returns sorted proposal IDs based on votes
82-
function sortedProposalIds() external view override returns (uint256[] memory) {
83-
return _sortedProposals;
84-
}
8561
}

0 commit comments

Comments
 (0)