Votes trait is not bound to the token contract type
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 35/100
Direzione di ricerca
Start with packages/governance/src/votes/mod.rs and the fungible and non-fungible composition modules named in the issue; compare their trait bounds and contract-type markers. The issue outlines two incomplete approaches and says to address this during the planned extension restructure, but does not settle a complete design. Done means preventing the unbounded token implementation while preserving the intended reusable votes interface and validating the cross-contract call behavior.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Description
Every token extension trait is tied to the contract type through its bound. For example, FungibleAllowList: FungibleToken<ContractType: AllowListContractType> and NonFungibleEnumerable: NonFungibleToken<ContractType: EnumerableContractType>. Implementing one of these traits without the matching entry in the Compose<(...)> list does not compile, and both composition modules (fungible/extensions/combinations/mod.rs, non_fungible/extensions/combinations/mod.rs) document this guarantee.
Votes is the exception. It is declared in stellar-governance (packages/governance/src/votes/mod.rs) with no supertrait and no bound. So the following compiles:
#[contractimpl(contracttrait)]
impl FungibleToken for MyToken {
type ContractType = Compose<(AllowList,)>; // no FungibleVotes
}
#[contractimpl(contracttrait)]
impl Votes for MyToken {}
Transfers, mints and burns never call transfer_voting_units, so no checkpoint is ever written. get_votes and get_votes_at_checkpoint return 0 for every account, and delegate succeeds while moving nothing. The contract type is fixed at compile time, so this holds for the whole life of the contract.
This was raised as L-03 in the latest audit.
The bound cannot simply be added to Votes: stellar-tokens depends on stellar-governance, so governance cannot name FungibleToken, NonFungibleToken, or a tokens-side marker trait without a dependency cycle.
Potential solutions
A. Move the trait to tokens, keep only storage in governance
- Governance keeps the votes storage functions, errors (4100 block) and events, but no longer declares a
Votestrait. A small client-only interface stays so the Governor can still callget_votes_at_checkpointon the token. - Tokens defines
FungibleVotes: FungibleToken<ContractType: VotesContractType>andNonFungibleVotes: NonFungibleToken<ContractType: VotesContractType>, with default bodies calling the governance storage functions. - The contract types are renamed to
Votes(matchingAllowList,Enumerable, ...), andVotesContractTypeis implemented byVotesand the existing*Votescombined types.
Contract author:
type ContractType = Compose<(AllowList, Votes)>;
#[contractimpl(contracttrait)]
impl FungibleVotes for MyToken {}
Advantages
- Token contracts can only get the votes functions through a bounded trait, so the L-03 scenario fails to compile.
- The "rejected by that trait's bound" claim in both composition modules holds without exceptions.
- Votes follows the same naming and structure as the other extensions.
Disadvantages
- Contracts that are not tokens (staking contracts, custom voting-power sources) lose the ready-made trait. They have to write the votes functions themselves on top of the storage functions.
- Breaking change:
impl Votes for X {}becomesimpl FungibleVotes for X {}, and theFungibleVotes/NonFungibleVotescontract types are renamed.
B. Body-less interface in governance, bounded traits in tokens
- Governance replaces the
#[contracttrait] Voteswith a body-less#[contractclient(name = "VotesClient")] pub trait VotesInterfacethat declares all six votes functions (the counterpart of Solidity'sIVotes). This follows the existingUpgradeable/ClaimIssuerpattern. Storage, errors and events are unchanged. - Tokens adds the same bounded
FungibleVotes/NonFungibleVotestraits, contract type rename andVotesContractTypemarker as in A.
Advantages
- Governance still publishes the full votes interface that any voting source should expose, so non-token contracts keep a reference to implement against.
governor/storage.rsonly changes an import.- An empty
impl VotesInterface for X {}no longer compiles, since there are no default bodies.
Disadvantages
- It does not close the gap for tokens. A token can still implement
VotesInterfacedirectly, writing bodies that forward to the governance storage functions, withoutVotesin itsComposelist. The result is the same silent-zero behavior as today, just with more code to write. - The function signatures live in two places (governance interface and tokens traits), with no compile-time check that they match. A mismatch only shows up as a failed cross-contract call at runtime, so it needs a test that calls a
FungibleVotestoken throughVotesClient. - Same breaking change for token authors as A.
Summary
Neither option is complete: A gives full type-safety for tokens but drops the reusable trait for non-token contracts, and B keeps that reusability but leaves the unbounded path open for tokens.
Reminder for the restructure
We plan to make some extensions reusable across fungible and non-fungible by moving their business logic (storage functions) to a shared location (e.g. contract-utils), while keeping the traits per token type. When that restructure happens, this issue should be addressed as part of it, since votes is the same shape of problem: shared storage logic, with per-token-type traits that carry the contract type bound.
- Lingua principale
- Rust
- Stelle
- 97
- Fork
- 75
- Merge medio
- 1g 1h
- PR unite (30g)
- 8
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di OpenZeppelin/stellar-contracts
-
Confidential Token: specs disagree with the code in a few placesForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
OpenZeppelin/stellar-contracts#949 ·
I maintainer di solito rispondono entro 1 giorno
-
🐞 [Bug]: Example identity registry does not export CountryDataManager default gettersForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
OpenZeppelin/stellar-contracts#907 · 4 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 1-3 ore Idoneità per principianti 72/100
OpenZeppelin/stellar-contracts#833 ·
I maintainer di solito rispondono entro 1 giorno
-
Policies: document that policies own the signer check, and add a test harness for custom policiesAperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 30/100
OpenZeppelin/stellar-contracts#975 ·
I maintainer di solito rispondono entro 1 giorno
-
Spending-limit policy: keep the window in a fixed-size entry instead of a per-payment historyAperta
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
OpenZeppelin/stellar-contracts#974 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di OpenZeppelin/stellar-contracts
Issue simili
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 62/100
-
bug UI
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
wardian-app/Wardian#1746 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
jlcodes99/cockpit-tools#3125 ·
I maintainer di solito rispondono entro 2 giorni