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}