Skip to content

Fix issue #14#67

Open
Fiuum1 wants to merge 20 commits intoBreadchainCoop:devfrom
Fiuum1:fix-issue-14
Open

Fix issue #14#67
Fiuum1 wants to merge 20 commits intoBreadchainCoop:devfrom
Fiuum1:fix-issue-14

Conversation

@Fiuum1
Copy link

@Fiuum1 Fiuum1 commented Mar 13, 2026

Hey @RonTuretzky and @exo404,

As requested, this PR implements the solution for Issue #14: the system now uses a 33% contest threshold to trigger a veto.

Here is a technical overview of the modifications I've made, although GitHub already gives us an overview of the modifications:

SafetyNet.sol:

  • 'isContested[]' replaced by 'isVetoed[]'
  • Added 'contestCount' initialization (=0) in new Request creation in '_withdraw()'
  • Added 'contestCount' increment in 'contest()'
  • Removed 'vote()' function
  • Removed 'requestVotes' parameter (mapping)
  • Removed "_isVotingOnGoing()' function
  • Modified 'createRequest()' function, replacing 'yesVotes' and 'noVotes' initialization (=0) with 'contestCount' initialization (=0)
  • Added in 'contest()' a mechanism to check if contestCount is enough (compared to threshold) to reject withdrawal
  • Replaced 'consensusTreshold' parameter in 'SafetyNetCreated' event in 'create()' function with 'creationstruct with 'contestTreshold' parameter
  • Added "emit WithdrawalVetoed()" in contest()
  • Added 'AlreadyContestedByMember()' error in contest()
  • Added 'hasContested' parameter (mapping)
  • Added "if (hasContested[_requestId][msg.sender]) revert AlreadyContestedByMember()" in contest()

ISafetyNet.sol:

  • 'AlreadyContested()' replaced by 'AlreadyVetoed()'
  • Removed 'WithdrawalContested()' event
  • Removed 'yesVotes' e 'noVotes', replaced by 'contestCount'
  • Removed 'vote()' interface
  • Removed 'Voted()' event
  • Removed 'AlreadyVoted()' error
  • Removed 'NotAllVoted()' error
  • Removed 'votingWindow' parameter from 'SafetyNet' struct
  • Modified 'RequestEnded()' event
  • Removed 'VotingWindowsClosed()' error
  • Replaced 'consensusTreshold' parameter in 'SafetyNet' struct with 'contestTreshold' parameter, representing the percentage of members who contest required to reject a request
  • Added 'WithdrawalVetoed()' event
  • Added 'AlreadyContestedByMember()' error

All tests (Unit and Fuzz) have been updated and pass successfully.

Looking forward to your feedback!
Fabio

@Fiuum1
Copy link
Author

Fiuum1 commented Mar 13, 2026

P.S: Sorry but I forgot to remove modifications.txt from src/contracts/

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the SafetyNet withdrawal-request governance flow from a vote-based mechanism to a contest/veto-based mechanism, updating the core contract interface and aligning unit/fuzz tests with the new request model.

Changes:

  • Replace request voting (yes/no votes + voting window) with contest counting and a veto threshold.
  • Update ISafetyNet structs/events/errors and the SafetyNet contract storage/execution logic to match the contest/veto flow.
  • Remove voting-focused fuzz tests and add new fuzz coverage for contesting/veto boundaries and timeout behavior.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
test/unit/SafetyNetUnit.sol Updates unit tests to use contestThreshold, contestCount, and veto semantics.
test/invariants/fuzz/SafetyNetFuzzBase.t.sol Updates fuzz default config to use contest-based parameters (removes voting window defaults).
test/invariants/fuzz/SafetyNetFuzz_RequestsVoting.t.sol Removes the voting-oriented fuzz suite.
test/invariants/fuzz/SafetyNetFuzz_RequestsContesting.t.sol Adds contest/veto-focused fuzz scenarios and threshold-boundary properties.
test/invariants/fuzz/SafetyNetFuzz_DepositWithdraw.t.sol Updates request struct destructuring for the new Request layout.
test/invariants/fuzz/SafetyNetFuzz_Create.t.sol Updates creation fuzzing to vary contestThreshold instead of consensus/voting fields.
src/interfaces/ISafetyNet.sol Renames/reshapes config and request fields/events/errors to reflect contest/veto instead of voting.
src/contracts/SafetyNet.sol Implements contest counting + vetoing, removes voting state and vote execution path.
src/contracts/modification.txt Adds an empty file under contracts (no content).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@exo404
Copy link
Contributor

exo404 commented Mar 14, 2026

@Fiuum1 please solve every copilot issue in a separate commit and replay to every comment with the commit ID

@Fiuum1
Copy link
Author

Fiuum1 commented Mar 15, 2026

@exo404 All done! Lmk if I need to do anything else.

@exo404
Copy link
Contributor

exo404 commented Mar 17, 2026

lgtm @RonTuretzky @Fiuum1

@exo404 exo404 requested review from RonTuretzky and exo404 March 17, 2026 17:25
@exo404 exo404 added the enhancement New feature or request label Mar 17, 2026
@Fiuum1
Copy link
Author

Fiuum1 commented Mar 17, 2026

