Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

upgrade.gno

3.01 Kb · 95 lines
 1package pool
 2
 3import (
 4	"errors"
 5
 6	"gno.land/r/gnoswap/access/v1"
 7)
 8
 9// RegisterInitializer registers a new pool implementation version.
10// This function is called by each version (v1, v2, etc.) during initialization
11// to register their implementation with the proxy system.
12//
13// Parameters:
14//   - cur: Current realm context; callers use cross(cur) when crossing into this
15//     realm.
16//   - initializer: Version factory receiving the forwarded discriminator, current
17//     realm, and shared IPoolStore; it returns the implementation instance to
18//     register and later activate.
19//
20// Security: Only contracts within the domain path can register initializers.
21// Each package path can only register once to prevent duplicate registrations.
22func RegisterInitializer(cur realm, initializer func(_ int, rlm realm, poolStore IPoolStore) IPool) {
23	initializerFunc := func(_ int, rlm realm, domainStore any) any {
24		access.AssertIsRlmCurrent(0, rlm)
25
26		currentPoolStore, ok := domainStore.(IPoolStore)
27		if !ok {
28			panic("domainStore is not an IPoolStore")
29		}
30
31		return initializer(0, rlm, currentPoolStore)
32	}
33
34	err := versionManager.RegisterInitializer(0, cur, initializerFunc)
35	if err != nil {
36		panic(err)
37	}
38
39	err = updateImplementation()
40	if err != nil {
41		panic(err)
42	}
43}
44
45// UpgradeImpl switches the active pool implementation to a different version.
46// This function allows seamless upgrades from one version to another without
47// data migration or downtime.
48//
49// Parameters:
50//   - cur: Current realm context; callers use cross(cur) when crossing into this
51//     realm.
52//   - packagePath: Full package path of a version previously registered for this
53//     pool domain.
54//
55// Security: Only admin or governance can perform upgrades.
56// The new implementation must have been previously registered via RegisterInitializer.
57// The pool must not be locked (see assertPoolUnlocked).
58func UpgradeImpl(cur realm, packagePath string) {
59	// Ensure only admin or governance can perform upgrades
60	caller := cur.Previous().Address()
61	access.AssertIsAdminOrGovernance(caller)
62
63	assertPoolUnlocked()
64
65	err := versionManager.ChangeImplementation(0, cur, packagePath)
66	if err != nil {
67		panic(err)
68	}
69
70	err = updateImplementation()
71	if err != nil {
72		panic(err)
73	}
74}
75
76// assertPoolUnlocked panics if the pool's reentrancy lock is currently held.
77// It mirrors poolV1.assertPoolUnlocked (r/gnoswap/pool/v1/lock.gno): read-only,
78// so it is safe to call before the admin/governance authorization check too.
79// HasUnlocked() is false until a swap has ever run, so pools with no swap
80// history are unaffected.
81func assertPoolUnlocked() {
82	s := NewPoolStore(kvStore)
83	if s.HasUnlocked() && !s.GetUnlocked() {
84		panic(errors.New(errUpgradeWhileLocked))
85	}
86}
87
88// GetImplementationPackagePath returns the package path of the currently active implementation.
89//
90// Returns:
91//   - packagePath: Full package path of the active implementation; empty before
92//     any version has been registered.
93func GetImplementationPackagePath() string {
94	return versionManager.GetCurrentPackagePath()
95}