Module baking_swap
Expand source code
import smartpy as sp
class BakingSwap(sp.Contract):
"""A contract that takes tez deposits and pays interest.
The deposited funds cannot leave the contract, but the administrator can
delegate them for baking.
In more detail:
- The administrator funds the contract with collateral.
- The administrator publishes an offer: a rate (in basis points) and a
duration (in days).
- For each deposit the amount to be paid out and the due date are recorded.
The corresponding amount of collateral is locked up.
- At maturity the deposit plus interest can be withdrawn.
"""
def __init__(self, admin, initialRate, initialDuration):
"""Constructor
Args:
admin (sp.TAddress): admin of the contract.
initialRate (sp.TNat): Basis points to compute the interest.
initialDuration (sp.TNat): Number of days before a deposit can be
withdrawn.
"""
self.init(
admin=admin,
collateral=sp.mutez(0),
ledger={},
rate=initialRate,
duration=initialDuration,
)
# Admin-only entrypoints
@sp.entrypoint(new_syntax = True)
def delegate(self, public_key_hash):
"""Admin-only. Delegate the contract's balance to the admin.
Args:
public_key_hash (sp.TKeyHash): public key hash of the admin.
"""
assert sp.sender == self.data.admin
assert sp.amount == sp.mutez(0)
assert sp.sender == sp.to_address(sp.implicit_account(public_key_hash))
sp.set_delegate(sp.Some(public_key_hash))
@sp.entrypoint(new_syntax = True)
def collateralize(self):
"""Admin-only. Provide tez as collateral for interest to be paid."""
assert sp.sender == self.data.admin
self.data.collateral += sp.amount
@sp.entrypoint(new_syntax = True)
def uncollateralize(self, amount, receiver):
"""Admin-only. Withdraw collateral.
Transfer `amount` mutez to admin if it doesn't exceed collateral.
Args:
amount (sp.TMutez): Amount to be removed from the collateral.
"""
assert sp.sender == self.data.admin
# Explicitly fails for insufficient collateral.
assert amount <= self.data.collateral, "insufficient collateral"
self.data.collateral -= amount
sp.send(receiver, amount)
@sp.entrypoint(new_syntax = True)
def set_offer(self, rate, duration):
"""Admin-only. Set the current offer: interest rate (in basis points)
and duration.
Args:
rate (sp.TNat): Basis points to compute the interest.
duration (sp.TNat): Number of days before a deposit can be withdrawn.
"""
assert sp.sender == self.data.admin
assert sp.amount == sp.mutez(0)
self.data.rate = rate
self.data.duration = duration
# Permissionless entrypoints
@sp.entrypoint(new_syntax = True)
def deposit(self, rate, duration):
"""Deposit tez. The current offer has to be repeated in the parameters.
Args:
rate (sp.TNat): Basis points to compute the interest.
duration (sp.TNat): Number of days before a deposit can be withdrawn.
"""
assert self.data.rate >= rate
assert self.data.duration <= duration
assert not self.data.ledger.contains(sp.sender)
# Compute interest to be paid.
interest = sp.split_tokens(sp.amount, self.data.rate, 10_000)
self.data.collateral -= interest
# Record the payment to be made.
self.data.ledger[sp.sender] = sp.record(
amount=sp.amount + interest,
due=sp.add_days(sp.now, self.data.duration),
)
@sp.entrypoint(new_syntax = True)
def withdraw(self, receiver):
"""Withdraw tez at maturity."""
assert sp.amount == sp.mutez(0)
entry = self.data.ledger.get(sp.sender, error="NoDeposit")
assert sp.now >= entry.due
sp.send(receiver, entry.amount)
del self.data.ledger[sp.sender]
if "templates" not in __name__:
admin = sp.test_account("Admin")
voting_powers = {
admin.public_key_hash: 0,
}
@sp.add_test(name="Baking")
def test():
scenario = sp.test_scenario()
scenario.h1("Baking Swap")
c = BakingSwap(admin.address, 700, 365)
scenario += c
c.delegate(admin.public_key_hash).run(sender=admin, voting_powers=voting_powers)
sp.add_compilation_target(
"bakingSwap", BakingSwap(sp.test_account("admin").address, 700, 365)
)
Classes
class BakingSwap (admin, initialRate, initialDuration)
-
A contract that takes tez deposits and pays interest.
The deposited funds cannot leave the contract, but the administrator can delegate them for baking.
In more detail:
-
The administrator funds the contract with collateral.
-
The administrator publishes an offer: a rate (in basis points) and a duration (in days).
-
For each deposit the amount to be paid out and the due date are recorded. The corresponding amount of collateral is locked up.
-
At maturity the deposit plus interest can be withdrawn.
Constructor
Args
admin
:sp.TAddress
- admin of the contract.
initialRate
:sp.TNat
- Basis points to compute the interest.
initialDuration
:sp.TNat
- Number of days before a deposit can be withdrawn.
Expand source code
class BakingSwap(sp.Contract): """A contract that takes tez deposits and pays interest. The deposited funds cannot leave the contract, but the administrator can delegate them for baking. In more detail: - The administrator funds the contract with collateral. - The administrator publishes an offer: a rate (in basis points) and a duration (in days). - For each deposit the amount to be paid out and the due date are recorded. The corresponding amount of collateral is locked up. - At maturity the deposit plus interest can be withdrawn. """ def __init__(self, admin, initialRate, initialDuration): """Constructor Args: admin (sp.TAddress): admin of the contract. initialRate (sp.TNat): Basis points to compute the interest. initialDuration (sp.TNat): Number of days before a deposit can be withdrawn. """ self.init( admin=admin, collateral=sp.mutez(0), ledger={}, rate=initialRate, duration=initialDuration, ) # Admin-only entrypoints @sp.entrypoint(new_syntax = True) def delegate(self, public_key_hash): """Admin-only. Delegate the contract's balance to the admin. Args: public_key_hash (sp.TKeyHash): public key hash of the admin. """ assert sp.sender == self.data.admin assert sp.amount == sp.mutez(0) assert sp.sender == sp.to_address(sp.implicit_account(public_key_hash)) sp.set_delegate(sp.Some(public_key_hash)) @sp.entrypoint(new_syntax = True) def collateralize(self): """Admin-only. Provide tez as collateral for interest to be paid.""" assert sp.sender == self.data.admin self.data.collateral += sp.amount @sp.entrypoint(new_syntax = True) def uncollateralize(self, amount, receiver): """Admin-only. Withdraw collateral. Transfer `amount` mutez to admin if it doesn't exceed collateral. Args: amount (sp.TMutez): Amount to be removed from the collateral. """ assert sp.sender == self.data.admin # Explicitly fails for insufficient collateral. assert amount <= self.data.collateral, "insufficient collateral" self.data.collateral -= amount sp.send(receiver, amount) @sp.entrypoint(new_syntax = True) def set_offer(self, rate, duration): """Admin-only. Set the current offer: interest rate (in basis points) and duration. Args: rate (sp.TNat): Basis points to compute the interest. duration (sp.TNat): Number of days before a deposit can be withdrawn. """ assert sp.sender == self.data.admin assert sp.amount == sp.mutez(0) self.data.rate = rate self.data.duration = duration # Permissionless entrypoints @sp.entrypoint(new_syntax = True) def deposit(self, rate, duration): """Deposit tez. The current offer has to be repeated in the parameters. Args: rate (sp.TNat): Basis points to compute the interest. duration (sp.TNat): Number of days before a deposit can be withdrawn. """ assert self.data.rate >= rate assert self.data.duration <= duration assert not self.data.ledger.contains(sp.sender) # Compute interest to be paid. interest = sp.split_tokens(sp.amount, self.data.rate, 10_000) self.data.collateral -= interest # Record the payment to be made. self.data.ledger[sp.sender] = sp.record( amount=sp.amount + interest, due=sp.add_days(sp.now, self.data.duration), ) @sp.entrypoint(new_syntax = True) def withdraw(self, receiver): """Withdraw tez at maturity.""" assert sp.amount == sp.mutez(0) entry = self.data.ledger.get(sp.sender, error="NoDeposit") assert sp.now >= entry.due sp.send(receiver, entry.amount) del self.data.ledger[sp.sender]
Ancestors
- smartpy.Contract
Methods
def delegate(self, public_key_hash)
-
Entrypoint. Admin-only. Delegate the contract's balance to the admin.
Args
public_key_hash
:sp.TKeyHash
- public key hash of the admin.
Expand source code
@sp.entrypoint(new_syntax = True) def delegate(self, public_key_hash): """Admin-only. Delegate the contract's balance to the admin. Args: public_key_hash (sp.TKeyHash): public key hash of the admin. """ assert sp.sender == self.data.admin assert sp.amount == sp.mutez(0) assert sp.sender == sp.to_address(sp.implicit_account(public_key_hash)) sp.set_delegate(sp.Some(public_key_hash))
def collateralize(self)
-
Entrypoint. Admin-only. Provide tez as collateral for interest to be paid.
Expand source code
@sp.entrypoint(new_syntax = True) def collateralize(self): """Admin-only. Provide tez as collateral for interest to be paid.""" assert sp.sender == self.data.admin self.data.collateral += sp.amount
def uncollateralize(self, amount, receiver)
-
Entrypoint. Admin-only. Withdraw collateral.
Transfer
amount
mutez to admin if it doesn't exceed collateral.Args
amount
:sp.TMutez
- Amount to be removed from the collateral.
Expand source code
@sp.entrypoint(new_syntax = True) def uncollateralize(self, amount, receiver): """Admin-only. Withdraw collateral. Transfer `amount` mutez to admin if it doesn't exceed collateral. Args: amount (sp.TMutez): Amount to be removed from the collateral. """ assert sp.sender == self.data.admin # Explicitly fails for insufficient collateral. assert amount <= self.data.collateral, "insufficient collateral" self.data.collateral -= amount sp.send(receiver, amount)
def set_offer(self, rate, duration)
-
Entrypoint. Admin-only. Set the current offer: interest rate (in basis points) and duration.
Args
rate
:sp.TNat
- Basis points to compute the interest.
duration
:sp.TNat
- Number of days before a deposit can be withdrawn.
Expand source code
@sp.entrypoint(new_syntax = True) def set_offer(self, rate, duration): """Admin-only. Set the current offer: interest rate (in basis points) and duration. Args: rate (sp.TNat): Basis points to compute the interest. duration (sp.TNat): Number of days before a deposit can be withdrawn. """ assert sp.sender == self.data.admin assert sp.amount == sp.mutez(0) self.data.rate = rate self.data.duration = duration
def deposit(self, rate, duration)
-
Entrypoint. Deposit tez. The current offer has to be repeated in the parameters.
Args
rate
:sp.TNat
- Basis points to compute the interest.
duration
:sp.TNat
- Number of days before a deposit can be withdrawn.
Expand source code
@sp.entrypoint(new_syntax = True) def deposit(self, rate, duration): """Deposit tez. The current offer has to be repeated in the parameters. Args: rate (sp.TNat): Basis points to compute the interest. duration (sp.TNat): Number of days before a deposit can be withdrawn. """ assert self.data.rate >= rate assert self.data.duration <= duration assert not self.data.ledger.contains(sp.sender) # Compute interest to be paid. interest = sp.split_tokens(sp.amount, self.data.rate, 10_000) self.data.collateral -= interest # Record the payment to be made. self.data.ledger[sp.sender] = sp.record( amount=sp.amount + interest, due=sp.add_days(sp.now, self.data.duration), )
def withdraw(self, receiver)
-
Entrypoint. Withdraw tez at maturity.
Expand source code
@sp.entrypoint(new_syntax = True) def withdraw(self, receiver): """Withdraw tez at maturity.""" assert sp.amount == sp.mutez(0) entry = self.data.ledger.get(sp.sender, error="NoDeposit") assert sp.now >= entry.due sp.send(receiver, entry.amount) del self.data.ledger[sp.sender]
-