PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/gnoswap/gov/governance/v1

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v1
Namespace
gnoswap / gov / governance
Files
23 (README)(gnomod.toml)
Exported functions
n/a — Gnoland RPC unavailable (functions): rpc abci_query: HTTP 500
Module
gno.land/r/gnoswap/gov/governance/v1
gno
0.9

Files (23)

  • README.mdmarkdown
  • gnomod.tomltoml
  • assert.gnogno
  • config.gnogno
  • consts.gnogno
  • doc.gnogno
  • errors.gnogno
  • getter_utils.gnogno
  • getter.gnogno
  • governance_execute.gnogno
  • governance_propose.gnogno
  • governance_vote.gnogno
  • init.gnogno
  • instance.gnogno
  • parameter_registry.gnogno
  • proposal_action_status.gnogno
  • proposal_data.gnogno
  • proposal_schedule_status.gnogno
  • proposal_status.gnogno
  • proposal_vote_status.gnogno
  • proposal.gnogno
  • render.gnogno
  • utils.gnogno
  • parameter_registry.gnogno
    1package governance23import (4	"strings"56	prbac "gno.land/p/gnoswap/rbac/v1"7	ufmt "gno.land/p/nt/ufmt/v0"8

    Functions

    Gnoland RPC unavailable (functions): rpc abci_query: HTTP 500

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    Rendered

    RenderedRawgnoweb ↗

    Render unavailable

    rate limit exceeded — the render query is served by the Gnoland archive RPC.

    vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.

    9 cm "gno.land/r/gnoswap/common"
    10 cp "gno.land/r/gnoswap/community_pool/v1"
    11 en "gno.land/r/gnoswap/emission"
    12 "gno.land/r/gnoswap/rbac/v1"
    13
    14 "gno.land/r/gnoswap/gov/governance"
    15 gs "gno.land/r/gnoswap/gov/staker"
    16 lp "gno.land/r/gnoswap/launchpad"
    17 pl "gno.land/r/gnoswap/pool"
    18 pos "gno.land/r/gnoswap/position"
    19 pf "gno.land/r/gnoswap/protocol_fee"
    20 rr "gno.land/r/gnoswap/router"
    21 sr "gno.land/r/gnoswap/staker"
    22
    23 "gno.land/r/gnoswap/halt/v1"
    24)
    25
    26// globalParameterRegistry is initialized once and reused for all validation and execution.
    27// This provides consistent validation at proposal creation time and execution time.
    28var globalParameterRegistry *ParameterRegistry
    29
    30func init() {
    31 globalParameterRegistry = CreateParameterHandlers()
    32}
    33
    34// Package paths
    35const (
    36 GNS_TOKEN_KEY = "gno.land/r/gnoswap/gns.GNS"
    37 HALT_PATH = "gno.land/r/gnoswap/halt/v1"
    38 RBAC_PATH = "gno.land/r/gnoswap/rbac/v1"
    39 ACCESS_PATH = "gno.land/r/gnoswap/access/v1"
    40 EMISSION_PATH = "gno.land/r/gnoswap/emission"
    41 COMMON_PATH = "gno.land/r/gnoswap/common"
    42 POOL_PATH = "gno.land/r/gnoswap/pool"
    43 POSITION_PATH = "gno.land/r/gnoswap/position"
    44 ROUTER_PATH = "gno.land/r/gnoswap/router"
    45 STAKER_PATH = "gno.land/r/gnoswap/staker"
    46 LAUNCHPAD_PATH = "gno.land/r/gnoswap/launchpad"
    47 PROTOCOL_FEE_PATH = "gno.land/r/gnoswap/protocol_fee"
    48 COMMUNITY_POOL_PATH = "gno.land/r/gnoswap/community_pool/v1"
    49 GOV_GOVERNANCE_PATH = "gno.land/r/gnoswap/gov/governance"
    50 GOV_STAKER_PATH = "gno.land/r/gnoswap/gov/staker"
    51)
    52
    53// ParameterHandler interface defines the contract for parameter execution handlers.
    54// Each handler is responsible for executing specific parameter changes in the system.
    55type ParameterHandler interface {
    56 // Execute processes the parameters and applies the changes to the system.
    57 // The `_ int, rlm realm` discriminator pair forwards the governance proxy's
    58 // realm value into the handler so any cross-realm calls inside the closure
    59 // run under the proxy's identity (the only address with caller-allowlist
    60 // permission against the targeted /r/ realms).
    61 //
    62 // Parameters:
    63 // - _: integer discriminator required by the crossing entrypoint; callers use 0
    64 // - rlm: current governance proxy realm context forwarded to the handler
    65 // - params: serialized parameter values to validate and apply in handler order
    66 //
    67 // Returns:
    68 // - error: nil when the parameter change succeeds, or an execution/validation error
    69 Execute(_ int, rlm realm, params []string) error
    70}
    71
    72// ParameterHandlerOptions contains the configuration and execution logic for a parameter handler.
    73// This struct encapsulates all information needed to identify and execute a parameter change.
    74//
    75// NOTE: handlerFunc uses `rlm realm` (rather than `cur realm`) as the realm
    76// parameter name. The v2 preprocessor reserves the `cur` name for the first
    77// realm-type parameter of top-level crossing function declarations and
    78// `t.Run` closures only; using it as the realm-parameter name on a
    79// multi-parameter struct-field function value trips a parser check
    80// ("only the first realm type argument of a crossing function may have name
    81// `cur`"). Naming it `rlm` keeps the lowering identical without the syntax
    82// constraint.
    83type ParameterHandlerOptions struct {
    84 pkgPath string // Package path of the target contract
    85 function string // Function name to be called
    86 paramCount int // Expected number of parameters
    87 handlerFunc func(_ int, rlm realm, _ []string) error // Function that executes the parameter change
    88 paramValidators []paramValidator // Optional per-parameter validators for proposal-time checks
    89 compositeValidator compositeValidator // Optional cross-parameter validator for static business rules
    90}
    91
    92// paramValidator validates a single parameter value and returns an error on failure.
    93type paramValidator func(string) error
    94
    95// compositeValidator validates relationships between a handler's parameters.
    96// It must only enforce deterministic, state-independent rules so that a
    97// proposal is not rejected merely because on-chain state changes while voting.
    98type compositeValidator func([]string) error
    99
    100// NewParameterHandlerOptions creates a new parameter handler with the specified configuration.
    101//
    102// Parameters:
    103// - pkgPath: package path of the target contract
    104// - function: function name to be called
    105// - paramCount: expected number of parameters
    106// - handlerFunc: callback receiving the discriminator, propagated realm, and serialized parameters to execute the change
    107// - paramValidators: optional validators for each parameter (must match paramCount if provided)
    108//
    109// Returns:
    110// - ParameterHandler: configured parameter handler interface
    111func NewParameterHandlerOptions(
    112 pkgPath,
    113 function string,
    114 paramCount int,
    115 handlerFunc func(_ int, rlm realm, _ []string) error,
    116 paramValidators ...paramValidator,
    117) ParameterHandler {
    118 if len(paramValidators) > 0 && len(paramValidators) != paramCount {
    119 panic(ufmt.Sprintf(
    120 "invalid validator count for %s:%s: expected %d, got %d",
    121 pkgPath, function, paramCount, len(paramValidators),
    122 ))
    123 }
    124
    125 return &ParameterHandlerOptions{
    126 pkgPath: pkgPath,
    127 function: function,
    128 paramCount: paramCount,
    129 handlerFunc: handlerFunc,
    130 paramValidators: paramValidators,
    131 }
    132}
    133
    134// HandlerKey generates a unique key for this handler based on package path and function name.
    135//
    136// Returns:
    137// - string: unique identifier for the handler
    138func (h *ParameterHandlerOptions) HandlerKey() string {
    139 return makeHandlerKey(h.pkgPath, h.function)
    140}
    141
    142// Execute validates parameter count and executes the handler function.
    143// This method ensures the correct number of parameters are provided before execution.
    144//
    145// Parameters:
    146// - _: integer discriminator required by the crossing entrypoint; callers use 0
    147// - rlm: governance proxy realm threaded into the wrapped handler
    148// - params: serialized parameter values to pass to the handler
    149//
    150// Returns:
    151// - error: parameter-count error or the error returned by the wrapped handler
    152func (h *ParameterHandlerOptions) Execute(_ int, rlm realm, params []string) error {
    153 if len(params) != h.paramCount {
    154 return ufmt.Errorf("expected %d parameters, got %d", h.paramCount, len(params))
    155 }
    156
    157 return h.handlerFunc(0, rlm, params)
    158}
    159
    160// ValidateParams checks the parameter count and runs configured individual and composite validators without executing the handler.
    161//
    162// Parameters:
    163// - params: serialized parameter values to validate in handler order
    164//
    165// Returns:
    166// - error: nil when all configured checks pass, or the first count/type/business-rule validation error
    167func (h *ParameterHandlerOptions) ValidateParams(params []string) error {
    168 if len(params) != h.paramCount {
    169 return ufmt.Errorf(
    170 "expected %d parameters for %s, got %d",
    171 h.paramCount, h.HandlerKey(), len(params),
    172 )
    173 }
    174
    175 if len(h.paramValidators) > 0 {
    176 if len(h.paramValidators) != h.paramCount {
    177 return ufmt.Errorf(
    178 "validator count mismatch for %s: expected %d validator(s), got %d",
    179 h.HandlerKey(), h.paramCount, len(h.paramValidators),
    180 )
    181 }
    182
    183 for i, validator := range h.paramValidators {
    184 if validator == nil {
    185 continue
    186 }
    187
    188 if err := validator(params[i]); err != nil {
    189 return ufmt.Errorf("param[%d]: %v", i, err)
    190 }
    191 }
    192 }
    193
    194 if h.compositeValidator != nil {
    195 if err := h.compositeValidator(params); err != nil {
    196 return err
    197 }
    198 }
    199
    200 return nil
    201}
    202
    203// ParameterRegistry manages the collection of parameter handlers for governance execution.
    204// This registry allows proposals to execute parameter changes across different system contracts.
    205type ParameterRegistry struct {
    206 handlers map[string]ParameterHandlerOptions // Map storing handler configurations keyed by package:function
    207}
    208
    209// Register adds a new parameter handler to the registry.
    210// Each handler is identified by a unique combination of package path and function name.
    211//
    212// Parameters:
    213// - handler: parameter handler configuration to register
    214func (r *ParameterRegistry) Register(handler ParameterHandlerOptions) {
    215 r.handlers[handler.HandlerKey()] = handler
    216}
    217
    218// Handler retrieves a parameter handler by its package:function key.
    219// This method is used during proposal execution to find the appropriate handler.
    220//
    221// Parameters:
    222// - key: handler key returned by HandlerKey, in "pkgPath:function" format
    223//
    224// Returns:
    225// - ParameterHandler: the matching parameter handler
    226// - error: error if the key has no registered handler
    227func (r *ParameterRegistry) Handler(key string) (ParameterHandler, error) {
    228 // Retrieve handler from registry
    229 handler, exists := r.handlers[key]
    230 if !exists {
    231 return nil, ufmt.Errorf("handler not found for %s", key)
    232 }
    233
    234 return &handler, nil
    235}
    236
    237// NewParameterRegistry creates a new empty parameter registry.
    238//
    239// Returns:
    240// - *ParameterRegistry: new registry instance
    241func NewParameterRegistry() *ParameterRegistry {
    242 return &ParameterRegistry{handlers: make(map[string]ParameterHandlerOptions)}
    243}
    244
    245// makeHandlerKey creates a unique identifier for a handler based on package path and function.
    246//
    247// Parameters:
    248// - pkgPath: package path of the target contract
    249// - function: function name to be called
    250//
    251// Returns:
    252// - string: unique key in format "pkgPath:function"
    253func makeHandlerKey(pkgPath, function string) string {
    254 return pkgPath + ":" + function
    255}
    256
    257// CreateParameterHandlers initializes and configures all supported parameter handlers.
    258// This function defines all the parameter changes that can be executed through governance proposals.
    259// It covers configuration changes for various system components including pools, staking, fees, etc.
    260//
    261// Returns:
    262// - *ParameterRegistry: fully configured registry with all supported handlers
    263func CreateParameterHandlers() *ParameterRegistry {
    264 registry := NewParameterRegistry()
    265
    266 // Define all handler configurations for different system components.
    267 //
    268 // Each closure receives `(_ int, rlm realm, params []string)` and threads
    269 // `rlm` into the targeted /r/ realm call. The closure is invoked from
    270 // ParameterHandlerOptions.Execute which forwards the governance proxy's
    271 // realm value, so cross-realm calls land on the targeted realm with the
    272 // governance proxy as the immediate caller.
    273 handlers := []*ParameterHandlerOptions{
    274 // Community pool token transfers
    275 {
    276 pkgPath: COMMUNITY_POOL_PATH,
    277 function: "TransferToken",
    278 paramCount: 3,
    279 paramValidators: []paramValidator{
    280 stringValidator, // pkgPath
    281 addressValidator, // to
    282 positiveInt64Validator("amount"),
    283 },
    284 handlerFunc: func(_ int, rlm realm, params []string) error {
    285 // Transfer tokens from community pool to specified address
    286 cp.TransferToken(
    287 cross(rlm),
    288 params[0], // pkgPath
    289 address(params[1]), // to
    290 parseNumber(params[2], kindInt64).(int64), // amount
    291 )
    292
    293 return nil
    294 },
    295 },
    296 // Emission distribution configuration
    297 {
    298 pkgPath: EMISSION_PATH,
    299 function: "SetDistributionStartTime",
    300 paramCount: 1,
    301 paramValidators: []paramValidator{
    302 numberValidator(kindInt64), // start time
    303 },
    304 handlerFunc: func(_ int, rlm realm, params []string) error {
    305 // Set distribution start time
    306 en.SetDistributionStartTime(cross(rlm), parseInt64(params[0]))
    307
    308 return nil
    309 },
    310 },
    311 {
    312 pkgPath: EMISSION_PATH,
    313 function: "ChangeDistributionPct",
    314 paramCount: 4,
    315 paramValidators: []paramValidator{
    316 numberValidator(kindInt64), // liquidityStakerPct
    317 numberValidator(kindInt64), // devOpsPct
    318 numberValidator(kindInt64), // communityPoolPct
    319 numberValidator(kindInt64), // govStakerPct
    320 },
    321 compositeValidator: distributionPctCompositeValidator,
    322 handlerFunc: func(_ int, rlm realm, params []string) error {
    323 liquidityStakerPct := parseNumber(params[0], kindInt64).(int64)
    324 devOpsPct := parseNumber(params[1], kindInt64).(int64)
    325 communityPoolPct := parseNumber(params[2], kindInt64).(int64)
    326 govStakerPct := parseNumber(params[3], kindInt64).(int64)
    327
    328 en.ChangeDistributionPct(
    329 cross(rlm),
    330 liquidityStakerPct,
    331 devOpsPct,
    332 communityPoolPct,
    333 govStakerPct,
    334 )
    335
    336 return nil
    337 },
    338 },
    339 // Governance configuration changes
    340 {
    341 pkgPath: GOV_GOVERNANCE_PATH,
    342 function: "Reconfigure",
    343 paramCount: 7,
    344 paramValidators: []paramValidator{
    345 numberValidator(kindInt64), // votingStartDelay
    346 numberValidator(kindInt64), // votingPeriod
    347 numberValidator(kindInt64), // votingWeightSmoothingDuration
    348 numberValidator(kindInt64), // quorum
    349 numberValidator(kindInt64), // proposalCreationThreshold
    350 numberValidator(kindInt64), // executionDelay
    351 numberValidator(kindInt64), // executionWindow
    352 },
    353 handlerFunc: func(_ int, rlm realm, params []string) error {
    354 // Parse governance configuration parameters
    355 votingStartDelay := parseInt64(params[0])
    356 votingPeriod := parseInt64(params[1])
    357 votingWeightSmoothingDuration := parseInt64(params[2])
    358 quorum := parseInt64(params[3])
    359 proposalCreationThreshold := parseInt64(params[4])
    360 executionDelay := parseInt64(params[5])
    361 executionWindow := parseInt64(params[6])
    362
    363 // Reconfigure governance parameters through governance process
    364 governance.Reconfigure(
    365 cross(rlm),
    366 votingStartDelay,
    367 votingPeriod,
    368 votingWeightSmoothingDuration,
    369 quorum,
    370 proposalCreationThreshold,
    371 executionDelay,
    372 executionWindow,
    373 )
    374
    375 return nil
    376 },
    377 },
    378
    379 // Pool protocol fee configuration
    380 {
    381 pkgPath: POOL_PATH,
    382 function: "CollectProtocol",
    383 paramCount: 6,
    384 paramValidators: []paramValidator{
    385 stringValidator, // token0Path
    386 stringValidator, // token1Path
    387 uint64Validator, // fee
    388 addressValidator, // recipient
    389 nonNegativeInt64Validator("amount0Requested"),
    390 nonNegativeInt64Validator("amount1Requested"),
    391 },
    392 handlerFunc: func(_ int, rlm realm, params []string) error {
    393 pl.CollectProtocol(
    394 cross(rlm),
    395 params[0], // token0Path
    396 params[1], // token1Path
    397 uint32(parseUint64(params[2])), // fee
    398 address(params[3]), // recipient
    399 params[4], // amount0Requested
    400 params[5], // amount1Requested
    401 )
    402
    403 return nil
    404 },
    405 },
    406 {
    407 pkgPath: POOL_PATH,
    408 function: "SetFeeProtocol",
    409 paramCount: 2,
    410 paramValidators: []paramValidator{
    411 uint8RangeValidator("feeProtocol0"),
    412 uint8RangeValidator("feeProtocol1"),
    413 },
    414 handlerFunc: func(_ int, rlm realm, params []string) error {
    415 // Parse and validate fee protocol values
    416 feeProtocol0 := parseInt64(params[0])
    417 feeProtocol1 := parseInt64(params[1])
    418
    419 // Validate fee protocol values are within uint8 range
    420 if feeProtocol0 > 255 {
    421 panic(ufmt.Sprintf("feeProtocol0 out of range: %d", feeProtocol0))
    422 }
    423
    424 if feeProtocol1 > 255 {
    425 panic(ufmt.Sprintf("feeProtocol1 out of range: %d", feeProtocol1))
    426 }
    427
    428 // Set protocol fee percentages
    429 pl.SetFeeProtocol(
    430 cross(rlm),
    431 uint8(feeProtocol0), // feeProtocol0
    432 uint8(feeProtocol1), // feeProtocol1
    433 )
    434
    435 return nil
    436 },
    437 },
    438 // Pool creation fee
    439 {
    440 pkgPath: POOL_PATH,
    441 function: "SetPoolCreationFee",
    442 paramCount: 1,
    443 paramValidators: []paramValidator{
    444 nonNegativeInt64Validator("fee"),
    445 },
    446 handlerFunc: func(_ int, rlm realm, params []string) error {
    447 // Set fee required to create new pools
    448 pl.SetPoolCreationFee(cross(rlm), parseInt64(params[0])) // fee
    449 return nil
    450 },
    451 },
    452 // Pool withdrawal fee
    453 {
    454 pkgPath: POOL_PATH,
    455 function: "SetWithdrawalFee",
    456 paramCount: 1,
    457 paramValidators: []paramValidator{
    458 uint64RangeValidator("fee", 1000),
    459 },
    460 handlerFunc: func(_ int, rlm realm, params []string) error {
    461 // Set fee for withdrawing from pools
    462 pl.SetWithdrawalFee(cross(rlm), parseUint64(params[0])) // fee
    463 return nil
    464 },
    465 },
    466
    467 // Protocol fee distribution
    468 {
    469 pkgPath: PROTOCOL_FEE_PATH,
    470 function: "SetDevOpsPct",
    471 paramCount: 1,
    472 paramValidators: []paramValidator{
    473 int64RangeValidator("pct", 0, 10000),
    474 },
    475 handlerFunc: func(_ int, rlm realm, params []string) error {
    476 // Set percentage of protocol fees going to development operations
    477 pf.SetDevOpsPct(cross(rlm), parseInt64(params[0])) // pct
    478 return nil
    479 },
    480 },
    481
    482 // Router swap fee
    483 {
    484 pkgPath: ROUTER_PATH,
    485 function: "SetSwapFee",
    486 paramCount: 1,
    487 paramValidators: []paramValidator{
    488 uint64RangeValidator("fee", 1000),
    489 },
    490 handlerFunc: func(_ int, rlm realm, params []string) error {
    491 // Set fee charged for token swaps
    492 rr.SetSwapFee(cross(rlm), parseUint64(params[0])) // fee
    493 return nil
    494 },
    495 },
    496
    497 // Staker configuration handlers
    498 {
    499 pkgPath: STAKER_PATH,
    500 function: "SetDepositGnsAmount",
    501 paramCount: 1,
    502 paramValidators: []paramValidator{
    503 nonNegativeInt64Validator("amount"),
    504 },
    505 handlerFunc: func(_ int, rlm realm, params []string) error {
    506 // Set minimum GNS amount required for staking deposits
    507 sr.SetDepositGnsAmount(cross(rlm), parseInt64(params[0])) // amount
    508 return nil
    509 },
    510 },
    511 {
    512 pkgPath: STAKER_PATH,
    513 function: "SetMinimumRewardAmount",
    514 paramCount: 1,
    515 paramValidators: []paramValidator{
    516 nonNegativeInt64Validator("amount"),
    517 },
    518 handlerFunc: func(_ int, rlm realm, params []string) error {
    519 // Set minimum GNS amount required for staking deposits
    520 sr.SetMinimumRewardAmount(cross(rlm), parseInt64(params[0])) // amount
    521 return nil
    522 },
    523 },
    524 {
    525 pkgPath: STAKER_PATH,
    526 function: "SetTokenMinimumRewardAmount",
    527 paramCount: 1,
    528 paramValidators: []paramValidator{
    529 tokenMinimumRewardAmountValidator,
    530 },
    531 handlerFunc: func(_ int, rlm realm, params []string) error {
    532 // Set minimum GNS amount required for staking deposits
    533 // params[0] is a string in the format "tokenPath:amount"
    534 sr.SetTokenMinimumRewardAmount(cross(rlm), params[0]) // amount
    535 return nil
    536 },
    537 },
    538 {
    539 pkgPath: STAKER_PATH,
    540 function: "SetPoolTier",
    541 paramCount: 2,
    542 paramValidators: []paramValidator{
    543 stringValidator, // pool
    544 uint64RangeValidator("tier", sr.AllTierCount-1),
    545 },
    546 handlerFunc: func(_ int, rlm realm, params []string) error {
    547 // Assign tier level to a specific pool
    548 sr.SetPoolTier(
    549 cross(rlm),
    550 params[0], // pool
    551 parseUint64(params[1]), // tier
    552 )
    553 return nil
    554 },
    555 },
    556 {
    557 pkgPath: STAKER_PATH,
    558 function: "ChangePoolTier",
    559 paramCount: 2,
    560 paramValidators: []paramValidator{
    561 stringValidator, // pool
    562 uint64RangeValidator("tier", sr.AllTierCount-1),
    563 },
    564 handlerFunc: func(_ int, rlm realm, params []string) error {
    565 // Change existing pool's tier level
    566 sr.ChangePoolTier(
    567 cross(rlm),
    568 params[0], // pool
    569 parseUint64(params[1]), // tier
    570 )
    571 return nil
    572 },
    573 },
    574 {
    575 pkgPath: STAKER_PATH,
    576 function: "RemovePoolTier",
    577 paramCount: 1,
    578 paramValidators: []paramValidator{
    579 stringValidator, // pool
    580 },
    581 handlerFunc: func(_ int, rlm realm, params []string) error {
    582 // Remove tier assignment from a pool
    583 sr.RemovePoolTier(cross(rlm), params[0]) // pool
    584 return nil
    585 },
    586 },
    587 {
    588 pkgPath: STAKER_PATH,
    589 function: "SetUnStakingFee",
    590 paramCount: 1,
    591 paramValidators: []paramValidator{
    592 uint64RangeValidator("fee", 1000),
    593 },
    594 handlerFunc: func(_ int, rlm realm, params []string) error {
    595 // Set fee charged for unstaking operations
    596 fee := parseUint64(params[0])
    597 sr.SetUnStakingFee(cross(rlm), fee)
    598 return nil
    599 },
    600 },
    601 {
    602 pkgPath: STAKER_PATH,
    603 function: "SetWarmUp",
    604 paramCount: 2,
    605 paramValidators: []paramValidator{
    606 numberValidator(kindInt64), // percent
    607 numberValidator(kindInt64), // block
    608 },
    609 handlerFunc: func(_ int, rlm realm, params []string) error {
    610 // Set warm-up period configuration for staking
    611 percent := parseInt64(params[0])
    612 block := parseNumber(params[1], kindInt64).(int64)
    613 sr.SetWarmUp(cross(rlm), percent, block)
    614
    615 return nil
    616 },
    617 },
    618
    619 // System halt controls
    620 {
    621 pkgPath: HALT_PATH,
    622 function: "SetHaltLevel",
    623 paramCount: 1,
    624 paramValidators: []paramValidator{
    625 haltLevelValidator,
    626 },
    627 handlerFunc: func(_ int, rlm realm, params []string) error {
    628 // Set system-wide halt status
    629 halt.SetHaltLevel(cross(rlm), halt.HaltLevel(params[0])) // true = halt, false = no halt
    630
    631 return nil
    632 },
    633 },
    634 {
    635 pkgPath: HALT_PATH,
    636 function: "SetOperationStatus",
    637 paramCount: 2,
    638 paramValidators: []paramValidator{
    639 haltOperationTypeValidator,
    640 boolValidator, // allowed
    641 },
    642 handlerFunc: func(_ int, rlm realm, params []string) error {
    643 // Enable or disable specific operation types
    644 opType := halt.OpType(params[0])
    645 allowed := parseBool(params[1])
    646
    647 halt.SetOperationStatus(cross(rlm), opType, allowed)
    648
    649 return nil
    650 },
    651 },
    652
    653 // RBAC configuration
    654 {
    655 pkgPath: RBAC_PATH,
    656 function: "RegisterRole",
    657 paramCount: 2,
    658 paramValidators: []paramValidator{
    659 roleNameValidator,
    660 addressValidator, // roleAddress
    661 },
    662 handlerFunc: func(_ int, rlm realm, params []string) error {
    663 roleName := params[0]
    664 roleAddress := address(params[1])
    665
    666 // Register a new role
    667 rbac.RegisterRole(cross(rlm), roleName, roleAddress)
    668
    669 return nil
    670 },
    671 },
    672 {
    673 pkgPath: RBAC_PATH,
    674 function: "UpdateRoleAddress",
    675 paramCount: 2,
    676 paramValidators: []paramValidator{
    677 updatableRoleNameValidator,
    678 addressValidator, // roleAddress
    679 },
    680 handlerFunc: func(_ int, rlm realm, params []string) error {
    681 roleName := params[0]
    682 roleAddress := address(params[1])
    683
    684 // Update role address
    685 rbac.UpdateRoleAddress(cross(rlm), roleName, roleAddress)
    686
    687 return nil
    688 },
    689 },
    690 {
    691 pkgPath: RBAC_PATH,
    692 function: "RemoveRole",
    693 paramCount: 1,
    694 paramValidators: []paramValidator{
    695 removableRoleNameValidator,
    696 },
    697 handlerFunc: func(_ int, rlm realm, params []string) error {
    698 roleName := params[0]
    699
    700 // Remove role
    701 rbac.RemoveRole(cross(rlm), roleName)
    702
    703 return nil
    704 },
    705 },
    706
    707 // Protocol fee - SetGovStakerPct
    708 {
    709 pkgPath: PROTOCOL_FEE_PATH,
    710 function: "SetGovStakerPct",
    711 paramCount: 1,
    712 paramValidators: []paramValidator{
    713 int64RangeValidator("pct", 0, 10000),
    714 },
    715 handlerFunc: func(_ int, rlm realm, params []string) error {
    716 // Set percentage of protocol fees going to governance stakers
    717 pf.SetGovStakerPct(cross(rlm), parseInt64(params[0])) // pct
    718 return nil
    719 },
    720 },
    721
    722 // Staker - Token list management
    723 {
    724 pkgPath: STAKER_PATH,
    725 function: "AddToken",
    726 paramCount: 1,
    727 paramValidators: []paramValidator{
    728 stringValidator, // tokenPath
    729 },
    730 handlerFunc: func(_ int, rlm realm, params []string) error {
    731 // Add token to allowed token list for external incentives
    732 sr.AddToken(cross(rlm), params[0]) // tokenPath
    733 return nil
    734 },
    735 },
    736 {
    737 pkgPath: STAKER_PATH,
    738 function: "RemoveToken",
    739 paramCount: 1,
    740 paramValidators: []paramValidator{
    741 stringValidator, // tokenPath
    742 },
    743 handlerFunc: func(_ int, rlm realm, params []string) error {
    744 // Remove token from allowed token list
    745 sr.RemoveToken(cross(rlm), params[0]) // tokenPath
    746 return nil
    747 },
    748 },
    749 {
    750 pkgPath: STAKER_PATH,
    751 function: "SetDeniedRewardToken",
    752 paramCount: 2,
    753 paramValidators: []paramValidator{
    754 stringValidator, // tokenPath
    755 boolValidator, // denied
    756 },
    757 handlerFunc: func(_ int, rlm realm, params []string) error {
    758 // Deny or re-allow a token as an external incentive reward token
    759 sr.SetDeniedRewardToken(cross(rlm), params[0], parseBool(params[1]))
    760 return nil
    761 },
    762 },
    763
    764 // Staker - External incentive recovery
    765 {
    766 pkgPath: STAKER_PATH,
    767 function: "CancelExternalIncentive",
    768 paramCount: 2,
    769 paramValidators: []paramValidator{
    770 stringValidator, // targetPoolPath
    771 stringValidator, // incentiveId
    772 },
    773 handlerFunc: func(_ int, rlm realm, params []string) error {
    774 // Cancel a not-yet-started external incentive; the reward tokens
    775 // and the GNS deposit are refunded to the incentive creator
    776 sr.CancelExternalIncentive(
    777 cross(rlm),
    778 params[0], // targetPoolPath
    779 params[1], // incentiveId
    780 )
    781 return nil
    782 },
    783 },
    784
    785 // Launchpad - Project management
    786 {
    787 pkgPath: LAUNCHPAD_PATH,
    788 function: "CreateProject",
    789 paramCount: 10,
    790 paramValidators: []paramValidator{
    791 stringValidator, // name
    792 stringValidator, // tokenPath
    793 addressValidator, // recipient
    794 numberValidator(kindInt64), // depositAmount
    795 stringValidator, // conditionTokens
    796 stringValidator, // conditionAmounts
    797 numberValidator(kindInt64), // tier30Ratio
    798 numberValidator(kindInt64), // tier90Ratio
    799 numberValidator(kindInt64), // tier180Ratio
    800 numberValidator(kindInt64), // startTime
    801 },
    802 handlerFunc: func(_ int, rlm realm, params []string) error {
    803 // Create a new launchpad project
    804 lp.CreateProject(
    805 cross(rlm),
    806 params[0], // name
    807 params[1], // tokenPath
    808 address(params[2]), // recipient
    809 parseNumber(params[3], kindInt64).(int64), // depositAmount
    810 params[4], // conditionTokens
    811 params[5], // conditionAmounts
    812 parseNumber(params[6], kindInt64).(int64), // tier30Ratio
    813 parseNumber(params[7], kindInt64).(int64), // tier90Ratio
    814 parseNumber(params[8], kindInt64).(int64), // tier180Ratio
    815 parseNumber(params[9], kindInt64).(int64), // startTime
    816 )
    817 return nil
    818 },
    819 },
    820 // Upgrade handlers for various domains
    821 {
    822 pkgPath: POOL_PATH,
    823 function: "UpgradeImpl",
    824 paramCount: 1,
    825 paramValidators: []paramValidator{
    826 stringValidator, // packagePath
    827 },
    828 handlerFunc: func(_ int, rlm realm, params []string) error {
    829 // Upgrade pool implementation
    830 pl.UpgradeImpl(cross(rlm), params[0]) // packagePath
    831 return nil
    832 },
    833 },
    834 {
    835 pkgPath: POSITION_PATH,
    836 function: "UpgradeImpl",
    837 paramCount: 1,
    838 paramValidators: []paramValidator{
    839 stringValidator, // packagePath
    840 },
    841 handlerFunc: func(_ int, rlm realm, params []string) error {
    842 // Upgrade position implementation
    843 pos.UpgradeImpl(cross(rlm), params[0]) // packagePath
    844 return nil
    845 },
    846 },
    847 {
    848 pkgPath: STAKER_PATH,
    849 function: "UpgradeImpl",
    850 paramCount: 1,
    851 paramValidators: []paramValidator{
    852 stringValidator, // packagePath
    853 },
    854 handlerFunc: func(_ int, rlm realm, params []string) error {
    855 // Upgrade staker implementation
    856 sr.UpgradeImpl(cross(rlm), params[0]) // packagePath
    857 return nil
    858 },
    859 },
    860 {
    861 pkgPath: LAUNCHPAD_PATH,
    862 function: "UpgradeImpl",
    863 paramCount: 1,
    864 paramValidators: []paramValidator{
    865 stringValidator, // packagePath
    866 },
    867 handlerFunc: func(_ int, rlm realm, params []string) error {
    868 // Upgrade launchpad implementation
    869 lp.UpgradeImpl(cross(rlm), params[0]) // packagePath
    870 return nil
    871 },
    872 },
    873 {
    874 pkgPath: GOV_GOVERNANCE_PATH,
    875 function: "UpgradeImpl",
    876 paramCount: 1,
    877 paramValidators: []paramValidator{
    878 stringValidator, // targetPackagePath
    879 },
    880 handlerFunc: func(_ int, rlm realm, params []string) error {
    881 // Upgrade governance implementation
    882 governance.UpgradeImpl(cross(rlm), params[0]) // packagePath
    883 return nil
    884 },
    885 },
    886 {
    887 pkgPath: GOV_STAKER_PATH,
    888 function: "UpgradeImpl",
    889 paramCount: 1,
    890 paramValidators: []paramValidator{
    891 stringValidator, // packagePath
    892 },
    893 handlerFunc: func(_ int, rlm realm, params []string) error {
    894 // Upgrade gov staker implementation
    895 gs.UpgradeImpl(cross(rlm), params[0]) // packagePath
    896 return nil
    897 },
    898 },
    899 {
    900 pkgPath: ROUTER_PATH,
    901 function: "UpgradeImpl",
    902 paramCount: 1,
    903 paramValidators: []paramValidator{
    904 stringValidator, // packagePath
    905 },
    906 handlerFunc: func(_ int, rlm realm, params []string) error {
    907 // Upgrade router implementation
    908 rr.UpgradeImpl(cross(rlm), params[0]) // packagePath
    909 return nil
    910 },
    911 },
    912 {
    913 pkgPath: PROTOCOL_FEE_PATH,
    914 function: "UpgradeImpl",
    915 paramCount: 1,
    916 paramValidators: []paramValidator{
    917 stringValidator, // packagePath
    918 },
    919 handlerFunc: func(_ int, rlm realm, params []string) error {
    920 // Upgrade protocol fee implementation
    921 pf.UpgradeImpl(cross(rlm), params[0]) // packagePath
    922 return nil
    923 },
    924 },
    925 {
    926 pkgPath: COMMON_PATH,
    927 function: "UpgradeImpl",
    928 paramCount: 1,
    929 paramValidators: []paramValidator{
    930 stringValidator, // packagePath
    931 },
    932 handlerFunc: func(_ int, rlm realm, params []string) error {
    933 // Upgrade common (token resolution) implementation
    934 cm.UpgradeImpl(cross(rlm), params[0]) // packagePath
    935 return nil
    936 },
    937 },
    938 }
    939
    940 // Register all configured handlers in the registry
    941 registerHandlers(registry, handlers)
    942
    943 return registry
    944}
    945
    946// registerHandlers batch registers all configured handlers into the registry.
    947// This helper function processes the handler configuration array and adds each handler to the registry.
    948//
    949// Parameters:
    950// - registry: the parameter registry to add handlers to
    951// - handlerOptions: slice of handler configurations to register
    952func registerHandlers(registry *ParameterRegistry, handlerOptions []*ParameterHandlerOptions) {
    953 for _, handlerOption := range handlerOptions {
    954 registry.Register(*handlerOption)
    955 }
    956}
    957
    958// runValidator executes a validator function and converts panics to errors.
    959func runValidator(fn func()) (err error) {
    960 defer func() {
    961 if r := recover(); r != nil {
    962 if e, ok := r.(error); ok {
    963 err = e
    964 return
    965 }
    966 err = ufmt.Errorf("%v", r)
    967 }
    968 }()
    969
    970 fn()
    971 return nil
    972}
    973
    974// Basic reusable validators for proposal-time type checking.
    975var (
    976 stringValidator = func(s string) error {
    977 return nil
    978 }
    979 boolValidator = func(s string) error {
    980 return runValidator(func() {
    981 parseBool(s)
    982 })
    983 }
    984 uint64Validator = func(s string) error {
    985 return runValidator(func() {
    986 parseUint64(s)
    987 })
    988 }
    989 addressValidator = func(s string) error {
    990 return runValidator(func() {
    991 addr := address(s)
    992 if !addr.IsValid() {
    993 panic(ufmt.Sprintf("invalid address: %s", addr))
    994 }
    995 })
    996 }
    997)
    998
    999func numberValidator(kind numberKind) paramValidator {
    1000 return func(s string) error {
    1001 return runValidator(func() {
    1002 parseNumber(s, kind)
    1003 })
    1004 }
    1005}
    1006
    1007func uint8RangeValidator(name string) paramValidator {
    1008 return func(s string) error {
    1009 return runValidator(func() {
    1010 value := parseInt64(s)
    1011 if value < 0 || value > 255 {
    1012 panic(ufmt.Sprintf("%s out of range: %d", name, value))
    1013 }
    1014 })
    1015 }
    1016}
    1017
    1018func roleNameValidator(s string) error {
    1019 return runValidator(func() {
    1020 roleName := strings.TrimSpace(s)
    1021 if roleName == "" {
    1022 panic(ufmt.Sprintf("role name is empty: %q", s))
    1023 }
    1024 })
    1025}
    1026
    1027func updatableRoleNameValidator(s string) error {
    1028 return runValidator(func() {
    1029 roleName := strings.TrimSpace(s)
    1030 if err := roleNameValidator(roleName); err != nil {
    1031 panic(err)
    1032 }
    1033
    1034 if roleName == prbac.ROLE_ADMIN.String() {
    1035 panic(ufmt.Sprintf("admin role cannot be updated: %s", roleName))
    1036 }
    1037 })
    1038}
    1039
    1040func removableRoleNameValidator(s string) error {
    1041 return runValidator(func() {
    1042 roleName := strings.TrimSpace(s)
    1043 if err := roleNameValidator(roleName); err != nil {
    1044 panic(err)
    1045 }
    1046
    1047 if prbac.IsSystemRole(roleName) {
    1048 panic(ufmt.Sprintf("system role cannot be removed: %s", roleName))
    1049 }
    1050 })
    1051}
    1052
    1053func nonNegativeInt64Validator(name string) paramValidator {
    1054 return func(s string) error {
    1055 return runValidator(func() {
    1056 value := parseInt64(s)
    1057 if value < 0 {
    1058 panic(ufmt.Sprintf("%s must be non-negative: %d", name, value))
    1059 }
    1060 })
    1061 }
    1062}
    1063
    1064func positiveInt64Validator(name string) paramValidator {
    1065 return func(s string) error {
    1066 return runValidator(func() {
    1067 value := parseInt64(s)
    1068 if value <= 0 {
    1069 panic(ufmt.Sprintf("%s must be positive: %d", name, value))
    1070 }
    1071 })
    1072 }
    1073}
    1074
    1075func int64RangeValidator(name string, min, max int64) paramValidator {
    1076 return func(s string) error {
    1077 return runValidator(func() {
    1078 value := parseInt64(s)
    1079 if value < min || value > max {
    1080 panic(ufmt.Sprintf("%s must be in range %d to %d: %d", name, min, max, value))
    1081 }
    1082 })
    1083 }
    1084}
    1085
    1086func uint64RangeValidator(name string, max uint64) paramValidator {
    1087 return func(s string) error {
    1088 return runValidator(func() {
    1089 value := parseUint64(s)
    1090 if value > max {
    1091 panic(ufmt.Sprintf("%s must be in range 0 to %d: %d", name, max, value))
    1092 }
    1093 })
    1094 }
    1095}
    1096
    1097func haltLevelValidator(s string) error {
    1098 return runValidator(func() {
    1099 if !halt.HaltLevel(s).IsValid() {
    1100 panic(ufmt.Sprintf("invalid halt level: %s", s))
    1101 }
    1102 })
    1103}
    1104
    1105func haltOperationTypeValidator(s string) error {
    1106 return runValidator(func() {
    1107 if !halt.OpType(s).IsValid() {
    1108 panic(ufmt.Sprintf("invalid operation type: %s", s))
    1109 }
    1110 })
    1111}
    1112
    1113func tokenMinimumRewardAmountValidator(s string) error {
    1114 return runValidator(func() {
    1115 parts := strings.SplitN(s, ":", 2)
    1116 if len(parts) != 2 || parts[0] == "" {
    1117 panic("token minimum reward amount must be tokenPath:amount")
    1118 }
    1119 amount := parseInt64(parts[1])
    1120 if amount < 0 {
    1121 panic(ufmt.Sprintf("minimum reward amount must be non-negative: %d", amount))
    1122 }
    1123 })
    1124}
    1125
    1126func distributionPctCompositeValidator(params []string) error {
    1127 return runValidator(func() {
    1128 sum := int64(0)
    1129 for i, param := range params {
    1130 pct := parseInt64(param)
    1131 if pct < 0 || pct > 10000 {
    1132 panic(ufmt.Sprintf("percentage %d must be in range 0 to 10000: %d", i+1, pct))
    1133 }
    1134 sum += pct
    1135 }
    1136 if sum != 10000 {
    1137 panic(ufmt.Sprintf("sum of percentages must be 10000, got %d", sum))
    1138 }
    1139 })
    1140}
    1141
    1142func splitExecutionsRaw(executions string) []string {
    1143 if executions == "" {
    1144 return []string{}
    1145 }
    1146
    1147 return strings.Split(executions, messageSeparator)
    1148}
    1149
    1150func parseExecutionMessage(msg string) (pkgPath string, function string, params []string, partCount int) {
    1151 parts := strings.Split(msg, parameterSeparator)
    1152 partCount = len(parts)
    1153 if partCount != 3 {
    1154 return "", "", nil, partCount
    1155 }
    1156
    1157 pkgPath = parts[0]
    1158 function = parts[1]
    1159 if parts[2] == "" {
    1160 return pkgPath, function, []string{}, partCount
    1161 }
    1162
    1163 return pkgPath, function, strings.Split(parts[2], ","), partCount
    1164}
    1165
    1166// validateExecutions validates that all executions in a parameter change proposal
    1167// correspond to registered handlers in the global parameter registry.
    1168// This function performs comprehensive validation including:
    1169// - Basic format validation (count, structure)
    1170// - Handler existence verification in the registry
    1171// - Parameter count validation against handler expectations
    1172//
    1173// Parameters:
    1174// - numToExecute: number of parameter changes to execute
    1175// - msgs: pre-split slice of execution messages, where each message
    1176// is formatted as <pkgPath>*EXE*<function>*EXE*<params>
    1177//
    1178// Returns:
    1179// - error: validation error if any execution is invalid
    1180func validateExecutions(numToExecute int64, msgs []string) error {
    1181 // Validate execution count is positive
    1182 if numToExecute <= 0 {
    1183 return makeErrorWithDetails(
    1184 errInvalidInput,
    1185 "numToExecute is less than or equal to 0",
    1186 )
    1187 }
    1188
    1189 // Check if executions are empty
    1190 if len(msgs) == 0 {
    1191 return makeErrorWithDetails(
    1192 errInvalidInput,
    1193 "executions is empty",
    1194 )
    1195 }
    1196
    1197 // Validate execution count doesn't exceed maximum
    1198 if numToExecute > maxNumberOfExecution {
    1199 return makeErrorWithDetails(
    1200 errInvalidInput,
    1201 ufmt.Sprintf("numToExecute is greater than %d", maxNumberOfExecution),
    1202 )
    1203 }
    1204
    1205 msgCount := len(msgs)
    1206 // Validate execution count matches message count
    1207 if msgCount != int(numToExecute) {
    1208 return makeErrorWithDetails(
    1209 errInvalidInput,
    1210 ufmt.Sprintf("executions count (%d) does not match numToExecute (%d)", len(msgs), numToExecute),
    1211 )
    1212 }
    1213
    1214 // Parse and validate each execution message
    1215 for i, execution := range msgs {
    1216 pkgPath, function, params, partCount := parseExecutionMessage(execution)
    1217 if partCount != 3 {
    1218 // Provide more helpful error message based on what's wrong
    1219 detail := ufmt.Sprintf("execution[%d]: expected 3 parts (pkgPath, function, params), got %d", i, partCount)
    1220 return makeErrorWithDetails(
    1221 errInvalidMessageFormat,
    1222 detail,
    1223 )
    1224 }
    1225
    1226 // Validate package path and function are not empty
    1227 if pkgPath == "" {
    1228 return makeErrorWithDetails(
    1229 errInvalidInput,
    1230 ufmt.Sprintf("execution[%d]: package path is empty", i),
    1231 )
    1232 }
    1233
    1234 if function == "" {
    1235 return makeErrorWithDetails(
    1236 errInvalidInput,
    1237 ufmt.Sprintf("execution[%d]: function name is empty", i),
    1238 )
    1239 }
    1240
    1241 // Check if handler exists in registry
    1242 key := makeHandlerKey(pkgPath, function)
    1243 handler, err := globalParameterRegistry.Handler(key)
    1244 if err != nil {
    1245 return makeErrorWithDetails(
    1246 errInvalidExecution,
    1247 ufmt.Sprintf("execution[%d]: %s (key: %s)", i, err.Error(), key),
    1248 )
    1249 }
    1250
    1251 // Get expected parameter count from handler
    1252 handlerOpts, ok := handler.(*ParameterHandlerOptions)
    1253 if !ok {
    1254 return makeErrorWithDetails(
    1255 errInvalidExecution,
    1256 ufmt.Sprintf("execution[%d]: failed to get handler options", i),
    1257 )
    1258 }
    1259
    1260 // Validate parameter types/format ahead of proposal creation
    1261 if err := handlerOpts.ValidateParams(params); err != nil {
    1262 return makeErrorWithDetails(
    1263 errInvalidInput,
    1264 ufmt.Sprintf("execution[%d]: %v", i, err),
    1265 )
    1266 }
    1267 }
    1268
    1269 return nil
    1270}
    1271