Search Apps Documentation Source Content File Folder Download Copy Actions Download

ownable.gno

3.03 Kb ยท 124 lines
  1package ownable2step
  2
  3import (
  4	"chain"
  5	"chain/runtime"
  6)
  7
  8const OwnershipTransferEvent = "OwnershipTransfer"
  9
 10// Ownable2Step is a two-step ownership transfer package
 11// It allows the current owner to set a new owner and the new owner will need to accept the ownership before it is transferred
 12// XXX Implement using Ownable instead of replicating it.
 13type Ownable2Step struct {
 14	owner        address
 15	pendingOwner address
 16}
 17
 18func New() *Ownable2Step {
 19	return &Ownable2Step{
 20		owner:        runtime.CurrentRealm().Address(),
 21		pendingOwner: "",
 22	}
 23}
 24
 25func NewWithOrigin() *Ownable2Step {
 26	origin := runtime.OriginCaller()
 27	previous := runtime.PreviousRealm()
 28	if origin != previous.Address() {
 29		panic("NewWithOrigin() should be called from init() where std.PreviousRealm() is origin")
 30	}
 31	return &Ownable2Step{
 32		owner: origin,
 33	}
 34}
 35
 36func NewWithAddress(addr address) *Ownable2Step {
 37	return &Ownable2Step{
 38		owner:        addr,
 39		pendingOwner: "",
 40	}
 41}
 42
 43// TransferOwnership initiate the transfer of the ownership to a new address by setting the PendingOwner
 44func (o *Ownable2Step) TransferOwnership(newOwner address) error {
 45	if !o.OwnedByCurrent() {
 46		return ErrUnauthorized
 47	}
 48	if !newOwner.IsValid() {
 49		return ErrInvalidAddress
 50	}
 51
 52	o.pendingOwner = newOwner
 53	return nil
 54}
 55
 56// AcceptOwnership accepts the pending ownership transfer
 57func (o *Ownable2Step) AcceptOwnership() error {
 58	if o.pendingOwner.String() == "" {
 59		return ErrNoPendingOwner
 60	}
 61	if runtime.CurrentRealm().Address() != o.pendingOwner {
 62		return ErrPendingUnauthorized
 63	}
 64
 65	o.owner = o.pendingOwner
 66	o.pendingOwner = ""
 67
 68	return nil
 69}
 70
 71// DropOwnership 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 *Ownable2Step) DropOwnership() error {
 75	if !o.OwnedByCurrent() {
 76		return ErrUnauthorized
 77	}
 78
 79	prevOwner := o.owner
 80	o.owner = ""
 81	o.pendingOwner = ""
 82
 83	chain.Emit(
 84		OwnershipTransferEvent,
 85		"from", prevOwner.String(),
 86		"to", "",
 87	)
 88
 89	return nil
 90}
 91
 92// Owner returns the owner address from Ownable
 93func (o *Ownable2Step) Owner() address {
 94	return o.owner
 95}
 96
 97// PendingOwner returns the pending owner address from Ownable2Step
 98func (o *Ownable2Step) PendingOwner() address {
 99	return o.pendingOwner
100}
101
102// OwnedByCurrent checks if the caller of the function is the Realm's owner
103func (o *Ownable2Step) OwnedByCurrent() bool {
104	return runtime.CurrentRealm().Address() == o.owner
105}
106
107// AssertOwnedByCurrent panics if the caller is not the owner
108func (o *Ownable2Step) AssertOwnedByCurrent() {
109	if runtime.CurrentRealm().Address() != o.owner {
110		panic(ErrUnauthorized)
111	}
112}
113
114// OwnedByPrevious checks if the caller of the function is the Realm's owner
115func (o *Ownable2Step) OwnedByPrevious() bool {
116	return runtime.PreviousRealm().Address() == o.owner
117}
118
119// AssertOwnedByPrevious panics if the caller is not the owner
120func (o *Ownable2Step) AssertOwnedByPrevious() {
121	if runtime.PreviousRealm().Address() != o.owner {
122		panic(ErrUnauthorized)
123	}
124}