Skip to content

Commit 9855f53

Browse files
leohhhngfanton
andauthored
feat(examples): expose ownable & pausable safe objects, update ownable API (#3331)
## Description This PR exposes safe objects where possible for ownable and pausable packages. Let's start exposing variables named `Ownable`, ie: ```go var Ownable = ownable.New() ``` This is the intended use, as exposing this field allows direct, safe, MsgRun calls to access the ownable functions. It's also impossible to directly reassign the value of this variable from another realm. This PR also introduces a BREAKING CHANGE: the `Ownable.CallerIsOwner` API now returns a boolean instead of an error, which makes more sense considering the name of the function. --------- Co-authored-by: Guilhem Fanton <[email protected]>
1 parent fdedae9 commit 9855f53

File tree

19 files changed

+82
-137
lines changed

19 files changed

+82
-137
lines changed

examples/gno.land/p/demo/memeland/memeland.gno

+2-2
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ func (m *Memeland) RemovePost(id string) string {
160160
panic("id cannot be empty")
161161
}
162162

163-
if err := m.CallerIsOwner(); err != nil {
164-
panic(err)
163+
if !m.CallerIsOwner() {
164+
panic(ownable.ErrUnauthorized)
165165
}
166166

167167
for i, post := range m.Posts {

examples/gno.land/p/demo/ownable/exts/authorizable/authorizable.gno

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func NewAuthorizableWithAddress(addr std.Address) *Authorizable {
4141
}
4242

4343
func (a *Authorizable) AddToAuthList(addr std.Address) error {
44-
if err := a.CallerIsOwner(); err != nil {
44+
if !a.CallerIsOwner() {
4545
return ErrNotSuperuser
4646
}
4747

@@ -55,7 +55,7 @@ func (a *Authorizable) AddToAuthList(addr std.Address) error {
5555
}
5656

5757
func (a *Authorizable) DeleteFromAuthList(addr std.Address) error {
58-
if err := a.CallerIsOwner(); err != nil {
58+
if !a.CallerIsOwner() {
5959
return ErrNotSuperuser
6060
}
6161

examples/gno.land/p/demo/ownable/ownable.gno

+7-12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const OwnershipTransferEvent = "OwnershipTransfer"
66

77
// Ownable is meant to be used as a top-level object to make your contract ownable OR
88
// being embedded in a Gno object to manage per-object ownership.
9+
// Ownable is safe to export as a top-level object
910
type Ownable struct {
1011
owner std.Address
1112
}
@@ -24,9 +25,8 @@ func NewWithAddress(addr std.Address) *Ownable {
2425

2526
// TransferOwnership transfers ownership of the Ownable struct to a new address
2627
func (o *Ownable) TransferOwnership(newOwner std.Address) error {
27-
err := o.CallerIsOwner()
28-
if err != nil {
29-
return err
28+
if !o.CallerIsOwner() {
29+
return ErrUnauthorized
3030
}
3131

3232
if !newOwner.IsValid() {
@@ -48,9 +48,8 @@ func (o *Ownable) TransferOwnership(newOwner std.Address) error {
4848
// Top-level usage: disables all only-owner actions/functions,
4949
// Embedded usage: behaves like a burn functionality, removing the owner from the struct
5050
func (o *Ownable) DropOwnership() error {
51-
err := o.CallerIsOwner()
52-
if err != nil {
53-
return err
51+
if !o.CallerIsOwner() {
52+
return ErrUnauthorized
5453
}
5554

5655
prevOwner := o.owner
@@ -71,12 +70,8 @@ func (o Ownable) Owner() std.Address {
7170
}
7271

7372
// CallerIsOwner checks if the caller of the function is the Realm's owner
74-
func (o Ownable) CallerIsOwner() error {
75-
if std.PrevRealm().Addr() == o.owner {
76-
return nil
77-
}
78-
79-
return ErrUnauthorized
73+
func (o Ownable) CallerIsOwner() bool {
74+
return std.PrevRealm().Addr() == o.owner
8075
}
8176

8277
// AssertCallerIsOwner panics if the caller is not the owner

examples/gno.land/p/demo/ownable/ownable_test.gno

+10-22
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
"gno.land/p/demo/testutils"
88
"gno.land/p/demo/uassert"
9+
"gno.land/p/demo/urequire"
910
)
1011

1112
var (
@@ -19,18 +20,14 @@ func TestNew(t *testing.T) {
1920

2021
o := New()
2122
got := o.Owner()
22-
if alice != got {
23-
t.Fatalf("Expected %s, got: %s", alice, got)
24-
}
23+
uassert.Equal(t, got, alice)
2524
}
2625

2726
func TestNewWithAddress(t *testing.T) {
2827
o := NewWithAddress(alice)
2928

3029
got := o.Owner()
31-
if alice != got {
32-
t.Fatalf("Expected %s, got: %s", alice, got)
33-
}
30+
uassert.Equal(t, got, alice)
3431
}
3532

3633
func TestTransferOwnership(t *testing.T) {
@@ -39,14 +36,11 @@ func TestTransferOwnership(t *testing.T) {
3936
o := New()
4037

4138
err := o.TransferOwnership(bob)
42-
if err != nil {
43-
t.Fatalf("TransferOwnership failed, %v", err)
44-
}
39+
urequire.NoError(t, err)
4540

4641
got := o.Owner()
47-
if bob != got {
48-
t.Fatalf("Expected: %s, got: %s", bob, got)
49-
}
42+
43+
uassert.Equal(t, got, bob)
5044
}
5145

5246
func TestCallerIsOwner(t *testing.T) {
@@ -58,8 +52,7 @@ func TestCallerIsOwner(t *testing.T) {
5852
std.TestSetRealm(std.NewUserRealm(unauthorizedCaller))
5953
std.TestSetOrigCaller(unauthorizedCaller) // TODO(bug): should not be needed
6054

61-
err := o.CallerIsOwner()
62-
uassert.Error(t, err) // XXX: IsError(..., unauthorizedCaller)
55+
uassert.False(t, o.CallerIsOwner())
6356
}
6457

6558
func TestDropOwnership(t *testing.T) {
@@ -68,7 +61,7 @@ func TestDropOwnership(t *testing.T) {
6861
o := New()
6962

7063
err := o.DropOwnership()
71-
uassert.NoError(t, err, "DropOwnership failed")
64+
urequire.NoError(t, err, "DropOwnership failed")
7265

7366
owner := o.Owner()
7467
uassert.Empty(t, owner, "owner should be empty")
@@ -85,13 +78,8 @@ func TestErrUnauthorized(t *testing.T) {
8578
std.TestSetRealm(std.NewUserRealm(bob))
8679
std.TestSetOrigCaller(bob) // TODO(bug): should not be needed
8780

88-
err := o.TransferOwnership(alice)
89-
if err != ErrUnauthorized {
90-
t.Fatalf("Should've been ErrUnauthorized, was %v", err)
91-
}
92-
93-
err = o.DropOwnership()
94-
uassert.ErrorContains(t, err, ErrUnauthorized.Error())
81+
uassert.ErrorContains(t, o.TransferOwnership(alice), ErrUnauthorized.Error())
82+
uassert.ErrorContains(t, o.DropOwnership(), ErrUnauthorized.Error())
9583
}
9684

9785
func TestErrInvalidAddress(t *testing.T) {

examples/gno.land/p/demo/pausable/pausable.gno

+4-4
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ func (p Pausable) IsPaused() bool {
3434

3535
// Pause sets the state of Pausable to true, meaning all pausable functions are paused
3636
func (p *Pausable) Pause() error {
37-
if err := p.CallerIsOwner(); err != nil {
38-
return err
37+
if !p.CallerIsOwner() {
38+
return ownable.ErrUnauthorized
3939
}
4040

4141
p.paused = true
@@ -46,8 +46,8 @@ func (p *Pausable) Pause() error {
4646

4747
// Unpause sets the state of Pausable to false, meaning all pausable functions are resumed
4848
func (p *Pausable) Unpause() error {
49-
if err := p.CallerIsOwner(); err != nil {
50-
return err
49+
if !p.CallerIsOwner() {
50+
return ownable.ErrUnauthorized
5151
}
5252

5353
p.paused = false

examples/gno.land/p/demo/subscription/lifetime/lifetime.gno

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func (ls *LifetimeSubscription) HasValidSubscription(addr std.Address) error {
6767

6868
// UpdateAmount allows the owner of the LifetimeSubscription contract to update the subscription price.
6969
func (ls *LifetimeSubscription) UpdateAmount(newAmount int64) error {
70-
if err := ls.CallerIsOwner(); err != nil {
70+
if !ls.CallerIsOwner() {
7171
return ErrNotAuthorized
7272
}
7373

examples/gno.land/p/demo/subscription/recurring/recurring.gno

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ func (rs *RecurringSubscription) GetExpiration(addr std.Address) (time.Time, err
9090

9191
// UpdateAmount allows the owner of the subscription contract to change the required subscription amount.
9292
func (rs *RecurringSubscription) UpdateAmount(newAmount int64) error {
93-
if err := rs.CallerIsOwner(); err != nil {
93+
if !rs.CallerIsOwner() {
9494
return ErrNotAuthorized
9595
}
9696

examples/gno.land/p/n2p5/mgroup/mgroup.gno

+8-8
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ func New(ownerAddress std.Address) *ManagedGroup {
4444
// AddBackupOwner adds a backup owner to the group by std.Address.
4545
// If the caller is not the owner, an error is returned.
4646
func (g *ManagedGroup) AddBackupOwner(addr std.Address) error {
47-
if err := g.owner.CallerIsOwner(); err != nil {
48-
return err
47+
if !g.owner.CallerIsOwner() {
48+
return ownable.ErrUnauthorized
4949
}
5050
if !addr.IsValid() {
5151
return ErrInvalidAddress
@@ -57,8 +57,8 @@ func (g *ManagedGroup) AddBackupOwner(addr std.Address) error {
5757
// RemoveBackupOwner removes a backup owner from the group by std.Address.
5858
// The owner cannot be removed. If the caller is not the owner, an error is returned.
5959
func (g *ManagedGroup) RemoveBackupOwner(addr std.Address) error {
60-
if err := g.owner.CallerIsOwner(); err != nil {
61-
return err
60+
if !g.owner.CallerIsOwner() {
61+
return ownable.ErrUnauthorized
6262
}
6363
if !addr.IsValid() {
6464
return ErrInvalidAddress
@@ -90,8 +90,8 @@ func (g *ManagedGroup) ClaimOwnership() error {
9090
// AddMember adds a member to the group by std.Address.
9191
// If the caller is not the owner, an error is returned.
9292
func (g *ManagedGroup) AddMember(addr std.Address) error {
93-
if err := g.owner.CallerIsOwner(); err != nil {
94-
return err
93+
if !g.owner.CallerIsOwner() {
94+
return ownable.ErrUnauthorized
9595
}
9696
if !addr.IsValid() {
9797
return ErrInvalidAddress
@@ -104,8 +104,8 @@ func (g *ManagedGroup) AddMember(addr std.Address) error {
104104
// The owner cannot be removed. If the caller is not the owner,
105105
// an error is returned.
106106
func (g *ManagedGroup) RemoveMember(addr std.Address) error {
107-
if err := g.owner.CallerIsOwner(); err != nil {
108-
return err
107+
if !g.owner.CallerIsOwner() {
108+
return ownable.ErrUnauthorized
109109
}
110110
if !addr.IsValid() {
111111
return ErrInvalidAddress

examples/gno.land/r/demo/foo20/foo20.gno

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ import (
1717
var (
1818
Token, privateLedger = grc20.NewToken("Foo", "FOO", 4)
1919
UserTeller = Token.CallerTeller()
20-
owner = ownable.NewWithAddress("g1manfred47kzduec920z88wfr64ylksmdcedlf5") // @manfred
20+
Ownable = ownable.NewWithAddress("g1manfred47kzduec920z88wfr64ylksmdcedlf5") // @manfred
2121
)
2222

2323
func init() {
24-
privateLedger.Mint(owner.Owner(), 1_000_000*10_000) // @privateLedgeristrator (1M)
24+
privateLedger.Mint(Ownable.Owner(), 1_000_000*10_000) // @privateLedgeristrator (1M)
2525
getter := func() *grc20.Token { return Token }
2626
grc20reg.Register(getter, "")
2727
}
@@ -66,13 +66,13 @@ func Faucet() {
6666
}
6767

6868
func Mint(to pusers.AddressOrName, amount uint64) {
69-
owner.AssertCallerIsOwner()
69+
Ownable.AssertCallerIsOwner()
7070
toAddr := users.Resolve(to)
7171
checkErr(privateLedger.Mint(toAddr, amount))
7272
}
7373

7474
func Burn(from pusers.AddressOrName, amount uint64) {
75-
owner.AssertCallerIsOwner()
75+
Ownable.AssertCallerIsOwner()
7676
fromAddr := users.Resolve(from)
7777
checkErr(privateLedger.Burn(fromAddr, amount))
7878
}

examples/gno.land/r/demo/grc20factory/grc20factory.gno

+11
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,17 @@ func Burn(symbol string, from std.Address, amount uint64) {
120120
checkErr(inst.ledger.Burn(from, amount))
121121
}
122122

123+
// instance admin functionality
124+
func DropInstanceOwnership(symbol string) {
125+
inst := mustGetInstance(symbol)
126+
checkErr(inst.admin.DropOwnership())
127+
}
128+
129+
func TransferInstanceOwnership(symbol string, newOwner std.Address) {
130+
inst := mustGetInstance(symbol)
131+
checkErr(inst.admin.TransferOwnership(newOwner))
132+
}
133+
123134
func Render(path string) string {
124135
parts := strings.Split(path, "/")
125136
c := len(parts)

examples/gno.land/r/gnoland/events/administration.gno

-26
This file was deleted.

examples/gno.land/r/gnoland/events/events.gno

+7-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"strings"
1010
"time"
1111

12+
"gno.land/p/demo/ownable/exts/authorizable"
1213
"gno.land/p/demo/seqid"
1314
"gno.land/p/demo/ufmt"
1415
)
@@ -28,6 +29,9 @@ type (
2829
)
2930

3031
var (
32+
su = std.Address("g125em6arxsnj49vx35f0n0z34putv5ty3376fg5") // @leohhhn
33+
Auth = authorizable.NewAuthorizableWithAddress(su)
34+
3135
events = make(eventsSlice, 0) // sorted
3236
idCounter seqid.ID
3337
)
@@ -42,7 +46,7 @@ const (
4246
// AddEvent adds auth new event
4347
// Start time & end time need to be specified in RFC3339, ie 2024-08-08T12:00:00+02:00
4448
func AddEvent(name, description, link, location, startTime, endTime string) (string, error) {
45-
auth.AssertOnAuthList()
49+
Auth.AssertOnAuthList()
4650

4751
if strings.TrimSpace(name) == "" {
4852
return "", ErrEmptyName
@@ -81,7 +85,7 @@ func AddEvent(name, description, link, location, startTime, endTime string) (str
8185

8286
// DeleteEvent deletes an event with auth given ID
8387
func DeleteEvent(id string) {
84-
auth.AssertOnAuthList()
88+
Auth.AssertOnAuthList()
8589

8690
e, idx, err := GetEventByID(id)
8791
if err != nil {
@@ -99,7 +103,7 @@ func DeleteEvent(id string) {
99103
// It only updates values corresponding to non-empty arguments sent with the call
100104
// Note: if you need to update the start time or end time, you need to provide both every time
101105
func EditEvent(id string, name, description, link, location, startTime, endTime string) {
102-
auth.AssertOnAuthList()
106+
Auth.AssertOnAuthList()
103107

104108
e, _, err := GetEventByID(id)
105109
if err != nil {

examples/gno.land/r/gnoland/monit/monit.gno

+3-8
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ var (
2020
lastUpdate time.Time
2121
lastCaller std.Address
2222
wd = watchdog.Watchdog{Duration: 5 * time.Minute}
23-
owner = ownable.New() // TODO: replace with -> ownable.NewWithAddress...
23+
Ownable = ownable.New() // TODO: replace with -> ownable.NewWithAddress...
2424
watchdogDuration = 5 * time.Minute
2525
)
2626

@@ -37,9 +37,8 @@ func Incr() int {
3737
// Reset resets the realm state.
3838
// This function can only be called by the admin.
3939
func Reset() {
40-
if owner.CallerIsOwner() != nil { // TODO: replace with owner.AssertCallerIsOwner
41-
panic("unauthorized")
42-
}
40+
Ownable.AssertCallerIsOwner()
41+
4342
counter = 0
4443
lastCaller = std.PrevRealm().Addr()
4544
lastUpdate = time.Now()
@@ -53,7 +52,3 @@ func Render(_ string) string {
5352
counter, lastUpdate, lastCaller, status,
5453
)
5554
}
56-
57-
// TransferOwnership transfers ownership to a new owner. This is a proxy to
58-
// ownable.Ownable.TransferOwnership.
59-
func TransferOwnership(newOwner std.Address) { owner.TransferOwnership(newOwner) }

0 commit comments

Comments
 (0)