lgtm @RonTuretzky

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the SafetyNet withdrawal flow to match Issue #14 by removing the voting phase and instead vetoing a withdrawal request if more than a configured percentage of members contest it (defaulted to 33% in tests).

Changes:

  • Replaced request voting (yes/no votes + voting window) with a contest counter and veto logic based on contestThreshold.
  • Updated unit + fuzz/invariant tests to exercise contest/veto behavior and removed the prior voting-oriented fuzz suite.
  • Updated the public interface (ISafetyNet) to reflect the new request fields and events.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/contracts/SafetyNet.sol Implements contestCount + veto threshold logic; removes voting; introduces isVetoed and hasContested.
src/interfaces/ISafetyNet.sol Updates structs/events/errors to remove voting and add veto/contesting semantics.
test/unit/SafetyNetUnit.sol Updates unit tests for new contest/veto behavior and request struct shape.
test/invariants/fuzz/SafetyNetFuzzBase.t.sol Updates fuzz defaults to use contestThreshold and removes voting window config.
test/invariants/fuzz/SafetyNetFuzz_DepositWithdraw.t.sol Adjusts request destructuring/assertions for contestCount.
test/invariants/fuzz/SafetyNetFuzz_Create.t.sol Renames params and switches fuzz configuration to contestThreshold.
test/invariants/fuzz/SafetyNetFuzz_RequestsVoting.t.sol Removed (legacy voting-focused fuzz tests).
test/invariants/fuzz/SafetyNetFuzz_RequestsContesting.t.sol Added fuzz tests for contest threshold boundary + sybil/double-contest + timeout behavior.
src/contracts/modification.txt Empty file added/modified.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Fix contest threshold integer division rounding: multiply contestCount
  by PERCENTAGE_BASE instead of dividing the right-hand side, preventing
  truncation from silently lowering the effective veto threshold
- Change _deduct visibility from private to internal for consistency
  with other helper functions
- Fix gendered language in AlreadyContestedByMember NatSpec
- Remove empty src/contracts/modification.txt
@RonTuretzky
Copy link
Contributor

@Fiuum1 please review https://github.com/Fiuum1/safety-net/pull/1/changes

@Fiuum1
Copy link
Author

Fiuum1 commented Mar 23, 2026

Hey @RonTuretzky,

I have completed all the fixes. Please let me know if there is anything else I should do.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the SafetyNet withdrawal flow to remove request voting and instead support a contest-based veto: withdrawals above autoThreshold are auto-executed after the contest window unless contests exceed a configurable percentage threshold, in which case the request is vetoed.

Changes:

  • Replaced vote-based approval with contestCount-based veto logic using a contestThreshold percentage.
  • Updated ISafetyNet and SafetyNet to reflect the new request struct/events/errors and removed the voting window API surface.
  • Refactored and replaced fuzz/unit tests to cover contest threshold boundary behavior and veto behavior.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/contracts/SafetyNet.sol Implements per-member contest tracking and veto threshold logic; removes voting execution path.
src/interfaces/ISafetyNet.sol Updates structs/events/errors for contest/veto model and removes voting-related declarations.
test/unit/SafetyNetUnit.sol Updates unit tests for new contest/veto semantics and request struct shape.
test/invariants/fuzz/SafetyNetFuzzBase.t.sol Updates fuzz default config constants/struct fields to use contestThreshold and removes voting window config.
test/invariants/fuzz/SafetyNetFuzz_RequestsVoting.t.sol Removes voting-focused fuzz tests that no longer apply.
test/invariants/fuzz/SafetyNetFuzz_RequestsContesting.t.sol Adds new fuzz coverage for contest threshold boundaries, veto behavior, and contest window behavior.
test/invariants/fuzz/SafetyNetFuzz_DepositWithdraw.t.sol Updates request destructuring and invariants to validate contestCount initialization.
test/invariants/fuzz/SafetyNetFuzz_Create.t.sol Updates creation fuzzing to randomize contestThreshold instead of consensus threshold.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +318 to 331
function test_CreateWhenContestThresholdIsZero() external {
_allowToken(address(_token));
ISafetyNet.SafetyNet memory _safetyNet = _defaultSafetyNet(address(_token));
_safetyNet.consensusThreshold = 0;
_safetyNet.contestThreshold = 0;
uint256 id = _sn.create(_safetyNet);
assertEq(id, 0);
}

function test_CreateWhenConsensusThresholdIsGreaterThan100() external {
function test_CreateWhenContestThresholdIsGreaterThan100() external {
_allowToken(address(_token));
ISafetyNet.SafetyNet memory _safetyNet = _defaultSafetyNet(address(_token));
_safetyNet.consensusThreshold = 150;
_safetyNet.contestThreshold = 150;
uint256 id = _sn.create(_safetyNet);
assertEq(id, 0);
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are named as if contestThreshold values of 0 or >100 are invalid, but they don’t assert any failure mode (they only check id == 0, which will be true for the first create() call even if creation succeeds). Either add an explicit expectation (e.g., revert / no state changes) and enforce the constraint in create(), or rename the tests to reflect the actual intended behavior for out-of-range thresholds.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RonTuretzky This tests are modeled based on the previous one created on vote() function, they were already like this...

Fiuum1 and others added 2 commits March 25, 2026 11:31
…et.sol

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants