Search Apps Documentation Source Content File Folder Download Copy Actions Download 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}