1package revshare23import (4 "chain"5 "chain/banker"6 "strings"7 "testing"89 "gno.land/p/nt/testutils/v0"10 "gno.land/p/nt/uassert/v0"1112 subs "gno.land/r/g1qp5pt8cdq2f6kfdamn3yuxwg6quqnfpyewzz39/subscriptions"13)1415var (16 testAdmin = testutils.TestAddress("rsadmin")17 alice = testutils.TestAddress("rsalice")18 bob = testutils.TestAddress("rsbob")19 subber = testutils.TestAddress("rssubber")20 subber2 = testutils.TestAddress("rssubber2")21 mallory = testutils.TestAddress("rsmallory")22)2324// Harness facts, carried from the sibling suites: init runs with an25// empty origin (real deploys capture the signer); realm globals persist26// across tests while the banker resets; SetRealm binds to the CALLING27// frame only, so arming is inlined at every site; SkipHeights wipes the28// origin context. NEW for a two-realm money suite: the banker reset29// hits BOTH realms, so held-balance sync must restore revshare's30// backing AND the downstream subscriptions realm's backing, or the31// first cross-boundary banker send machine-panics the run.32func init() {33 admin = testAdmin34 sweeper = testAdmin35 self = chain.PackageAddress("gno.land/r/g1qp5pt8cdq2f6kfdamn3yuxwg6quqnfpyewzz39/revshare")36}3738func ugnot(n int64) chain.Coins { return chain.NewCoins(chain.NewCoin(Denom, n)) }3940func coinsOf(a address) int64 { return banker.NewReadonlyBanker().GetCoin(a, Denom) }4142// conserved asserts the local conservation equation at rest:43// everything this realm holds is members' earned-but-unclaimed value.44// (Out-of-band surplus tests manage their own expectations.)45func conserved(t *testing.T) {46 t.Helper()47 if Held() != UsersTotal() {48 t.Fatalf("conservation violated: Held=%d users=%d", Held(), UsersTotal())49 }50}5152// syncHeld restores BOTH realms' banker backing to match their53// persistent ledgers after the harness banker reset.54func syncHeld() {55 if want, have := UsersTotal(), coinsOf(Address()); want > have {56 testing.IssueCoins(Address(), ugnot(want-have))57 }58 if want, have := subs.Liabilities(), coinsOf(subs.Address()); want > have {59 testing.IssueCoins(subs.Address(), ugnot(want-have))60 }61}6263// SetRealm binds to the CALLING frame only, so arming is inlined at64// every call site — a helper that arms and returns is silently65// ineffective (the sibling suites' documented trap).6667// subscribe drives the REAL subscriptions realm: who pays exactly68// price into planID. Nothing is mocked.69func subscribe(cur realm, t *testing.T, who address, planID, price int64) int64 {70 t.Helper()71 testing.SetRealm(testing.NewUserRealm(who))72 testing.SetOriginCaller(who)73 testing.SetOriginSend(ugnot(price))74 testing.IssueCoins(subs.Address(), ugnot(price))75 return subs.Subscribe(cross(cur), planID)76}7778func TestInitialState(t *testing.T) {79 if Admin() != testAdmin || MemberCount() != 0 || TotalWeight() != 0 ||80 Pulled() != 0 || NumPlans() != 0 {81 t.Fatal("unexpected initial state")82 }83 conserved(t)84}8586// The no-members refusal must fire BEFORE any downstream call.87func TestPullNoMembers(cur realm, t *testing.T) {88 testing.SetRealm(testing.NewUserRealm(mallory))89 testing.SetOriginCaller(mallory)90 testing.SetOriginSend(nil)91 uassert.AbortsWithMessage(t, cur, "no members configured to receive revenue", func() {92 Pull(cross(cur))93 })94}9596func TestMembership(cur realm, t *testing.T) {97 testing.SetRealm(testing.NewUserRealm(mallory))98 testing.SetOriginCaller(mallory)99 testing.SetOriginSend(nil)100 uassert.AbortsWithMessage(t, cur, "admin only", func() {101 AddMember(cross(cur), alice, 3)102 })103104 testing.SetRealm(testing.NewUserRealm(testAdmin))105 testing.SetOriginCaller(testAdmin)106 testing.SetOriginSend(nil)107 var zero address108 uassert.AbortsContains(t, cur, "zero address", func() {109 AddMember(cross(cur), zero, 1)110 })111 uassert.AbortsContains(t, cur, "weight must be in", func() {112 AddMember(cross(cur), alice, 0)113 })114 uassert.AbortsContains(t, cur, "weight must be in", func() {115 AddMember(cross(cur), alice, MaxWeight+1)116 })117118 testing.SetRealm(testing.NewUserRealm(testAdmin))119 testing.SetOriginCaller(testAdmin)120 testing.SetOriginSend(nil)121 AddMember(cross(cur), alice, 3)122 testing.SetRealm(testing.NewUserRealm(testAdmin))123 testing.SetOriginCaller(testAdmin)124 testing.SetOriginSend(nil)125 AddMember(cross(cur), bob, 1)126127 testing.SetRealm(testing.NewUserRealm(testAdmin))128 testing.SetOriginCaller(testAdmin)129 testing.SetOriginSend(nil)130 uassert.AbortsWithMessage(t, cur, "already a member", func() {131 AddMember(cross(cur), alice, 5)132 })133 uassert.AbortsWithMessage(t, cur, "not a member", func() {134 SetWeight(cross(cur), mallory, 2)135 })136 uassert.AbortsContains(t, cur, "weight must be in", func() {137 SetWeight(cross(cur), alice, 0)138 })139140 if MemberCount() != 2 || TotalWeight() != 4 ||141 MemberWeight(alice) != 3 || MemberWeight(bob) != 1 {142 t.Fatal("membership state wrong")143 }144}145146// The provider flow across all three value boundaries, against the147// REAL subscriptions realm.148func TestProviderFlowAndPull(cur realm, t *testing.T) {149 syncHeld()150151 // Plan creation is admin-gated HERE (quota griefing) before the152 // downstream call.153 testing.SetRealm(testing.NewUserRealm(mallory))154 testing.SetOriginCaller(mallory)155 testing.SetOriginSend(nil)156 uassert.AbortsWithMessage(t, cur, "admin only", func() {157 CreatePlan(cross(cur), "team", "d", 1000, 10, 1000)158 })159160 testing.SetRealm(testing.NewUserRealm(testAdmin))161 testing.SetOriginCaller(testAdmin)162 testing.SetOriginSend(nil)163 planID := CreatePlan(cross(cur), "team", "d", 1000, 10, 1000)164 if NumPlans() != 1 || PlanID(0) != planID {165 t.Fatal("plan bookkeeping wrong")166 }167168 // Downstream truth: the PROVIDER of the plan is this realm.169 provider, _, price, _, _, status, _ := subs.PlanInfo(planID)170 if provider != Address() || price != 1000 || status != "active" {171 t.Fatalf("downstream plan wrong: provider=%v price=%d status=%q",172 provider, price, status)173 }174175 // Boundary B1: subscriber pays the subscriptions realm directly.176 subID := subscribe(cur, t, subber, planID, 1000)177 if Receivable() != 1000 {178 t.Fatalf("receivable=%d, want 1000", Receivable())179 }180 if Held() != 0 {181 t.Fatal("nothing should be held here before Pull")182 }183 _ = subID184185 // Boundary B2: anyone may crank the pull (permissionless).186 heldBefore := Held()187 testing.SetRealm(testing.NewUserRealm(mallory))188 testing.SetOriginCaller(mallory)189 testing.SetOriginSend(nil)190 got := Pull(cross(cur))191 if got != 1000 || Held()-heldBefore != 1000 || Receivable() != 0 {192 t.Fatalf("pull moved wrong value: got=%d held=%d receivable=%d",193 got, Held(), Receivable())194 }195 // 3:1 split of 1000 -> 750 / 250, no dust.196 if BalanceOf(alice) != 750 || BalanceOf(bob) != 250 || BalanceOf(mallory) != 0 {197 t.Fatalf("split wrong: alice=%d bob=%d mallory=%d",198 BalanceOf(alice), BalanceOf(bob), BalanceOf(mallory))199 }200 if Pulled() != 1000 || UsersTotal() != 1000 {201 t.Fatal("lifetime accounting wrong")202 }203 conserved(t)204}205206// Replay: the downstream realm holds the replay guard — an empty207// receivable aborts there and no local state changes.208func TestPullReplay(cur realm, t *testing.T) {209 syncHeld()210 usersBefore, pulledBefore := UsersTotal(), Pulled()211 testing.SetRealm(testing.NewUserRealm(mallory))212 testing.SetOriginCaller(mallory)213 testing.SetOriginSend(nil)214 uassert.AbortsWithMessage(t, cur, "nothing to claim", func() {215 Pull(cross(cur))216 })217 if UsersTotal() != usersBefore || Pulled() != pulledBefore {218 t.Fatal("aborted pull mutated state")219 }220 conserved(t)221}222223// Rounding: dust goes to the highest-weight member, deterministically,224// and the sum always equals the pulled amount exactly.225func TestRoundingDust(cur realm, t *testing.T) {226 syncHeld()227 testing.SetRealm(testing.NewUserRealm(testAdmin))228 testing.SetOriginCaller(testAdmin)229 testing.SetOriginSend(nil)230 planID := CreatePlan(cross(cur), "odd", "d", 1001, 10, 1000)231 subscribe(cur, t, subber2, planID, 1001)232233 a0, b0 := BalanceOf(alice), BalanceOf(bob)234 testing.SetRealm(testing.NewUserRealm(mallory))235 testing.SetOriginCaller(mallory)236 testing.SetOriginSend(nil)237 Pull(cross(cur))238 // 1001 at 3:1 -> alice floor 750 + dust 1 = 751, bob 250.239 if BalanceOf(alice)-a0 != 751 || BalanceOf(bob)-b0 != 250 {240 t.Fatalf("dust policy wrong: alice+%d bob+%d",241 BalanceOf(alice)-a0, BalanceOf(bob)-b0)242 }243 conserved(t)244}245246// Minimum values: a 1ugnot pull where every floor share is zero still247// conserves — the whole amount is dust to the highest weight.248func TestMinimumPull(cur realm, t *testing.T) {249 syncHeld()250 testing.SetRealm(testing.NewUserRealm(testAdmin))251 testing.SetOriginCaller(testAdmin)252 testing.SetOriginSend(nil)253 planID := CreatePlan(cross(cur), "min", "d", 1, 10, 1000)254 subscribe(cur, t, subber, planID, 1)255256 a0, b0 := BalanceOf(alice), BalanceOf(bob)257 testing.SetRealm(testing.NewUserRealm(mallory))258 testing.SetOriginCaller(mallory)259 testing.SetOriginSend(nil)260 got := Pull(cross(cur))261 if got != 1 || BalanceOf(alice)-a0 != 1 || BalanceOf(bob)-b0 != 0 {262 t.Fatal("minimum pull mishandled")263 }264 conserved(t)265}266267// Weight changes shape FUTURE pulls only; earned balances never move.268func TestWeightChangeFutureOnly(cur realm, t *testing.T) {269 syncHeld()270 a0, b0 := BalanceOf(alice), BalanceOf(bob)271272 testing.SetRealm(testing.NewUserRealm(testAdmin))273 testing.SetOriginCaller(testAdmin)274 testing.SetOriginSend(nil)275 SetWeight(cross(cur), bob, 3)276 if BalanceOf(alice) != a0 || BalanceOf(bob) != b0 {277 t.Fatal("weight change touched earned balances")278 }279 if TotalWeight() != 6 {280 t.Fatalf("totalWeight=%d, want 6", TotalWeight())281 }282283 testing.SetRealm(testing.NewUserRealm(testAdmin))284 testing.SetOriginCaller(testAdmin)285 testing.SetOriginSend(nil)286 planID := CreatePlan(cross(cur), "even", "d", 600, 10, 1000)287 subscribe(cur, t, subber2, planID, 600)288 testing.SetRealm(testing.NewUserRealm(mallory))289 testing.SetOriginCaller(mallory)290 testing.SetOriginSend(nil)291 Pull(cross(cur))292 // 600 at 3:3 -> 300 each.293 if BalanceOf(alice)-a0 != 300 || BalanceOf(bob)-b0 != 300 {294 t.Fatal("new weights not applied to new revenue")295 }296 conserved(t)297}298299// Boundary B3: members pull their earnings out; strangers get nothing.300func TestClaims(cur realm, t *testing.T) {301 syncHeld()302 earned := BalanceOf(alice)303 if earned == 0 {304 t.Fatal("fixture: alice should have earnings")305 }306 before := coinsOf(alice)307 testing.SetRealm(testing.NewUserRealm(alice))308 testing.SetOriginCaller(alice)309 testing.SetOriginSend(nil)310 ClaimAll(cross(cur))311 if coinsOf(alice)-before != earned || BalanceOf(alice) != 0 {312 t.Fatal("claim did not move the earned balance")313 }314315 bobBefore, bobCoins := BalanceOf(bob), coinsOf(bob)316 testing.SetRealm(testing.NewUserRealm(bob))317 testing.SetOriginCaller(bob)318 testing.SetOriginSend(nil)319 Claim(cross(cur), 100)320 if BalanceOf(bob) != bobBefore-100 || coinsOf(bob)-bobCoins != 100 {321 t.Fatal("partial claim wrong")322 }323 testing.SetRealm(testing.NewUserRealm(bob))324 testing.SetOriginCaller(bob)325 testing.SetOriginSend(nil)326 uassert.AbortsContains(t, cur, "insufficient balance", func() {327 Claim(cross(cur), BalanceOf(bob)+1)328 })329330 testing.SetRealm(testing.NewUserRealm(mallory))331 testing.SetOriginCaller(mallory)332 testing.SetOriginSend(nil)333 uassert.AbortsWithMessage(t, cur, "nothing to claim", func() {334 ClaimAll(cross(cur))335 })336 conserved(t)337}338339// Removal never touches earned value: the ex-member keeps claiming.340func TestRemoveMemberKeepsBalance(cur realm, t *testing.T) {341 syncHeld()342 bobBal := BalanceOf(bob)343 if bobBal == 0 {344 t.Fatal("fixture: bob should still have a balance")345 }346 testing.SetRealm(testing.NewUserRealm(testAdmin))347 testing.SetOriginCaller(testAdmin)348 testing.SetOriginSend(nil)349 RemoveMember(cross(cur), bob)350 if MemberCount() != 1 || TotalWeight() != 3 || BalanceOf(bob) != bobBal {351 t.Fatal("removal corrupted state")352 }353354 // Future revenue goes entirely to the remaining member.355 testing.SetRealm(testing.NewUserRealm(testAdmin))356 testing.SetOriginCaller(testAdmin)357 testing.SetOriginSend(nil)358 planID := CreatePlan(cross(cur), "solo", "d", 500, 10, 1000)359 subscribe(cur, t, subber, planID, 500)360 a0 := BalanceOf(alice)361 testing.SetRealm(testing.NewUserRealm(mallory))362 testing.SetOriginCaller(mallory)363 testing.SetOriginSend(nil)364 Pull(cross(cur))365 if BalanceOf(alice)-a0 != 500 || BalanceOf(bob) != bobBal {366 t.Fatal("post-removal distribution wrong")367 }368369 // The ex-member's balance remains claimable.370 before := coinsOf(bob)371 testing.SetRealm(testing.NewUserRealm(bob))372 testing.SetOriginCaller(bob)373 testing.SetOriginSend(nil)374 ClaimAll(cross(cur))375 if coinsOf(bob)-before != bobBal {376 t.Fatal("ex-member could not claim")377 }378 conserved(t)379}380381// Plan retirement crosses the boundary admin-gated here, provider-only382// downstream.383func TestRetirePlan(cur realm, t *testing.T) {384 syncHeld()385 planID := PlanID(0)386 testing.SetRealm(testing.NewUserRealm(mallory))387 testing.SetOriginCaller(mallory)388 testing.SetOriginSend(nil)389 uassert.AbortsWithMessage(t, cur, "admin only", func() {390 RetirePlan(cross(cur), planID)391 })392 testing.SetRealm(testing.NewUserRealm(testAdmin))393 testing.SetOriginCaller(testAdmin)394 testing.SetOriginSend(nil)395 RetirePlan(cross(cur), planID)396 _, _, _, _, _, status, _ := subs.PlanInfo(planID)397 if status != "retired" {398 t.Fatalf("downstream not retired: %q", status)399 }400 // Downstream refuses new subscriptions to a retired plan.401 testing.SetRealm(testing.NewUserRealm(mallory))402 testing.SetOriginCaller(mallory)403 testing.SetOriginSend(ugnot(1000))404 testing.IssueCoins(subs.Address(), ugnot(1000))405 uassert.AbortsContains(t, cur, "plan is not active", func() {406 subs.Subscribe(cross(cur), planID)407 })408}409410// Every entrypoint refuses coin-carrying transactions.411func TestStraySend(cur realm, t *testing.T) {412 for _, f := range []func(){413 func() { Pull(cross(cur)) },414 func() { ClaimAll(cross(cur)) },415 func() { AddMember(cross(cur), mallory, 1) },416 func() { CreatePlan(cross(cur), "x", "d", 1000, 10, 1000) },417 func() { SweepDenom(cross(cur), Denom) },418 } {419 testing.SetRealm(testing.NewUserRealm(testAdmin))420 testing.SetOriginCaller(testAdmin)421 testing.SetOriginSend(ugnot(5))422 uassert.AbortsWithMessage(t, cur, "this function does not accept coins", f)423 }424}425426// Out-of-band value: the reserve protects member balances; foreign427// denominations sweep in full.428func TestSweepReserve(cur realm, t *testing.T) {429 syncHeld()430 testing.SetRealm(testing.NewUserRealm(testAdmin))431 testing.SetOriginCaller(testAdmin)432 testing.SetOriginSend(nil)433 uassert.AbortsContains(t, cur, "no surplus to sweep", func() {434 SweepDenom(cross(cur), Denom)435 })436437 testing.IssueCoins(Address(), ugnot(77))438 reserveBefore := UsersTotal()439 got := coinsOf(testAdmin)440 testing.SetRealm(testing.NewUserRealm(testAdmin))441 testing.SetOriginCaller(testAdmin)442 testing.SetOriginSend(nil)443 SweepDenom(cross(cur), Denom)444 if coinsOf(testAdmin)-got != 77 || UsersTotal() != reserveBefore {445 t.Fatal("sweep wrong or touched the reserve")446 }447448 testing.IssueCoins(Address(), chain.NewCoins(chain.NewCoin("foo", 9)))449 testing.SetRealm(testing.NewUserRealm(testAdmin))450 testing.SetOriginCaller(testAdmin)451 testing.SetOriginSend(nil)452 SweepDenom(cross(cur), "foo")453 if banker.NewReadonlyBanker().GetCoin(testAdmin, "foo") != 9 {454 t.Fatal("foreign denom not swept in full")455 }456457 testing.SetRealm(testing.NewUserRealm(mallory))458 testing.SetOriginCaller(mallory)459 testing.SetOriginSend(nil)460 uassert.AbortsWithMessage(t, cur, "sweeper only", func() {461 SweepDenom(cross(cur), Denom)462 })463 conserved(t)464}465466func TestAdminHandover(cur realm, t *testing.T) {467 testing.SetRealm(testing.NewUserRealm(testAdmin))468 testing.SetOriginCaller(testAdmin)469 testing.SetOriginSend(nil)470 TransferAdmin(cross(cur), alice)471 testing.SetRealm(testing.NewUserRealm(mallory))472 testing.SetOriginCaller(mallory)473 testing.SetOriginSend(nil)474 uassert.AbortsWithMessage(t, cur, "only the staged successor may accept", func() {475 AcceptAdmin(cross(cur))476 })477 testing.SetRealm(testing.NewUserRealm(alice))478 testing.SetOriginCaller(alice)479 testing.SetOriginSend(nil)480 AcceptAdmin(cross(cur))481 if Admin() != alice {482 t.Fatal("authority did not move")483 }484 // Former admin locked out of members, plans and sweep.485 testing.SetRealm(testing.NewUserRealm(testAdmin))486 testing.SetOriginCaller(testAdmin)487 testing.SetOriginSend(nil)488 uassert.AbortsWithMessage(t, cur, "admin only", func() {489 AddMember(cross(cur), mallory, 1)490 })491 uassert.AbortsWithMessage(t, cur, "sweeper only", func() {492 SweepDenom(cross(cur), Denom)493 })494 // Hand back.495 testing.SetRealm(testing.NewUserRealm(alice))496 testing.SetOriginCaller(alice)497 testing.SetOriginSend(nil)498 TransferAdmin(cross(cur), testAdmin)499 testing.SetRealm(testing.NewUserRealm(testAdmin))500 testing.SetOriginCaller(testAdmin)501 testing.SetOriginSend(nil)502 AcceptAdmin(cross(cur))503}504505func TestMemberTableBounds(cur realm, t *testing.T) {506 testing.SetRealm(testing.NewUserRealm(testAdmin))507 testing.SetOriginCaller(testAdmin)508 testing.SetOriginSend(nil)509 for i := MemberCount(); i < int64(MaxMembers); i++ {510 testing.SetRealm(testing.NewUserRealm(testAdmin))511 testing.SetOriginCaller(testAdmin)512 testing.SetOriginSend(nil)513 AddMember(cross(cur), testutils.TestAddress("rsfill"+string(rune('a'+i))), 1)514 }515 testing.SetRealm(testing.NewUserRealm(testAdmin))516 testing.SetOriginCaller(testAdmin)517 testing.SetOriginSend(nil)518 uassert.AbortsContains(t, cur, "member table is full", func() {519 AddMember(cross(cur), testutils.TestAddress("rsoverflow"), 1)520 })521}522523func TestRender(t *testing.T) {524 out := Render("")525 if !strings.Contains(out, "receivable") || !strings.Contains(out, "| member |") {526 t.Fatal("render missing sections")527 }528 if Render("x") == Render("") {529 t.Fatal("unknown path fell through")530 }531}532AcceptAdmin(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string})
AddMember(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, a string, weight int64)
Address() string
Admin() string
BalanceOf(a string) int64
Claim(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, amount int64)
ClaimAll(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string})
CreatePlan(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, title string, description string, price int64, periodBlocks int64, maxFeeBps int64) int64
Held() int64
MemberCount() int64
MemberWeight(a string) int64
NumPlans() int64
PendingAdmin() string
PlanID(i int64) int64
Pull(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}) int64
Pulled() int64
Receivable() int64
RemoveMember(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, a string)
Render(path string) string
RetirePlan(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, planID int64)
SetWeight(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, a string, weight int64)
SweepDenom(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, denom string)
TotalWeight() int64
TransferAdmin(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, successor string)
UsersTotal() int64
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
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.