Skip to content

Allow configurable quorum parameters via Skipper proposals #58

@ya7on

Description

@ya7on

Is your feature request related to a problem

Currently, the quorum logic is hardcoded:

  • PROPOSAL_ACCEPT_THRESHOLD = 300000 jettons
  • PROPOSAL_VOTES_GAP = 10000 jettons

This approach doesn't scale across different tokens with different total supplies. In some cases, 300k tokens is a trivial amount — allowing anyone with that many tokens to pass any proposal, even in a weakly participating DAO.

To ensure the protocol is adaptable to different communities, we need to make these values configurable.

Describe the solution you'd like

We want to introduce governance-controlled protocol parameters:

  • PROPOSAL_ACCEPT_THRESHOLD (min YES votes required to pass)
  • PROPOSAL_VOTES_GAP (min YES–NO vote difference to pass)

These should be stored onchain inside the Skipper contract.

Suggested approach:

  • Store parameters in a Map<Int, Int>
  • Use sha256("param_name") as the key (e.g. sha256("PROPOSAL_ACCEPT_THRESHOLD"))
  • Default values are still used until overwritten

Changes to these parameters can only be done via an onchain proposal:

  • Skipper must be able to send a message to itself
  • Add a special receiver handler for internal config updates
  • Only accept updates when the sender is Skipper itself (self-call check)

⚠️ Open question: How to initialize parameters?

It's unclear how the initial quorum parameters (e.g. PROPOSAL_ACCEPT_THRESHOLD) should be set safely at the time of DAO deployment.

If we allow the deployer to specify custom values at initialization, they could immediately set values that soft-lock the DAO — for example, by making the acceptance threshold higher than the total token supply. This would render all future proposals unpassable.

Even if we disable parameter overrides during deployment and rely on defaults (e.g., 300,000 YES votes), there's still a critical vulnerability:

In tokens with large supply and low capitalization, it's often easy for one person to acquire enough tokens to meet the default threshold.

This means an attacker could:

  • Deploy a DAO linked to such a token
  • Use their tokens to pass the first proposal while the DAO is still inactive
  • Change PROPOSAL_ACCEPT_THRESHOLD to a value higher than the current or even total supply
  • Effectively freeze the DAO forever (unless a hard fork is done)

💡 This scenario is dangerous even if no malicious intent is present — it can occur unintentionally with meme tokens or test deployments.

We need a secure, permissionless, but grief-resistant mechanism for parameter governance from day one.

✅ Potential mitigation: multiple DAOs per Jetton using nonce

One way to avoid the soft-lock vulnerability is to allow multiple DAOs to be deployed for the same Jetton Master.

Currently, the Skipper contract enforces a 1:1 mapping:

Jetton Master → DAO (Skipper)

This creates a critical risk: if someone deploys a DAO with a broken configuration (e.g. very high PROPOSAL_ACCEPT_THRESHOLD), the entire governance process becomes permanently stuck for that jetton.

Solution:
Introduce an additional parameter nonce: Int in Skipper’s init() function.

This makes the deployment address depend not only on the Jetton Master, but also on the nonce, which breaks the 1:1 constraint:

Skipper(jetton_master, nonce)

If a malicious or misconfigured DAO is deployed, the community can simply deploy a new one:

JETTON_MASTER=... NONCE=2 npx blueprint run deploySkipper

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestquestionFurther information is requested

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions