package governance
import (
"errors"
bptree "gno.land/p/nt/bptree/v0"
)
// Config represents the configuration of the governor contract
// All parameters in this struct can be modified through 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 active xGNS supply required for proposal approval
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
}
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
}
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.
func NewConfigPtr(
votingStartDelay,
votingPeriod,
votingWeightSmoothingDuration,
quorum,
proposalCreationThreshold,
executionDelay,
executionWindow int64,
) *Config {
c := NewConfig(
votingStartDelay,
votingPeriod,
votingWeightSmoothingDuration,
quorum,
proposalCreationThreshold,
executionDelay,
executionWindow,
)
return &c
}
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
}
}
func NewConfigTree() *bptree.BPTree {
return bptree.NewBPTreeN(16)
}