Skip to content
On this page

2. Push bonds โ€‹

Bonds consist of assets that a player posts into a channel. They can be wrapped XTZ, other fungible tokens like tzBTC, or non-fungible tokens.

Anyone can post bonds for any player in any channel. However, only the owner can withdraw bonds, under the conditions described in withdraw bonds.

The platform is associated with a ledger contract. This is the one you interact with when you want to push bonds. The tokens are configured by the admin (see tokens).

In general, the token 0 corresponds to wrapped XTZ ("WXTZ"). For every WXTZ you want to post as bond you have to transfer one XTZ.

Push internal token โ€‹

Internal tokens are tokens that are managed by the ledger (like wrapped XTZ).

  1. Mint the token (if needed)
  2. Call push_bonds on the ledger.

Push external tokens โ€‹

External tokens are tokens that are managed by another FA contract.

Depending on the case you have 2 solutions.

(a) Compatible with transfer_and_call (more secure) โ€‹

This call has to be done on the FA2 contract that manage the external tokens.

python
@sp.entrypoint
def transfer_and_call(self, from_, txs):
    sp.set_type(from_, sp.TAddress)  # Your address
    # Your transaction
    sp.set_type(txs,
        sp.TRecord(
            # Platform's address
            to=sp.TAddress,
            # <ledger_address>%on_received_bonds>
            callback=sp.TAddress,
            # sp.pack(sp.record(channel_id=<channel_id>,
            # player_addr=<your_address>, platform=<platform_address>))
            data=sp.TBytes,
            # Amount of tokens you want to bond.
            amount=sp.TNat,
            # Id of the tokens you want to bond.
            token_id=sp.TNat,
        )
    )
python
types = sp.io.import_template("state_channel_games/types.py").Types()

    my_address     = sp.address('tz1_MY_ADDRESS')
    ledger_address = sp.to_address("KT1_ADDRESS_OF_THE_LEDGER")
    callback       = sp.to_address(
        sp.contract(
            types.t_callback,
            ledger_address,
            entrypoint = "on_received_bonds"
        ).open_some()
    )

    fa2_contract.transfer_and_call([sp.record(
        from_ = my_address,
        txs = [
            sp.record(
                to_      = ledger_address,
                callback = callback,
                data     = sp.pack(sp.record(channel_id=channel_id, player_addr=my_address)),
                amount   = sp.nat(1337),
                token_id = sp.nat(42),
            )
    ])])

See channel id calculation.

(b) With operator (legacy) โ€‹

Set the ledger as your operator by calling update_operators on the FA2 contract.

Call push_bonds entrypoint on the ledger.

Push_bonds entrypoint โ€‹

python
@sp.entrypoint
def push_bonds(self, params):
    sp.set_type(params,
        sp.TRecord(
            to=sp.TAddress,  # Platform's address
            channel_id=sp.TBytes,  # Channel's id
            player_addr=sp.TNat,  # Receiver of the bonds
            token_id=sp.TNat,  # Map of token and amount
        )
    )
python
# ... (new channel)

    platform.push_bonds(
        platform    = platform.address,
        channel_id  = channel_id,
        player_addr = player1.address,
        tokens      = {0: 10_000_000}
    ).run(sender = player1.address)

See channel id calculation.

Withdraw bonds โ€‹

See withdraw bonds