Contracts
Instantiating and originating contracts
- module.<Contract>(**args) → instance
- Instantiate the contract.
Call the
__init__
method of the contract's class.For example:
pythondef main(): class MyContract(sp.Contract): def __init__(self): pass class MyContract2(sp.Contract): def __init__(self, x): self.data.x = x pass class MyContract3(sp.Contract): def __init__(self, x, y): self.data.x = x self.data.y = y @sp.add_test() def test(): sc = sp.test_scenario(main, "A Test") c1 = main.MyContract() c2 = main.MyContract2(2) c3 = main.MyContract3(x=5, y=2)
@sp.add_test()
def test():
# Create a test scenario
sc = sp.test_scenario(main, "A Test")
# Instantiate a contract
c = main.MyContract()
# Originate the contract
sc += c
Instance methods
Calls to entrypoints
- c.<entrypoint>(**args)
Call an entrypoint with the given arguments.
If the entrypoint accepts multiple arguments they must be named or given as a record.
Generic context arguments: see context.
Specific context arguments are:
Parameter Type Description _amount sp.mutez The simulated amount sent. It populates sp.amount
._valid sp.bool Tells the interpreter if the transaction is expected to fail or not. True by default. _show sp.bool Show or hide the transaction. True by default. _exception any type The expected exception raised by the transaction. If present, valid must be False. Examples:
python# Call entrypoint c.my_entrypoint(12) c.my_entrypoint(a="a", b="b") # equivalent to c.my_entrypoint(sp.record(a="a", b="b")) # Call entrypoint with context attributes. c.my_entrypoint(13, _sender = None, # sp.address _source = None, # sp.address _chain_id = None, # sp.chain_id _level = None, # sp.nait _now = None, # sp.timestamp _voting_powers = None, # sp.map[sp.key_hash, sp.nat] _amount = None, # sp.mutez _valid = True, # sp.bool _show = True, # sp.bool _exception = None, # any ) # Test that a contract fails with a given exception c.my_entrypoint(x=5, _valid=False, _exception="Error: x < 12")
Other instance methods
- c.get_source()
Returns the source code of the contract. See metadata.
- c.get_offchain_views()
Returns the offchain views of the contract. See metadata.
- c.get_generated_michelson()
Returns the michelson code the contract. See metadata.
Before the origination
Some methods can only be called before the contract's origination to specify origination informations.
- c.set_initial_balance(balance: sp.tez)
Set the initial balance that will be used when originating the contract in the tests.
pythonc.set_initial_balance(sp.tez(20))
- c.data = x: any
- Replace a field in the contract's storage.
This is mostly useful to initialize the metadata big map. See metadata.
Exceptions
- sp.is_failing(expression)
Returns
True
when an expression (views, lambdas, ...) results in failure, andFalse
when the expression succeeds.
Content of exceptions
- sp.catch_exception(expression, [t]) → sp.option[t]
t
is optional, just usingsp.catch_exception(<expression>)
will be valid in most situations.This method is used to test failing conditions of expressions (views, lambdas, ...). It returns an sp.option of type
t
that will containsp.Some(<exception>)
when the expression fails orNone
if it succeeds.
Views
Views, both off-chain or on-chain, can now be called from test scenarios the same way as entrypoints. The example below shows how to do it.
Example
import smartpy as sp
@sp.module
def main():
class MyContract(sp.Contract):
def __init__(self, param):
self.data = param
@sp.offchain_view()
def state(self, param):
assert param < 5, "This is false: param > 5"
return self.data * param
@sp.add_test()
def test():
scenario = sp.test_scenario("Minimal", main)
c1 = main.MyContract(1)
scenario += c1
""" Test views """
# Display the offchain call result
scenario.show(c1.state(1))
# Assert the view result
scenario.verify(c1.state(2) == 2)
# Assert call failures
scenario.verify(sp.is_failing(c1.state(6))); # Expected to fail
scenario.verify(~ sp.is_failing(c1.state(1))); # Not expected to fail
# Assert exception result
# catch_exception returns an option:
# - None if the call succeeds
# - sp.Some(<exception>) if the call fails
e = sp.catch_exception(c1.state(7), t = sp.string)
scenario.verify(e == sp.Some("This is false: param > 5"))
Context
Context arguments are:
Parameter | Type | Accessor | Description |
---|---|---|---|
_sender | sp.address or sp.test_account | sp.sender | The simulated sender of the computation. Specific to computation. |
_source | sp.address or sp.test_account | sp.source | The simulated source of the computation. Specific to computation. |
_chain_id | sp.chain_id | sp.chain_id | The simulated chain_id. Preserved until changed. |
_level | sp.nat | sp.level | The simulated block level. Preserved until changed. |
_now | sp.timestamp | sp.now | The simulated block timestamp. Preserved until changed. |
_voting_powers | sp.map[sp.key_hash, sp.nat] | sp.total_voting_power , sp.voting_power | The simulated voting powers for the test. Preserved until changed. |
Data associated with contracts
When a variable c1
represents a contract in a scenario, we can access some associated data:
c1.data
: Contract's storage.c1.balance
: Contract's balance.c1.baker
: Contract's pptional delegated baker.c1.address
: Contract's address within the scenario.Details
In storage or similar circumstances, deployed contracts get addresses of the form:
KT1TezoooozzSmartPyzzSTATiCzzzwwBFA1
KT1Tezooo1zzSmartPyzzSTATiCzzzyfC8eF
KT1Tezooo2zzSmartPyzzSTATiCzzzwqqQ4H
KT1Tezooo3zzSmartPyzzSTATiCzzzseJjWC
KT1Tezooo4zzSmartPyzzSTATiCzzzyPVdv3
KT1Tezooo5zzSmartPyzzSTATiCzzzz48Z4p
KT1Tezooo6zzSmartPyzzSTATiCzzztY1196
KT1Tezooo7zzSmartPyzzSTATiCzzzvTbG1z
KT1Tezooo8zzSmartPyzzSTATiCzzzzp29d1
KT1Tezooo9zzSmartPyzzSTATiCzzztdBMLX
KT1Tezoo1ozzSmartPyzzSTATiCzzzw8CmuY
- ...
c1.typed
Retrieve its testing typed contract value.
To access entrypoints, one can use field notation:
c1.typed.my_entrypoint
: to access typed entrypoint my_entrypoint of contractc1
.