Module admin_hand_over

Expand source code
import smartpy as sp


class AdminHandOver(sp.Contract):
    """This contract implements a mechanism to switch administrator (an address
    that with special permission) in a way that prevents the administrator from
    handing over to an address with a typo or a contract without an interaction
    code.

    The problem: An administrator hands the contract over to a new administrator
    and then discovers that they made a typing error in the address.
    In this case, the contract can no longer be administered.

    The solution: The administrator hand over is a two step process:
    1. the current administrator adds a candidate admin.
    2. the new administrator removes the old one.
    """

    def __init__(self, admins):
        """
        Args:
            admins (sp.TSet of sp.TAddress): The contract's administrators.
        """
        self.init(admins=admins)

    @sp.entrypoint(new_syntax = True)
    def add_admins(self, admins):
        """Add new administrators.

        Args:
            admins (sp.TList of sp.TAddress): The new admins.
        Raises:
            `Only an admin can call this entrypoint.`
        """
        assert \
          self.data.admins.contains(sp.sender), \
          "Only an admin can call this entrypoint."

        for admin in admins:
            self.data.admins.add(admin)

    @sp.entrypoint(new_syntax = True)
    def remove_admins(self, admins):
        """Remove administrators.

        An admin cannot remove themselves.

        Args:
            admins (sp.TList of sp.TAddress): The admins to remove.
        Raises:
            `Only an admin can call this entrypoint.`
            `An admin cannot remove themselves.`
        """
        assert \
          self.data.admins.contains(sp.sender), \
          "Only an admin can call this entrypoint."

        for admin in admins:
            assert admin != sp.sender, "An admin cannot remove themselves."
            self.data.admins.remove(admin)

    @sp.entrypoint(new_syntax = True)
    def protected(self):
        """Example of entrypoint reserved to administrators.

        Raises:
            `Only an admin can call this entrypoint.`
        """
        assert \
          self.data.admins.contains(sp.sender), \
          "Only an admin can call this entrypoint."



# This prevent tests from being executed on importation.
if "templates" not in __name__:

    first_admin = sp.test_account("first_admin")
    new_admin = sp.test_account("new_admin")

    @sp.add_test(name="Admin hand over basic scenario", is_default=True)
    def basic_scenario():
        """Test:
        - Origination
        - An admin adds a new admin.
        - The new admin removes the older admin.
        - The new admin calls the protected entrypoint.
        """
        sc = sp.test_scenario()
        sc.h1("Basic scenario.")

        sc.h2("Origination.")
        c1 = AdminHandOver(admins=sp.set([first_admin.address]))
        sc += c1

        sc.h2("An admin adds a new admin.")
        c1.add_admins([new_admin.address]).run(sender=first_admin)

        sc.h2("The new admin removes the older admin.")
        c1.remove_admins([first_admin.address]).run(sender=new_admin)

        sc.h2("The new admin calls the protected entrypoint")
        c1.protected().run(sender=new_admin)

Classes

class AdminHandOver (admins)

This contract implements a mechanism to switch administrator (an address that with special permission) in a way that prevents the administrator from handing over to an address with a typo or a contract without an interaction code.

The problem: An administrator hands the contract over to a new administrator and then discovers that they made a typing error in the address. In this case, the contract can no longer be administered.

The solution: The administrator hand over is a two step process: 1. the current administrator adds a candidate admin. 2. the new administrator removes the old one.

Args

admins : sp.TSet of sp.TAddress
The contract's administrators.
Expand source code
class AdminHandOver(sp.Contract):
    """This contract implements a mechanism to switch administrator (an address
    that with special permission) in a way that prevents the administrator from
    handing over to an address with a typo or a contract without an interaction
    code.

    The problem: An administrator hands the contract over to a new administrator
    and then discovers that they made a typing error in the address.
    In this case, the contract can no longer be administered.

    The solution: The administrator hand over is a two step process:
    1. the current administrator adds a candidate admin.
    2. the new administrator removes the old one.
    """

    def __init__(self, admins):
        """
        Args:
            admins (sp.TSet of sp.TAddress): The contract's administrators.
        """
        self.init(admins=admins)

    @sp.entrypoint(new_syntax = True)
    def add_admins(self, admins):
        """Add new administrators.

        Args:
            admins (sp.TList of sp.TAddress): The new admins.
        Raises:
            `Only an admin can call this entrypoint.`
        """
        assert \
          self.data.admins.contains(sp.sender), \
          "Only an admin can call this entrypoint."

        for admin in admins:
            self.data.admins.add(admin)

    @sp.entrypoint(new_syntax = True)
    def remove_admins(self, admins):
        """Remove administrators.

        An admin cannot remove themselves.

        Args:
            admins (sp.TList of sp.TAddress): The admins to remove.
        Raises:
            `Only an admin can call this entrypoint.`
            `An admin cannot remove themselves.`
        """
        assert \
          self.data.admins.contains(sp.sender), \
          "Only an admin can call this entrypoint."

        for admin in admins:
            assert admin != sp.sender, "An admin cannot remove themselves."
            self.data.admins.remove(admin)

    @sp.entrypoint(new_syntax = True)
    def protected(self):
        """Example of entrypoint reserved to administrators.

        Raises:
            `Only an admin can call this entrypoint.`
        """
        assert \
          self.data.admins.contains(sp.sender), \
          "Only an admin can call this entrypoint."

Ancestors

  • smartpy.Contract

Methods

def add_admins(self, admins)

Entrypoint. Add new administrators.

Args

admins : sp.TList of sp.TAddress
The new admins.

Raises

Only an admin can call this entrypoint.

Expand source code
@sp.entrypoint(new_syntax = True)
def add_admins(self, admins):
    """Add new administrators.

    Args:
        admins (sp.TList of sp.TAddress): The new admins.
    Raises:
        `Only an admin can call this entrypoint.`
    """
    assert \
      self.data.admins.contains(sp.sender), \
      "Only an admin can call this entrypoint."

    for admin in admins:
        self.data.admins.add(admin)
def remove_admins(self, admins)

Entrypoint. Remove administrators.

An admin cannot remove themselves.

Args

admins : sp.TList of sp.TAddress
The admins to remove.

Raises

Only an admin can call this entrypoint. An admin cannot remove themselves.

Expand source code
@sp.entrypoint(new_syntax = True)
def remove_admins(self, admins):
    """Remove administrators.

    An admin cannot remove themselves.

    Args:
        admins (sp.TList of sp.TAddress): The admins to remove.
    Raises:
        `Only an admin can call this entrypoint.`
        `An admin cannot remove themselves.`
    """
    assert \
      self.data.admins.contains(sp.sender), \
      "Only an admin can call this entrypoint."

    for admin in admins:
        assert admin != sp.sender, "An admin cannot remove themselves."
        self.data.admins.remove(admin)
def protected(self)

Entrypoint. Example of entrypoint reserved to administrators.

Raises

Only an admin can call this entrypoint.

Expand source code
@sp.entrypoint(new_syntax = True)
def protected(self):
    """Example of entrypoint reserved to administrators.

    Raises:
        `Only an admin can call this entrypoint.`
    """
    assert \
      self.data.admins.contains(sp.sender), \
      "Only an admin can call this entrypoint."