Transaction

3BA1F3D0E0AAAC…14D34344D8E6

Block 77,261 · index 0 · indexed

Summary

Hash
3BA1F3D0E0AAACBCD2663477F4AAB8A57D4DFCD7D88114772F3B14D34344D8E6
Block
77,261
Size
132948 bytes
Gas used
164,924,778 / 197,909,674
Fee
197910 ugnot
Status
success

Messages

#1AddPackagegno.land/r/gnoswap/gov/governance24 arguments

Arguments · 24

  1. #1governance
  2. #2README.md
  3. #3# Governance Decentralized protocol governance via GNS staking and voting. ## Overview Governance enables GNS holders to stake through `gov/staker`, receive xGNS, delegate voting power, create proposals, and vote on protocol changes. For more details, check out [docs](https://docs.gnoswap.io/core-concepts/governance). ## Configuration The `governance.Config` type defines the governance parameters. The values used by a proposal are stored with that proposal; later reconfiguration does not rewrite an existing proposal. The current configuration can be changed through the governance `Reconfigure` handler. This type can be found in [config.gno](./config.gno). | Field | Description | Default | |-------|-------------|---------| | `VotingStartDelay` | Delay before voting starts after proposal creation | 1 day | | `VotingPeriod` | Duration for collecting votes | 7 days | | `VotingWeightSmoothingDuration` | Duration used for timestamp-based voting-weight averaging | 1 day | | `Quorum` | Percentage of total xGNS supply required for proposal passage; total supply includes launchpad-held issuance | 50% | | `ProposalCreationThreshold` | Minimum xGNS balance required to create a proposal | 1,000,000,000 xGNS | | `ExecutionDelay` | Waiting period after voting ends before execution | 1 day | | `ExecutionWindow` | Time window during which an approved proposal can be executed | 30 days | All values are configurable; the values above are the defaults in `NewDefaultConfig`. ## Core Mechanics ### Staking Flow ```plain GNS → Delegate → xGNS + delegated voting history → Vote ``` 1. Delegate GNS through `gov/staker` to receive an equal amount of xGNS. 2. Assign voting power to a delegatee (which may be the delegator itself). 3. Vote on proposals with the delegatee's timestamped delegation weight. 4. Undelegation removes voting power immediately; the default lockup before collecting GNS is 7 days and is configurable. Launchpad-backed xGNS is included in total xGNS supply for quorum, but is not an ordinary user delegation record. ### Proposal Types - **Text**: Signal proposals without execution. - **CommunityPoolSpend**: Treasury disbursements encoded as a community-pool transfer on execution. - **ParameterChange**: Protocol parameter updates dispatched to registered handlers. ## Proposal Lifecycle ### Creation - Requires the configured `ProposalCreationThreshold` xGNS balance (1,000,000,000 xGNS by default). - One active proposal per address. - Valid type and parameters are required. Community-pool spend amounts must be strictly positive, recipients must be valid, and token paths must be registered. - A proposal stores its configuration version, creation timestamp, creation block height, quorum amount, and timestamp used for historical delegation lookup. The block height is metadata; voting-weight lookup is timestamp-based. ### Voting - Voting starts after the configured start delay (1 day by default) and runs for the configured voting period (7 days by default). - Weight is the average of the caller's delegation at the proposal's stored snapshot timestamp and at proposal creation time. The snapshot timestamp is `createdAt - VotingWeightSmoothingDuration` (clamped at zero), and the smoothing duration defaults to 24 hours. - Each address can vote only once on a proposal. `Vote` returns the applied vote weight as a decimal string. ### Execution A proposal is considered valid and executable when: - The voting period has ended. - Total votes meet the quorum amount computed at creation from the total xGNS supply (including launchpad-held issuance) and the proposal's configured quorum percentage. - `YES` votes strictly exceed `NO` votes (ties do not pass). - The configured execution delay (1 day by default) has passed after voting ends. - Execution occurs within the configured execution window (30 days by default). - Text proposals are informational and cannot be executed; anyone can trigger execution of an approved executable proposal. An approved community-pool spend can still fail at execution if the pool no longer has enough of the registered token. ## Technical Details ### Vote Weight Calculation ```go // `smoothing` is the proposal's configured VotingWeightSmoothingDuration. snapshotTime = max(createdAt - smoothing, 0) weightAtSnapshot = getDelegationAt(voter, snapshotTime) weightAtCreation = getDelegationAt(voter, createdAt) voteWeight = (weightAtSnapshot + weightAtCreation) / 2 ``` The lookups read delegation history by Unix timestamp. This is not a block-height snapshot. ### Quorum Calculation ```go quorumWeight = totalXGnsSupplyAtProposalCreation // includes launchpad-held xGNS quorumAmount = quorumWeight * quorumPercent / 100 // quorumPercent defaults to 50 ``` The quorum amount is stored on the proposal and is not recomputed from the proposer's or voters' smoothed voting weight. A proposal passes only when total votes reach quorum and accumulated `YES` votes strictly exceed accumulated `NO` votes. ### Rewards Distribution Gov/staker exposes two reward streams: 1. **GNS emission rewards** use the emission accumulator and each staker's own stake history. 2. **Protocol-fee rewards** are tracked per token and accrual epoch. Each consumed bucket is divided by the total stake in force during that epoch, added to that token's Q128 accumulator, and settled over the staker's stake-event segments. Sub-unit Q128 remainders are retained for later collection. `CollectReward` settles the emission stream and every known protocol-fee token. `CollectEmissionReward` and `CollectProtocolFeeReward(tokenPath)` are narrower paths; the token-specific protocol-fee path bounds both pending accrual buckets and stake events per call, so remaining work is collected later. Launchpad project wallets use the corresponding launchpad-only entry points. ## Usage These snippets call the public domain proxies from a realm function with a current `cur` token. Import the corresponding proxy packages and qualify their function names in integrating code. ```go // Through gov/staker: delegate GNS for xGNS voting power. Delegate(cross(cur), delegatee, 1_000_000_000, "g1referrer...") // Create a text or community-pool proposal. ProposeText(cross(cur), "Title", "Description") ProposeCommunityPoolSpend(cross(cur), "Title", "Description", recipient, tokenPath, amount) // A parameter-change execution uses a registered handler. This is one valid // Reconfigure message (all seven parameters are required). execution := "gno.land/r/gnoswap/gov/governance*EXE*Reconfigure*EXE*86400,604800,86400,50,1000000000,86400,2592000" ProposeParameterChange(cross(cur), "Update config", "Rationale", 1, execution) // Vote; the return value is the applied weight formatted as a decimal string. voteWeight := Vote(cross(cur), proposalId, true) // YES // Execute after the configured timelock and then, if needed, start undelegation. Execute(cross(cur), proposalId) Undelegate(cross(cur), delegatee, 250_000_000) // Collect only after the configured undelegation lockup has expired. CollectUndelegatedGns(cross(cur)) ``` ## Security - Timestamp-based smoothing reduces flash-loan-style voting manipulation; it is not a block snapshot. - Sybil resistance comes from stake-weighted delegation. - The execution delay and window constrain when approved executable proposals can run. - A single active proposal is allowed per proposer address. - Quorum is fixed from the creation-time total xGNS supply, including launchpad-held issuance. - Community-pool balance is checked when the approved transfer executes, not when the proposal is created.
  4. #4accessor.gno
  5. #5package governance import ( "gno.land/r/gnoswap/gov/staker" ) type govStakerAccessor struct{} // GetTotalDelegationAmountAtSnapshot forwards an aggregate delegation-history lookup. // // Parameters: // - snapshotTime: Unix timestamp at or before which to select the latest total-delegation entry. // // Returns: // - int64: aggregate delegated amount at or before snapshotTime. // - bool: true when a qualifying history entry exists; false otherwise. func (g *govStakerAccessor) GetTotalDelegationAmountAtSnapshot(snapshotTime int64) (int64, bool) { return staker.GetTotalDelegationAmountAtSnapshot(snapshotTime) } // GetUserDelegationAmountAtSnapshot forwards a user's delegation-history lookup. // // Parameters: // - userAddr: Delegator address whose historical amount is queried. // - snapshotTime: Unix timestamp at or before which to select the latest user entry. // // Returns: // - int64: user's delegated amount at or before snapshotTime. // - bool: true when a qualifying history entry exists; false otherwise. func (g *govStakerAccessor) GetUserDelegationAmountAtSnapshot(userAddr address, snapshotTime int64) (int64, bool) { return staker.GetUserDelegationAmountAtSnapshot(userAddr, snapshotTime) } // GetTotalxGnsSupply returns the total xGNS supply reported by the staker realm. // // Returns: // - int64: total xGNS supply, including launchpad-held xGNS. func (g *govStakerAccessor) GetTotalxGnsSupply() int64 { return staker.GetTotalxGnsSupply() } func newGovStakerAccessor() GovStakerAccessor { return &govStakerAccessor{} }
  6. #6config.gno
  7. #7package governance import ( "errors" bptree "gno.land/p/nt/bptree/v0" ) // Config represents the configuration of the governor contract. // All parameters can be modified through Reconfigure by admin or governance. type Config struct { // VotingStartDelay is the delay before voting starts after proposal creation (in seconds) VotingStartDelay int64 // VotingPeriod is the duration during which votes are collected (in seconds) VotingPeriod int64 // VotingWeightSmoothingDuration is the period over which voting weight is averaged // for proposal creation and cancellation threshold calculations (in seconds). VotingWeightSmoothingDuration int64 // Quorum is the percentage of total xGNS supply required for proposal approval. // Total supply includes xGNS held by the launchpad. Quorum int64 // ProposalCreationThreshold is the minimum xGNS amount required to create a proposal ProposalCreationThreshold int64 // ExecutionDelay is the waiting period after voting ends before a proposal can be executed (in seconds) ExecutionDelay int64 // ExecutionWindow is the time window during which an approved proposal can be executed (in seconds) ExecutionWindow int64 } // IsValid reports whether the configuration's durations, threshold, quorum, and // cumulative schedule values satisfy the governance validation constraints. // // Parameters: // - currentTime: current time value included when checking that the cumulative schedule does not become negative // // Returns: // - error: nil when all fields and cumulative values are valid; otherwise an error describing the first invalid value func (c Config) IsValid(currentTime int64) error { if c.VotingStartDelay < 0 { return errors.New("votingStartDelay cannot be negative") } if c.VotingPeriod < 0 { return errors.New("votingPeriod cannot be negative") } if c.ExecutionDelay < 0 { return errors.New("executionDelay cannot be negative") } if c.ExecutionWindow < 0 { return errors.New("executionWindow cannot be negative") } if c.VotingWeightSmoothingDuration < 0 { return errors.New("votingWeightSmoothingDuration cannot be negative") } if c.ProposalCreationThreshold < 0 { return errors.New("proposalCreationThreshold cannot be negative") } if c.Quorum < 0 || c.Quorum > 100 { return errors.New("quorum must be between 0 and 100") } sum := int64(0) sum += c.VotingStartDelay if sum < 0 { return errors.New("votingStartDelay cannot be negative") } sum += c.VotingPeriod if sum < 0 { return errors.New("votingPeriod cannot be negative") } sum += c.ExecutionDelay if sum < 0 { return errors.New("executionDelay cannot be negative") } sum += c.ExecutionWindow if sum < 0 { return errors.New("executionWindow cannot be negative") } sum += currentTime if sum < 0 { return errors.New("total delay cannot be negative") } return nil } // NewConfig constructs a governance configuration from the supplied delays, // thresholds, quorum percentage, and execution window. // // Parameters: // - votingStartDelay: delay from proposal creation until voting opens, in seconds // - votingPeriod: duration for which voting remains open, in seconds // - votingWeightSmoothingDuration: interval used to smooth delegation weight, in seconds // - quorum: required approval percentage of total xGNS supply, from 0 through 100 // - proposalCreationThreshold: minimum xGNS amount required to create a proposal // - executionDelay: delay after voting ends before execution, in seconds // - executionWindow: duration after the execution delay during which execution is allowed, in seconds // // Returns: // - Config: configuration value populated with the supplied governance parameters func NewConfig( votingStartDelay, votingPeriod, votingWeightSmoothingDuration, quorum, proposalCreationThreshold, executionDelay, executionWindow int64, ) Config { return Config{ VotingStartDelay: votingStartDelay, VotingPeriod: votingPeriod, VotingWeightSmoothingDuration: votingWeightSmoothingDuration, Quorum: quorum, ProposalCreationThreshold: proposalCreationThreshold, ExecutionDelay: executionDelay, ExecutionWindow: executionWindow, } } // NewConfigPtr constructs a Config and returns a pointer to it. The Config is // allocated within the governance domain realm, satisfying realm allocation // checks for callers (such as tests) that require a *Config value. // // Parameters: // - votingStartDelay: delay from proposal creation until voting opens, in seconds // - votingPeriod: duration for which voting remains open, in seconds // - votingWeightSmoothingDuration: interval used to smooth delegation weight, in seconds // - quorum: required approval percentage of total xGNS supply, from 0 through 100 // - proposalCreationThreshold: minimum xGNS amount required to create a proposal // - executionDelay: delay after voting ends before execution, in seconds // - executionWindow: duration after the execution delay during which execution is allowed, in seconds // // Returns: // - *Config: pointer to a configuration value populated with the supplied governance parameters func NewConfigPtr( votingStartDelay, votingPeriod, votingWeightSmoothingDuration, quorum, proposalCreationThreshold, executionDelay, executionWindow int64, ) *Config { c := NewConfig( votingStartDelay, votingPeriod, votingWeightSmoothingDuration, quorum, proposalCreationThreshold, executionDelay, executionWindow, ) return &c } // NewDefaultConfig returns the governance configuration's built-in defaults: // one day before voting, seven days of voting, one day of weight smoothing, // 50% quorum, a 1-billion-xGNS creation threshold, one day execution delay, // and a 30-day execution window. // // Returns: // - Config: default governance configuration value func NewDefaultConfig() Config { return Config{ VotingStartDelay: 86400, // 1 day - delay before voting starts VotingPeriod: 604800, // 7 days - duration for collecting votes VotingWeightSmoothingDuration: 86400, // 1 day - period for averaging voting weight Quorum: 50, // 50% of total xGNS supply required ProposalCreationThreshold: 1_000_000_000, // 1 billion xGNS - minimum amount to create proposals ExecutionDelay: 86400, // 1 day - waiting period before execution ExecutionWindow: 2592000, // 30 days - window for executing proposals } } // NewConfigTree creates an empty BPTree used to index configuration values by // their encoded int64 version. // // Returns: // - *bptree.BPTree: empty configuration index tree func NewConfigTree() *bptree.BPTree { return bptree.NewBPTreeN(16) }
  8. #8counter.gno
  9. #9package governance // Counter manages unique incrementing IDs. type Counter struct { id int64 } // NewCounter creates a new Counter whose current ID is initialized to zero. // // Returns: // - *Counter: counter initialized with current ID 0 func NewCounter() *Counter { return &Counter{ id: 0, } } // Get returns the counter's current ID without changing it. // // Returns: // - int64: currently stored counter ID func (c *Counter) Get() int64 { return c.id } // Set replaces the counter's current ID with id. // // Parameters: // - id: new current ID to store; the value is not incremented func (c *Counter) Set(id int64) { c.id = id } // Next increments the counter and returns the resulting ID. // // Returns: // - int64: incremented counter ID after the update func (c *Counter) Next() int64 { c.id++ return c.id }
  10. #10doc.gno
  11. #11// Package governance implements proposal lifecycle management and voting. // It supports text proposals, parameter changes, and community-pool spending. // Voting uses timestamped delegation history and quorum from total xGNS supply // (including launchpad-held xGNS); proposal timing and thresholds are configurable. package governance
  12. #12getters.gno
  13. #13package governance import ( rotree "gno.land/p/nt/bptree/rotree/v0" ) // ================================== // Store Data Getters // ================================== // GetLatestConfigVersion returns the current governance configuration version. // // Returns: // - int64: latest configuration version stored by governance func GetLatestConfigVersion() int64 { return getImplementation().GetLatestConfigVersion() } // GetCurrentProposalID returns the current proposal ID counter. // // Returns: // - int64: current proposal ID counter used for newly created proposals func GetCurrentProposalID() int64 { return getImplementation().GetCurrentProposalID() } // GetMaxSmoothingPeriod returns the maximum smoothing period for delegation history cleanup. // // Returns: // - int64: maximum permitted smoothing period in seconds func GetMaxSmoothingPeriod() int64 { return getImplementation().GetMaxSmoothingPeriod() } // ================================== // Config Getters // ================================== // GetLatestConfig returns the latest governance configuration. // // Returns: // - Config: latest stored configuration for the current version // - error: nil on success, or an error when the current configuration is missing func GetLatestConfig() (Config, error) { return getImplementation().GetLatestConfig() } // GetConfig returns a specific governance configuration by version. // // Parameters: // - configVersion: configuration version to retrieve // // Returns: // - Config: configuration stored under configVersion // - error: nil on success, or an error when configVersion is not found func GetConfig(configVersion int64) (Config, error) { return getImplementation().GetConfig(configVersion) } // ================================== // Proposal Getters // ================================== // GetProposals returns a read-only view of every proposal, keyed by the decimal // string form of the proposal ID. Callers paginate it themselves through // IterateByOffset. Reading an entry yields a clone, so the view cannot mutate // realm state. // // Returns: // - *rotree.ReadOnlyTree: read-only proposal tree keyed by decimal proposal ID func GetProposals() *rotree.ReadOnlyTree { return getImplementation().GetProposals() } // ExistsProposal checks whether a proposal is stored. // // Parameters: // - proposalID: proposal identifier to look up // // Returns: // - bool: true when proposalID is stored, otherwise false func ExistsProposal(proposalID int64) bool { return getImplementation().ExistsProposal(proposalID) } // GetProposerByProposalId returns the proposer address of a proposal. // // Parameters: // - proposalId: proposal identifier to look up // // Returns: // - address: address that submitted the proposal // - error: nil on success, or an error when the proposal does not exist func GetProposerByProposalId(proposalId int64) (address, error) { return getImplementation().GetProposerByProposalId(proposalId) } // GetProposalTypeByProposalId returns the type of a proposal. // // Parameters: // - proposalId: proposal identifier to look up // // Returns: // - ProposalType: type recorded for the proposal // - error: nil on success, or an error when the proposal does not exist func GetProposalTypeByProposalId(proposalId int64) (ProposalType, error) { return getImplementation().GetProposalTypeByProposalId(proposalId) } // GetYeaByProposalId returns the yes vote weight of a proposal. // // Parameters: // - proposalId: proposal identifier to inspect // // Returns: // - int64: total voting weight recorded for yes votes // - error: nil on success, or an error when the proposal does not exist func GetYeaByProposalId(proposalId int64) (int64, error) { return getImplementation().GetYeaByProposalId(proposalId) } // GetNayByProposalId returns the no vote weight of a proposal. // // Parameters: // - proposalId: proposal identifier to inspect // // Returns: // - int64: total voting weight recorded for no votes // - error: nil on success, or an error when the proposal does not exist func GetNayByProposalId(proposalId int64) (int64, error) { return getImplementation().GetNayByProposalId(proposalId) } // GetConfigVersionByProposalId returns the config version used by a proposal. // // Parameters: // - proposalId: proposal identifier to inspect // // Returns: // - int64: governance configuration version captured by the proposal // - error: nil on success, or an error when the proposal does not exist func GetConfigVersionByProposalId(proposalId int64) (int64, error) { return getImplementation().GetConfigVersionByProposalId(proposalId) } // GetQuorumAmountByProposalId returns the quorum requirement for a proposal. // // Parameters: // - proposalId: proposal identifier to inspect // // Returns: // - int64: minimum voting weight required for the proposal's quorum // - error: nil on success, or an error when the proposal does not exist func GetQuorumAmountByProposalId(proposalId int64) (int64, error) { return getImplementation().GetQuorumAmountByProposalId(proposalId) } // GetTitleByProposalId returns the title of a proposal. // // Parameters: // - proposalId: proposal identifier to inspect // // Returns: // - string: proposal title // - error: nil on success, or an error when the proposal does not exist func GetTitleByProposalId(proposalId int64) (string, error) { return getImplementation().GetTitleByProposalId(proposalId) } // GetDescriptionByProposalId returns the description of a proposal. // // Parameters: // - proposalId: proposal identifier to inspect // // Returns: // - string: proposal description // - error: nil on success, or an error when the proposal does not exist func GetDescriptionByProposalId(proposalId int64) (string, error) { return getImplementation().GetDescriptionByProposalId(proposalId) } // GetProposalStatusByProposalId returns the current status of a proposal. // // Parameters: // - proposalId: proposal identifier to inspect // // Returns: // - string: status computed from the proposal and the current Unix time // - error: nil on success, or an error when the proposal does not exist func GetProposalStatusByProposalId(proposalId int64) (string, error) { return getImplementation().GetProposalStatusByProposalId(proposalId) } // GetProposalCreatedAt returns the creation timestamp of a proposal. // // Parameters: // - proposalId: proposal identifier to look up // // Returns: // - int64: Unix timestamp at which the proposal was created // - error: nil on success, or an error when the proposal does not exist func GetProposalCreatedAt(proposalId int64) (int64, error) { return getImplementation().GetProposalCreatedAt(proposalId) } // GetProposalCreatedHeight returns the creation block height of a proposal. // // Parameters: // - proposalId: proposal identifier to look up // // Returns: // - int64: block height at which the proposal was created // - error: nil on success, or an error when the proposal does not exist func GetProposalCreatedHeight(proposalId int64) (int64, error) { return getImplementation().GetProposalCreatedHeight(proposalId) } // ================================== // Vote Getters // ================================== // GetVoteStatus returns the vote status of a proposal. // // Parameters: // - proposalId: proposal identifier to inspect // // Returns: // - quorum: minimum vote weight required for the proposal to pass // - maxVotingWeight: maximum possible voting weight recorded for the proposal // - yesWeight: total weight of yes votes // - noWeight: total weight of no votes // - err: nil on success, or an error when the proposal does not exist func GetVoteStatus(proposalId int64) (quorum, maxVotingWeight, yesWeight, noWeight int64, err error) { return getImplementation().GetVoteStatus(proposalId) } // GetVotingInfos returns a read-only view of a proposal's value-backed voting // infos, keyed by voter address. Existing proposals have an empty view before // the first vote; nil is returned only when the stored voting-info tree is absent. // // Parameters: // - proposalID: proposal identifier whose voting information is requested // // Returns: // - *rotree.ReadOnlyTree: read-only voting-info tree keyed by voter address, or nil when no tree is stored func GetVotingInfos(proposalID int64) *rotree.ReadOnlyTree { return getImplementation().GetVotingInfos(proposalID) } // ExistsVotingInfo checks whether voting information exists for a user on a proposal. // // Parameters: // - proposalID: proposal identifier to inspect // - addr: voter address to look up within proposalID // // Returns: // - bool: true when voting information exists for the proposal and address func ExistsVotingInfo(proposalID int64, addr address) bool { return getImplementation().ExistsVotingInfo(proposalID, addr) } // GetVoteWeight returns the voting weight of an address for a proposal. // // Parameters: // - proposalID: proposal identifier to inspect // - addr: voter address whose recorded vote weight is requested // // Returns: // - int64: weight recorded for addr's vote // - error: nil on success, or an error when no voting information exists for the proposal and address func GetVoteWeight(proposalID int64, addr address) (int64, error) { return getImplementation().GetVoteWeight(proposalID, addr) } // GetVotedHeight returns the block height when an address voted on a proposal. // // Parameters: // - proposalID: proposal identifier to inspect // - addr: voter address whose vote height is requested // // Returns: // - int64: block height recorded for addr's vote // - error: nil on success, or an error when no voting information exists for the proposal and address func GetVotedHeight(proposalID int64, addr address) (int64, error) { return getImplementation().GetVotedHeight(proposalID, addr) } // GetVotedAt returns the timestamp when an address voted on a proposal. // // Parameters: // - proposalID: proposal identifier to inspect // - addr: voter address whose vote timestamp is requested // // Returns: // - int64: Unix timestamp recorded for addr's vote // - error: nil on success, or an error when no voting information exists for the proposal and address func GetVotedAt(proposalID int64, addr address) (int64, error) { return getImplementation().GetVotedAt(proposalID, addr) } // GetProposalCommunityPoolSpendInfo returns a cloned copy of the community pool spend info for a proposal. // // Parameters: // - proposalID: proposal identifier to inspect // // Returns: // - *CommunityPoolSpendInfo: cloned community-pool spend details, or nil when an error occurs // - error: nil on success, or an error when the proposal is missing or has no spend data func GetProposalCommunityPoolSpendInfo(proposalID int64) (*CommunityPoolSpendInfo, error) { info, err := getImplementation().GetProposalCommunityPoolSpendInfo(proposalID) if err != nil { return nil, err } return info.Clone(), nil } // GetProposalExecutionInfo returns a cloned copy of the execution info for a proposal. // // Parameters: // - proposalID: proposal identifier to inspect // // Returns: // - *ExecutionInfo: cloned parameter-change execution messages and count, or nil when an error occurs // - error: nil on success, or an error when the proposal is missing or has no execution data func GetProposalExecutionInfo(proposalID int64) (*ExecutionInfo, error) { info, err := getImplementation().GetProposalExecutionInfo(proposalID) if err != nil { return nil, err } return info.Clone(), nil } // ================================== // User Proposal Getters // ================================== // GetUserProposals returns a read-only view of the proposals created per user, // keyed by creator address with the creator's proposal IDs as the value. // Reading an entry yields a copy of the ID slice, so the view cannot mutate // realm state. // // Returns: // - *rotree.ReadOnlyTree: read-only user-proposal tree keyed by creator address func GetUserProposals() *rotree.ReadOnlyTree { return getImplementation().GetUserProposals() } // ================================== // Active Proposal Query // ================================== // GetOldestActiveProposalSnapshotTime returns the oldest active proposal's // timestamp anchor. An empty index returns no active proposal; a stale or // missing first entry returns an error so cleanup cannot silently skip it. // // Returns: // - int64: snapshot timestamp of the oldest active proposal, or zero when the index is empty or an error occurs // - bool: true when an active proposal was found at the oldest index entry, otherwise false // - error: nil for an empty index or active entry, or an error when the entry is missing or inactive func GetOldestActiveProposalSnapshotTime() (int64, bool, error) { return getImplementation().GetOldestActiveProposalSnapshotTime() } // ================================== // Voting weight snapshot getters // ================================== // GetCurrentVotingWeightSnapshot returns the current total voting weight and its // timestamp anchor computed with the configured smoothing duration. // // Returns: // - int64: total voting weight averaged over the configured smoothing window // - int64: Unix timestamp used as the snapshot history anchor // - error: nil on success, or an error when the current configuration or snapshot data cannot be retrieved func GetCurrentVotingWeightSnapshot() (int64, int64, error) { return getImplementation().GetCurrentVotingWeightSnapshot() }
  14. #14gnomod.toml
  15. #15module = "gno.land/r/gnoswap/gov/governance" gno = "0.9"
  16. #16proposal.gno
  17. #17package governance import bptree "gno.land/p/nt/bptree/v0" // Proposal represents a governance proposal with all its associated data and state. // This is the core structure that tracks proposal lifecycle from creation to execution. type Proposal struct { id int64 // Unique identifier for the proposal proposer address // The address of the proposer configVersion int64 // The version of the governance config used status *ProposalStatus // Current status and voting information metadata *ProposalMetadata // Title and description data *ProposalData // Type-specific proposal data snapshotTime int64 // Timestamp for voting weight snapshot lookup createdHeight int64 // Block height at creation } // ID returns the unique identifier assigned to the proposal. // // Returns: // - int64: proposal identifier used as its storage key func (p *Proposal) ID() int64 { return p.id } // Type returns the proposal's type discriminator from its type-specific data. // // Returns: // - ProposalType: proposal kind, such as text, community-pool spend, or parameter change func (p *Proposal) Type() ProposalType { return p.data.ProposalType() } // Title returns the proposal title stored in its metadata. // // Returns: // - string: proposal title func (p *Proposal) Title() string { return p.metadata.Title() } // Description returns the proposal description stored in its metadata. // // Returns: // - string: proposal description func (p *Proposal) Description() string { return p.metadata.Description() } // Proposer returns the address that created the proposal. // // Returns: // - address: proposal creator's address func (p *Proposal) Proposer() address { return p.proposer } // CreatedHeight returns the block height at which the proposal was created. // // Returns: // - int64: proposal creation block height func (p *Proposal) CreatedHeight() int64 { return p.createdHeight } // CreatedAt returns the proposal creation timestamp recorded in its schedule. // // Returns: // - int64: proposal creation timestamp func (p *Proposal) CreatedAt() int64 { return p.status.schedule.createTime } // VotingYesWeight returns the total weight recorded for "yes" votes. // // Returns: // - int64: current "yes" vote weight func (p *Proposal) VotingYesWeight() int64 { return p.status.voteStatus.yea } // VotingNoWeight returns the total weight recorded for "no" votes. // // Returns: // - int64: current "no" vote weight func (p *Proposal) VotingNoWeight() int64 { return p.status.voteStatus.nay } // VotingQuorumAmount returns the minimum total vote weight required to pass. // // Returns: // - int64: quorum vote weight required by this proposal's configuration func (p *Proposal) VotingQuorumAmount() int64 { return p.status.voteStatus.quorumAmount } // VotingMaxWeight returns the maximum voting weight recorded for this proposal. // // Returns: // - int64: maximum voting weight used for the proposal's quorum calculation func (p *Proposal) VotingMaxWeight() int64 { return p.status.voteStatus.maxVotingWeight } // ConfigVersion returns the governance configuration version used by the proposal. // // Returns: // - int64: configuration version captured when the proposal was created func (p *Proposal) ConfigVersion() int64 { return p.configVersion } // SnapshotTime returns the timestamp used to look up historical voting weight. // // Returns: // - int64: voting-weight snapshot timestamp func (p *Proposal) SnapshotTime() int64 { return p.snapshotTime } // Data returns the proposal's type-specific data. // // Returns: // - *ProposalData: type-specific proposal data stored on the proposal func (p *Proposal) Data() *ProposalData { return p.data } // Status returns the proposal's schedule, vote, and action status. // // Returns: // - *ProposalStatus: mutable aggregate status associated with the proposal func (p *Proposal) Status() *ProposalStatus { return p.status } // Metadata returns the proposal's title and description metadata. // // Returns: // - *ProposalMetadata: metadata stored on the proposal func (p *Proposal) Metadata() *ProposalMetadata { return p.metadata } // IsTextType reports whether the proposal is a text proposal. // // Returns: // - bool: true when the proposal type is Text func (p *Proposal) IsTextType() bool { return p.Type() == Text } // IsCommunityPoolSpendType reports whether the proposal spends community-pool funds. // // Returns: // - bool: true when the proposal type is CommunityPoolSpend func (p *Proposal) IsCommunityPoolSpendType() bool { return p.Type() == CommunityPoolSpend } // IsParameterChangeType reports whether the proposal changes governance parameters. // // Returns: // - bool: true when the proposal type is ParameterChange func (p *Proposal) IsParameterChangeType() bool { return p.Type() == ParameterChange } // IsProposer reports whether addr matches the proposal's proposer address. // // Parameters: // - addr: address to compare with the proposal proposer // // Returns: // - bool: true when addr is the proposal proposer func (p *Proposal) IsProposer(addr address) bool { return p.proposer == addr } // NewProposal creates a new proposal instance with the supplied identity, // lifecycle, metadata, and type-specific data. // // Parameters: // - proposalID: unique identifier assigned to the proposal // - status: initial schedule, action, and voting status // - metadata: proposal title and description metadata // - data: type-specific proposal data // - proposerAddress: address of the proposal creator // - configVersion: governance configuration version captured for the proposal // - snapshotTime: timestamp anchor for historical voting-weight lookup // - createdHeight: block height at which the proposal was created // // Returns: // - *Proposal: newly initialized proposal containing the supplied fields func NewProposal( proposalID int64, status *ProposalStatus, metadata *ProposalMetadata, data *ProposalData, proposerAddress address, configVersion int64, snapshotTime int64, createdHeight int64, ) *Proposal { return &Proposal{ id: proposalID, proposer: proposerAddress, status: status, metadata: metadata, data: data, configVersion: configVersion, snapshotTime: snapshotTime, createdHeight: createdHeight, } } // Clone returns a deep copy of the proposal, including its type-specific data // and nested execution messages. // // The returned proposal and all nested status, metadata, data, and message // values are independent copies; mutating the clone does not mutate realm state. // // Returns: // - *Proposal: independent proposal copy, or nil when the receiver is nil func (p *Proposal) Clone() *Proposal { if p == nil { return nil } return &Proposal{ id: p.id, proposer: p.proposer, configVersion: p.configVersion, status: p.status.Clone(), metadata: p.metadata.Clone(), data: p.data.Clone(), snapshotTime: p.snapshotTime, createdHeight: p.createdHeight, } } // NewProposalTree creates an empty B+ tree for proposals keyed by proposal ID. // // Returns: // - *bptree.BPTree: empty 16-way proposal tree func NewProposalTree() *bptree.BPTree { return bptree.NewBPTreeN(16) } // NewUserProposalTree creates an empty B+ tree mapping users to proposal IDs. // // Returns: // - *bptree.BPTree: empty 16-way user-proposal index tree func NewUserProposalTree() *bptree.BPTree { return bptree.NewBPTreeN(16) } // NewVotingInfoTree creates an empty B+ tree for per-user voting information. // // Returns: // - *bptree.BPTree: empty 16-way voting-information tree func NewVotingInfoTree() *bptree.BPTree { return bptree.NewBPTreeN(16) } // NewProposalUserVotingInfoTree creates an empty B+ tree mapping proposal IDs // to their per-user voting-information trees. // // Returns: // - *bptree.BPTree: empty 16-way proposal voting-information index tree func NewProposalUserVotingInfoTree() *bptree.BPTree { return bptree.NewBPTreeN(16) }
  18. #18proposal_action_status.gno
  19. #19package governance // ProposalActionStatus tracks the execution and cancellation status of a proposal. // This structure manages the action-related state including who performed actions and when. type ProposalActionStatus struct { canceled bool // Whether the proposal has been canceled canceledAt int64 // Timestamp when proposal was canceled canceledHeight int64 // Block height when proposal was canceled canceledBy address // Who canceled the proposal executed bool // Whether the proposal has been executed executedAt int64 // Timestamp when proposal was executed executedHeight int64 // Block height when proposal was executed executedBy address // Who executed the proposal executable bool // Whether this proposal type supports execution } /* Getter methods */ // Canceled reports whether this proposal has been marked canceled. // // Returns: // - bool: true when cancellation has been recorded func (p *ProposalActionStatus) Canceled() bool { return p.canceled } // CanceledAt returns the timestamp recorded when the proposal was canceled. // // Returns: // - int64: cancellation timestamp, or zero when none has been recorded func (p *ProposalActionStatus) CanceledAt() int64 { return p.canceledAt } // CanceledHeight returns the block height recorded when the proposal was canceled. // // Returns: // - int64: cancellation block height, or zero when none has been recorded func (p *ProposalActionStatus) CanceledHeight() int64 { return p.canceledHeight } // Executed reports whether this proposal has been marked executed. // // Returns: // - bool: true when execution has been recorded func (p *ProposalActionStatus) Executed() bool { return p.executed } // ExecutedAt returns the timestamp recorded when the proposal was executed. // // Returns: // - int64: execution timestamp, or zero when none has been recorded func (p *ProposalActionStatus) ExecutedAt() int64 { return p.executedAt } // ExecutedHeight returns the block height recorded when the proposal was executed. // // Returns: // - int64: execution block height, or zero when none has been recorded func (p *ProposalActionStatus) ExecutedHeight() int64 { return p.executedHeight } // Executable reports whether this proposal type supports execution. // // Returns: // - bool: true when the proposal's action can be executed func (p *ProposalActionStatus) Executable() bool { return p.executable } /* Setter methods */ // SetCanceled records whether the proposal is canceled. // // Parameters: // - canceled: cancellation state to store func (p *ProposalActionStatus) SetCanceled(canceled bool) { p.canceled = canceled } // SetCanceledAt records the timestamp associated with proposal cancellation. // // Parameters: // - canceledAt: cancellation timestamp to store func (p *ProposalActionStatus) SetCanceledAt(canceledAt int64) { p.canceledAt = canceledAt } // SetCanceledHeight records the block height associated with proposal cancellation. // // Parameters: // - canceledHeight: cancellation block height to store func (p *ProposalActionStatus) SetCanceledHeight(canceledHeight int64) { p.canceledHeight = canceledHeight } // SetCanceledBy records the address that canceled the proposal. // // Parameters: // - canceledBy: address of the actor that canceled the proposal func (p *ProposalActionStatus) SetCanceledBy(canceledBy address) { p.canceledBy = canceledBy } // SetExecuted records whether the proposal is executed. // // Parameters: // - executed: execution state to store func (p *ProposalActionStatus) SetExecuted(executed bool) { p.executed = executed } // SetExecutedAt records the timestamp associated with proposal execution. // // Parameters: // - executedAt: execution timestamp to store func (p *ProposalActionStatus) SetExecutedAt(executedAt int64) { p.executedAt = executedAt } // SetExecutedHeight records the block height associated with proposal execution. // // Parameters: // - executedHeight: execution block height to store func (p *ProposalActionStatus) SetExecutedHeight(executedHeight int64) { p.executedHeight = executedHeight } // SetExecutedBy records the address that executed the proposal. // // Parameters: // - executedBy: address of the actor that executed the proposal func (p *ProposalActionStatus) SetExecutedBy(executedBy address) { p.executedBy = executedBy } // SetExecutable records whether this proposal type supports execution. // // Parameters: // - executable: execution capability to store for the proposal type func (p *ProposalActionStatus) SetExecutable(executable bool) { p.executable = executable } // CanceledBy returns the address recorded as having canceled the proposal. // The value is meaningful when Canceled() is true; before then it is the // zero address unless a caller has explicitly stored another value. // // Returns: // - address: address recorded for the cancellation actor func (p *ProposalActionStatus) CanceledBy() address { return p.canceledBy } // IsExecuted reports whether execution has been recorded for the proposal. // // Returns: // - bool: true when the proposal has been marked executed func (p *ProposalActionStatus) IsExecuted() bool { return p.executed } // ExecutedBy returns the address recorded as having executed the proposal. // The value is meaningful when IsExecuted() is true; before then it is the // zero address unless a caller has explicitly stored another value. // // Returns: // - address: address recorded for the execution actor func (p *ProposalActionStatus) ExecutedBy() address { return p.executedBy } // IsExecutable reports whether this proposal type can be executed. // // Returns: // - bool: true when execution is supported for the proposal type func (p *ProposalActionStatus) IsExecutable() bool { return p.executable } // NewProposalActionStatus creates a new action status for a proposal. // Initializes the status with default values and the executable flag. // // Parameters: // - executable: whether this proposal type can be executed // // Returns: // - *ProposalActionStatus: new action status instance func NewProposalActionStatus(executable bool) *ProposalActionStatus { return &ProposalActionStatus{ canceled: false, // Proposal starts as not canceled executed: false, // Proposal starts as not executed executable: executable, // Set based on proposal type } } // Clone creates a deep copy of the ProposalActionStatus, or nil when the // receiver is nil. // // Returns: // - *ProposalActionStatus: independent copy of the status, or nil for a nil receiver func (p *ProposalActionStatus) Clone() *ProposalActionStatus { if p == nil { return nil } return &ProposalActionStatus{ canceled: p.canceled, canceledAt: p.canceledAt, canceledHeight: p.canceledHeight, canceledBy: p.canceledBy, executed: p.executed, executedAt: p.executedAt, executedHeight: p.executedHeight, executedBy: p.executedBy, executable: p.executable, } }
  20. #20proposal_data.gno
  21. #21package governance import ( "strings" ) // ProposalMetadata contains descriptive information about a proposal. // This includes the title and description that are displayed to voters. type ProposalMetadata struct { title string // Proposal title (max 255 characters) description string // Detailed proposal description (max 10,000 characters) } // Title returns the proposal title. // // Returns: // - string: proposal title func (p *ProposalMetadata) Title() string { return p.title } // Description returns the proposal description. // // Returns: // - string: proposal description func (p *ProposalMetadata) Description() string { return p.description } // NewProposalMetadata creates a new proposal metadata instance with trimmed input. // // Parameters: // - title: proposal title // - description: proposal description // // Returns: // - *ProposalMetadata: new metadata instance with trimmed whitespace func NewProposalMetadata(title string, description string) *ProposalMetadata { return &ProposalMetadata{ title: strings.TrimSpace(title), description: strings.TrimSpace(description), } } // ProposalData contains the type-specific data for a proposal. // This structure holds different data depending on the proposal type. type ProposalData struct { proposalType ProposalType // Type of proposal (Text, CommunityPoolSpend, ParameterChange) communityPoolSpend *CommunityPoolSpendInfo // Data for community pool spending proposals execution *ExecutionInfo // Data for parameter change proposals } // ProposalType returns the type of this proposal. // // Returns: // - ProposalType: the proposal type func (p *ProposalData) ProposalType() ProposalType { return p.proposalType } // CommunityPoolSpend returns the community pool spending information. // // Returns: // - *CommunityPoolSpendInfo: community pool spending details func (p *ProposalData) CommunityPoolSpend() *CommunityPoolSpendInfo { return p.communityPoolSpend } // Execution returns the execution information for parameter changes. // // Returns: // - *ExecutionInfo: parameter change execution details func (p *ProposalData) Execution() *ExecutionInfo { return p.execution } // NewProposalData creates a new proposal data instance with the specified components. // // Parameters: // - proposalType: type of the proposal // - communityPoolSpend: community pool spending information // - execution: parameter change execution information // // Returns: // - *ProposalData: new proposal data instance func NewProposalData(proposalType ProposalType, communityPoolSpend *CommunityPoolSpendInfo, execution *ExecutionInfo) *ProposalData { return &ProposalData{ proposalType: proposalType, communityPoolSpend: communityPoolSpend, execution: execution, } } // CommunityPoolSpendInfo contains information for community pool spending proposals. type CommunityPoolSpendInfo struct { to address // Recipient address for token transfer tokenPath string // Path of the token to transfer amount int64 // Amount of tokens to transfer } // NewCommunityPoolSpendInfo creates community-pool spend data. // // Parameters: // - to: Recipient address that receives the community-pool transfer. // - tokenPath: Registered token path of the asset to transfer. // - amount: Transfer amount in the token's smallest unit. // // Returns: // - *CommunityPoolSpendInfo: spend data containing the recipient, token path, and amount. func NewCommunityPoolSpendInfo(to address, tokenPath string, amount int64) *CommunityPoolSpendInfo { return &CommunityPoolSpendInfo{ to: to, tokenPath: tokenPath, amount: amount, } } /* Getter methods */ // Returns: // - address: recipient address configured for the community-pool spend. // func (i *CommunityPoolSpendInfo) To() address { return i.to } // Returns: // - string: registered token path configured for the community-pool spend. func (i *CommunityPoolSpendInfo) TokenPath() string { return i.tokenPath } // Returns: // - int64: transfer amount in the token's smallest unit. func (i *CommunityPoolSpendInfo) Amount() int64 { return i.amount } // ExecutionInfo contains information for parameter change execution. // Messages are encoded strings that specify function calls and parameters. type ExecutionInfo struct { num int64 // Number of parameter changes to execute msgs []string // Execution messages separated by messageSeparator (*GOV*) } // NewExecutionInfo creates execution data for a parameter-change proposal. // // Parameters: // - num: Number of encoded parameter-change messages to execute. // - msgs: Encoded parameter-change messages, one message per execution. // // Returns: // - *ExecutionInfo: execution data containing the declared count and messages. func NewExecutionInfo(num int64, msgs []string) *ExecutionInfo { return &ExecutionInfo{ num: num, msgs: msgs, } } /* Getter methods */ // Returns: // - int64: declared number of parameter-change messages. // func (i *ExecutionInfo) Num() int64 { return i.num } // Returns: // - []string: encoded parameter-change messages in execution order. func (i *ExecutionInfo) Msgs() []string { return i.msgs } // ParameterChangeInfo represents a single parameter change to be executed. type ParameterChangeInfo struct { pkgPath string // Package path of the target contract function string // Function name to call params []string // Parameters to pass to the function } // NewParameterChangeInfo creates one encoded parameter-change target description. // // Parameters: // - pkgPath: Package path containing the parameter-change handler. // - function: Handler function name to invoke. // - params: String arguments passed to the handler in order. // // Returns: // - ParameterChangeInfo: parameter-change target and its encoded arguments. func NewParameterChangeInfo(pkgPath string, function string, params []string) ParameterChangeInfo { return ParameterChangeInfo{ pkgPath: pkgPath, function: function, params: params, } } /* Getter methods */ // Returns: // - string: package path of the parameter-change handler. // func (i *ParameterChangeInfo) PkgPath() string { return i.pkgPath } // Returns: // - string: function name of the parameter-change handler. func (i *ParameterChangeInfo) Function() string { return i.function } // Returns: // - []string: encoded arguments passed to the parameter-change handler. func (i *ParameterChangeInfo) Params() []string { return i.params } // Clone creates a deep copy of the ProposalMetadata. // Returns: // - *ProposalMetadata: independent metadata copy, or nil when the receiver is nil. func (p *ProposalMetadata) Clone() *ProposalMetadata { if p == nil { return nil } return &ProposalMetadata{ title: p.title, description: p.description, } } // Clone creates a deep copy of the CommunityPoolSpendInfo. // Returns: // - *CommunityPoolSpendInfo: independent spend-data copy, or nil when the receiver is nil. func (i *CommunityPoolSpendInfo) Clone() *CommunityPoolSpendInfo { if i == nil { return nil } return &CommunityPoolSpendInfo{ to: i.to, tokenPath: i.tokenPath, amount: i.amount, } } // Clone creates a deep copy of the ExecutionInfo. // Returns: // - *ExecutionInfo: independent execution-data copy including a copied message slice, or nil when the receiver is nil. func (i *ExecutionInfo) Clone() *ExecutionInfo { if i == nil { return nil } clonedMsgs := make([]string, len(i.msgs)) copy(clonedMsgs, i.msgs) return &ExecutionInfo{ num: i.num, msgs: clonedMsgs, } } // Clone creates a deep copy of the ProposalData. // Returns: // - *ProposalData: independent proposal-data copy with cloned nested values, or nil when the receiver is nil. func (p *ProposalData) Clone() *ProposalData { if p == nil { return nil } return &ProposalData{ proposalType: p.proposalType, communityPoolSpend: p.communityPoolSpend.Clone(), execution: p.execution.Clone(), } }
  22. #22proposal_schedule_status.gno
  23. #23package governance // ProposalScheduleStatus represents the pre-calculated time schedule for a proposal. // This structure defines all the important timestamps in a proposal's lifecycle, // from creation through voting to execution and expiration. type ProposalScheduleStatus struct { createTime int64 // When the proposal was created activeTime int64 // When voting starts (CreateTime + VotingStartDelay) votingEndTime int64 // When voting ends (ActiveTime + VotingPeriod) executableTime int64 // When execution window starts (VotingEndTime + ExecutionDelay) expiredTime int64 // When execution window ends (ExecutableTime + ExecutionWindow) } // NewProposalScheduleStatus creates a proposal schedule from its lifecycle timestamps. // // Parameters: // - createTime: Unix timestamp when the proposal was created // - activeTime: Unix timestamp when voting starts // - votingEndTime: Unix timestamp when voting ends // - executableTime: Unix timestamp when the execution window starts // - expiredTime: Unix timestamp when the execution window closes // // Returns: // - *ProposalScheduleStatus: schedule containing the supplied lifecycle timestamps func NewProposalScheduleStatus( createTime int64, activeTime int64, votingEndTime int64, executableTime int64, expiredTime int64, ) *ProposalScheduleStatus { return &ProposalScheduleStatus{ createTime: createTime, activeTime: activeTime, votingEndTime: votingEndTime, executableTime: executableTime, expiredTime: expiredTime, } } /* Getter methods */ // CreateTime returns the Unix timestamp when the proposal was created. // // Returns: // - int64: proposal creation timestamp func (p *ProposalScheduleStatus) CreateTime() int64 { return p.createTime } // ActiveTime returns the Unix timestamp when proposal voting starts. // // Returns: // - int64: voting start timestamp func (p *ProposalScheduleStatus) ActiveTime() int64 { return p.activeTime } // VotingEndTime returns the Unix timestamp when proposal voting ends. // // Returns: // - int64: voting end timestamp func (p *ProposalScheduleStatus) VotingEndTime() int64 { return p.votingEndTime } // ExecutableTime returns the Unix timestamp when the execution window starts. // // Returns: // - int64: execution start timestamp func (p *ProposalScheduleStatus) ExecutableTime() int64 { return p.executableTime } // ExpiredTime returns the Unix timestamp when the execution window closes. // // Returns: // - int64: execution expiration timestamp func (p *ProposalScheduleStatus) ExpiredTime() int64 { return p.expiredTime } /* Setter methods */ // SetCreateTime updates the proposal creation timestamp. // // Parameters: // - createTime: Unix timestamp when the proposal was created func (p *ProposalScheduleStatus) SetCreateTime(createTime int64) { p.createTime = createTime } // SetActiveTime updates the timestamp when proposal voting starts. // // Parameters: // - activeTime: Unix timestamp when voting starts func (p *ProposalScheduleStatus) SetActiveTime(activeTime int64) { p.activeTime = activeTime } // SetVotingEndTime updates the timestamp when proposal voting ends. // // Parameters: // - votingEndTime: Unix timestamp when voting ends func (p *ProposalScheduleStatus) SetVotingEndTime(votingEndTime int64) { p.votingEndTime = votingEndTime } // SetExecutableTime updates the timestamp when proposal execution can start. // // Parameters: // - executableTime: Unix timestamp when the execution window starts func (p *ProposalScheduleStatus) SetExecutableTime(executableTime int64) { p.executableTime = executableTime } // SetExpiredTime updates the timestamp when proposal execution expires. // // Parameters: // - expiredTime: Unix timestamp when the execution window closes func (p *ProposalScheduleStatus) SetExpiredTime(expiredTime int64) { p.expiredTime = expiredTime } // Clone creates a deep copy of the ProposalScheduleStatus. // // Returns: // - *ProposalScheduleStatus: copied schedule, or nil when the receiver is nil func (p *ProposalScheduleStatus) Clone() *ProposalScheduleStatus { if p == nil { return nil } return &ProposalScheduleStatus{ createTime: p.createTime, activeTime: p.activeTime, votingEndTime: p.votingEndTime, executableTime: p.executableTime, expiredTime: p.expiredTime, } }
  24. #24proposal_status.gno

Result log

msg:0,success:true,log:,events:[]