Search Apps Documentation Source Content File Folder Download Copy Actions Download

rotate.gno

2.21 Kb · 57 lines
 1// Package rotate is a single-use realm shipped at test-13 genesis whose
 2// sole purpose is to swap the gnoland1 sole T1 (`oldT1`) for the test-13
 3// sole T1 (`newT1`) after historical replay completes.
 4//
 5// The proposal-flow rotation pattern (manfred proposes self-withdraw →
 6// new-T1 votes + executes) is unworkable at genesis-mode replay because
 7// gov/dao exposes no API to discover the latest proposal ID across MsgRun
 8// txs — and the post-replay proposal counter depends on how many
 9// proposals manfred opened on gnoland1, which we can't determine
10// statically without re-executing the replay. This realm sidesteps the
11// problem entirely: a single genesis-mode MsgCall to Rotate does the
12// transfer through direct memberstore writes, no proposals involved.
13//
14// Phase-1 bootstrap (`transactions/base/bootstrap/govdao_prop1_test13.gno`) wires this package into
15// `dao.UpdateImpl(...AllowedDAOs)` at lock time, so memberstore.Get()
16// works from inside Rotate. Once Rotate runs it self-ejects from
17// AllowedDAOs, leaving the membership-mutation surface back at
18// `gno.land/r/gov/dao/v3/impl` alone.
19//
20// Single-use is enforced by the `runtime.ChainHeight() != 0` gate.
21// Migration txs run with BlockHeight=0 (forced by
22// `gnogenesis fork generate`'s readMigrationTxs), so during genesis
23// replay ChainHeight()==0 and Rotate proceeds; post-genesis any caller
24// gets a panic.
25package rotate
26
27import (
28	"chain/runtime"
29
30	"gno.land/r/gov/dao"
31	"gno.land/r/gov/dao/v3/memberstore"
32)
33
34const (
35	newT1 = address("g1aeddlftlfk27ret5rf750d7w5dume3kcsm8r8m")
36	oldT1 = address("g1manfred47kzduec920z88wfr64ylksmdcedlf5")
37)
38
39func Rotate(cur realm) {
40	if runtime.ChainHeight() != 0 {
41		panic("rotate is genesis-only")
42	}
43
44	ms := memberstore.Get(0, cur)
45	tier, ok := memberstore.GetTier(memberstore.T1)
46	if !ok {
47		panic("T1 tier not found")
48	}
49	if err := ms.SetMember(memberstore.T1, newT1, memberstore.NewMember(tier.InvitationPoints)); err != nil {
50		panic(err.Error())
51	}
52	ms.RemoveMember(oldT1)
53
54	// Pass nil DAO: bootstrap already installed impl.NewGovDAO() into dao.dao;
55	// rotate only narrows AllowedDAOs (removing itself) — DAO ref stays intact.
56	dao.UpdateImpl(cross(cur), dao.NewUpdateRequest(nil, []string{"gno.land/r/gov/dao/v3/impl"}))
57}