ownable.gno
2.94 Kb ยท 127 lines
1package ownable
2
3import (
4 "std"
5)
6
7const OwnershipTransferEvent = "OwnershipTransfer"
8
9// Ownable is meant to be used as a top-level object to make your contract ownable OR
10// being embedded in a Gno object to manage per-object ownership.
11// Ownable is safe to export as a top-level object
12type Ownable struct {
13 owner std.Address
14}
15
16func New() *Ownable {
17 return &Ownable{
18 owner: std.CurrentRealm().Address(),
19 }
20}
21
22func NewWithOrigin() *Ownable {
23 origin := std.OriginCaller()
24 previous := std.PreviousRealm()
25 if origin != previous.Address() {
26 panic("NewWithOrigin() should be called from init() where std.PreviousRealm() is origin")
27 }
28 return &Ownable{
29 owner: origin,
30 }
31}
32
33func NewWithAddress(addr std.Address) *Ownable {
34 return &Ownable{
35 owner: addr,
36 }
37}
38
39// TransferOwnership transfers ownership of the Ownable struct to a new address
40func (o *Ownable) TransferOwnership(newOwner std.Address) error {
41 if !o.OwnedByCurrent() {
42 return ErrUnauthorized
43 }
44
45 if !newOwner.IsValid() {
46 return ErrInvalidAddress
47 }
48
49 prevOwner := o.owner
50 o.owner = newOwner
51 std.Emit(
52 OwnershipTransferEvent,
53 "from", prevOwner.String(),
54 "to", newOwner.String(),
55 )
56
57 return nil
58}
59
60// DropOwnershipByCurrent removes the owner, effectively disabling any owner-related actions
61// Top-level usage: disables all only-owner actions/functions,
62// Embedded usage: behaves like a burn functionality, removing the owner from the struct
63func (o *Ownable) DropOwnershipByCurrent() error {
64 if !o.OwnedByCurrent() {
65 return ErrUnauthorized
66 }
67 o.dropOwnership(o.owner)
68 return nil
69}
70
71// DropOwnershipByPrevious removes the owner, effectively disabling any owner-related actions
72// Top-level usage: disables all only-owner actions/functions,
73// Embedded usage: behaves like a burn functionality, removing the owner from the struct
74func (o *Ownable) DropOwnershipByPrevious() error {
75 if !o.OwnedByPrevious() {
76 return ErrUnauthorized
77 }
78 o.dropOwnership(o.owner)
79 return nil
80}
81
82func (o *Ownable) dropOwnership(prevOwner std.Address) {
83 o.owner = ""
84 std.Emit(
85 OwnershipTransferEvent,
86 "from", prevOwner.String(),
87 "to", "",
88 )
89}
90
91// Owner returns the owner address from Ownable
92func (o *Ownable) Owner() std.Address {
93 if o == nil {
94 return std.Address("")
95 }
96 return o.owner
97}
98
99// OwnedByCurrent checks if the caller of the function is the Realm's owner
100func (o *Ownable) OwnedByCurrent() bool {
101 if o == nil {
102 return false
103 }
104 return std.CurrentRealm().Address() == o.owner
105}
106
107// AssertOwnedByCurrent panics if the caller is not the owner
108func (o *Ownable) AssertOwnedByCurrent() {
109 if !o.OwnedByCurrent() {
110 panic(ErrUnauthorized)
111 }
112}
113
114// OwnedByPrevious checks if the caller of the function is the Realm's owner
115func (o *Ownable) OwnedByPrevious() bool {
116 if o == nil {
117 return false
118 }
119 return std.PreviousRealm().Address() == o.owner
120}
121
122// AssertOwnedByPrevious panics if the caller is not the owner
123func (o *Ownable) AssertOwnedByPrevious() {
124 if !o.OwnedByPrevious() {
125 panic(ErrUnauthorized)
126 }
127}