Skip to content
This repository has been archived by the owner on Aug 21, 2024. It is now read-only.

Merge dev into main for the next release #264

Merged
merged 30 commits into from
Jan 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1dffc11
Update Examples, SDK and CLI v0.2.1
leighmcculloch Nov 11, 2022
c9928a2
Pin docker image
leighmcculloch Nov 11, 2022
d435edf
Merge branch 'main' into dev
leighmcculloch Dec 2, 2022
a2c8c1e
Add release notes (#234)
leighmcculloch Dec 2, 2022
88d2c4a
Update version of SDK (#236)
leighmcculloch Dec 3, 2022
52c7ba4
Remove BigInt and replace with i128 (#237)
leighmcculloch Dec 3, 2022
10cd25f
Fix soroban_sdk::i128 -> i128 (#238)
leighmcculloch Dec 3, 2022
702f395
Updated the deployer example. (#230)
dmkozh Dec 6, 2022
c4c8a04
Update soroban-cli to v0.3.1 (#239)
leighmcculloch Dec 6, 2022
25f3061
Update versions of software (#240)
leighmcculloch Dec 6, 2022
029ff79
Remove "Preview" from releases page title
leighmcculloch Dec 6, 2022
963705f
Update chanelogs
leighmcculloch Dec 6, 2022
d490ab6
Update soroban-rpc version
leighmcculloch Dec 6, 2022
2b88bf1
Update Friendbot version
leighmcculloch Dec 6, 2022
13a0c9f
updated quickstart image sha (#241)
sreuland Dec 6, 2022
114e00d
Add changelog notes about XDR
leighmcculloch Dec 6, 2022
170c0ef
Add changelog notes about env
leighmcculloch Dec 6, 2022
4829f83
Add other changelogs
leighmcculloch Dec 6, 2022
ffc2114
Add contributors
leighmcculloch Dec 6, 2022
ee1edf1
Merge branch 'main' into dev-main
sisuresh Jan 4, 2023
5dcd53b
Merge pull request #255 from sisuresh/dev-main
sisuresh Jan 4, 2023
3ab80f0
Token interface and single balance update
sisuresh Jan 5, 2023
647137a
Add deployment section for the SAC
sisuresh Jan 5, 2023
45f0ed4
Merge pull request #257 from sisuresh/update-token
sisuresh Jan 5, 2023
2f60472
Token clarifications
sisuresh Jan 6, 2023
3e434c1
Merge pull request #260 from sisuresh/token1
sisuresh Jan 6, 2023
4a5a17d
Update outdated token terminology
sisuresh Jan 6, 2023
b3b0774
Merge pull request #261 from sisuresh/fix-token-terminology
sisuresh Jan 6, 2023
d737360
Merge branch 'main' into update-dev
sisuresh Jan 7, 2023
d303585
Merge pull request #263 from sisuresh/update-dev
sisuresh Jan 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 186 additions & 0 deletions docs/built-in-contracts/stellar-asset-contract.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
---
sidebar_position: 1
title: Stellar Asset Contract
---

# Stellar Asset Contract

The Stellar Asset Contract is an implementation of [CAP-46-6 Smart Contract Standardized Asset].

[CAP-46-6 Smart Contract Standardized Asset]: https://stellar.org/protocol/cap-46-06

:::caution
The Stellar Asset Contract is in early development, has not been audited, and is
intended for use in development and testing only at this stage. Report issues
[here](https://github.com/stellar/soroban-token-contract/issues/new/choose).
:::

## Overview

Stellar has numerous assets on its classic network, and being able to use them
in Soroban would give users much more flexibility with how they can use their
assets. For this reason, we introduced the Stellar Asset Contract, or SAC for
short, which will allow users to use their Stellar account and trustline
balances in Soroban.

The SAC implements the [token interface](../common-interfaces/token.mdx), which is
similar to the widely used ERC-20 token standard. This should make it easier for
existing smart contract developers to get started on Stellar.

## Deployment

For every 'classic' asset exactly one respective Stellar Asset Contract can be
deployed. It can be deployed using the `InvokeHostFunctionOp` with
`HOST_FUNCTION_TYPE_CREATE_CONTRACT` and `CONTRACT_ID_FROM_ASSET` specified
[here](../tutorials/invoking-contracts-with-transactions). The resulting token
will have a deterministic identifier, which will be the sha256 hash of
`HashIDPreimage::ENVELOPE_TYPE_CONTRACT_ID_FROM_ASSET` xdr specified
[here](https://github.com/stellar/stellar-xdr/blob/026c9cd074bdb28ddde8ee52f2a4502d9e518a09/Stellar-transaction.x#L637).

## Interacting with classic Stellar assets

The Stellar Asset Contract is the only way to interact with 'classic' Stellar assets in
Soroban. 'Classic' assets include native Stellar token (lumens) and all the
existing trustlines. The issuer of the asset will be the
administrator of the deployed contract. Because the the Native Stellar token
doesn't have an issuer, it will not have an administrator either. It also cannot
be burned.

After the contract has been deployed, users can use their classic account or
trustline balance. There are some differences depending on if you are using a
classic account identifier vs a non-account identifier like a contract.

- Using `Identifier::Account`
- The balance must exist in a trustline (or an account for the native balance).
This means the contract will not store the balance in ContractData. If the
trustline or account is missing, any function that tries to interact with
that balance will fail.
- Classic trustline semantics will be followed.
- Transfers will only succeed if the corresponding
trustline(s) have the `AUTHORIZED_FLAG` set.
- A trustline balance can only be clawed back using the `clawback`
contract function if the trustline has `TRUSTLINE_CLAWBACK_ENABLED_FLAG`
set.
- The admin can only deauthorize a trustline if the issuer of the asset has
`AUTH_REVOCABLE` set. The deauthorization will fail if the issuer is
missing. Note that when a trustline is deauthorized from Soroban,
`AUTHORIZED_FLAG` is cleared and `AUTHORIZED_TO_MAINTAIN_LIABILITIES_FLAG` is
set to avoid having to pull offers and redeeming pool shares.
- Transfers to the issuer account will burn the token, while transfers from
the issuer account will mint.
- Trustline balances are stored in a 64-bit signed integer even though the
interface accepts 128-bit signed integers. Any operation that attempts to
send or recieve an amount more than the maximum amount that can be
represented by a 64-bit signed integer will fail.
- Using `Identifier::Ed25519` or `Identifier::Contract`
- The balance and authorization state will be stored in ContractData, as
opposed to a trustline.
- `AUTH_REVOCABLE` is not required to be set on the issuer to deauthorize a balance.
- These balances are stored in a 128-bit signed integer.

## Authorization semantics

See the [advanced auth example](../examples/auth-advanced) for an overview of
authorization.

### SAC operations

The token contract contains three kinds of operations

- getters, such as `balance`, which do not change the state of the contract
- unprivileged mutators, such as `incr_allow` and `xfer`, which change the state of
the contract but do not require special privileges
- privileged mutators, such as `clawback` and `set_admin`, which change the state of
the contract but require special privileges

Getters require no authorization because they do not change the state of the
contract and all contract data is public. For example, `balance` simply returns
the balance of the specified identity without changing it.

Unprivileged mutators require authorization from some identity. The identity
which must provide authorization will vary depending on the unprivileged
mutator. For example, a "grantor" can use `incr_allow` to allow a "spender" to spend
the grantor's money up to some limit. So for `incr_allow`, the grantor must provide
authorization. Similarly, a "sender" can use `xfer` to send money to a
"recipient". So for `xfer`, the sender must provide authorization.

Priviliged mutators require authorization from a specific privileged identity,
known as the "administrator". For example, only the administrator can `mint` more
of the asset. Similarly, only the administrator can appoint a new administrator.

### Replay prevention

The token contract provides replay prevention by using a [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce).
The messages that are signed to provide authorization contain a nonce. The
contract also stores a nonce per identity. When checking signatures, the
contract loads the nonce for the relevant identity. When an operation succeeds,
the nonce stored in the contract is incremented. This makes it impossible to
reuse a signature.

The current nonce for an identity can be retrieved using the `nonce` contract
function.

### Example: Invoker auth

The easiest way to use the built-in token with classic accounts is to just use
the [invoker](../examples/auth.mdx#invoker) auth. In this way there won't be
a need to sign the contract payload, so the contract call would look like this:

```rust
// `with_source_account` is a testing utility, but the contract call arguments
// would be the same for the real contract call too.
token.with_source_account(&token_admin_id).mint(
// No signature needed, just a flag that invoker auth should be used, i.e.
// `token_admin_id` in this case.
&Signature::Invoker,
// Nonce is always 0 for invokers.
&0,
&user_id,
&1000,
);
```

See a more complete example that uses invoker auth in the tests
[here](https://github.com/stellar/soroban-examples/blob/51a95262caba3f8ac466fa8bbc07004ad297ae13/timelock/src/test.rs#L60).

### Example: Signing payloads

The payload signature semantics is the same as for regular contracts using
[advanced auth](../examples/auth-advanced.mdx). The following snippet shows how
should the signature payload look like:

```rust
let nonce = token.nonce(&token_admin_id);
// This is the test call, but the contract call arguments and signature payload
// would be the same for the real contract call too.
let sig = soroban_auth::testutils::ed25519::sign(
&env,
// Signer has the private key of the admin.
&token_admin_signer,
// Identifier of the token contract.
&token_contract_id,
// Name of the contract function we call.
symbol!("mint"),
// Arguments of the contract function call.
// Notice that instead of the signature (first `mint` argument), public key
// is used as the first argument here.
(&token_admin_id, &nonce, &user_id, &1000),
);
// Call the contract with signature we computed above.
token.mint(
&sig,
&nonce,
&user_id,
&1000,
);
```

## Contract Interface

This interface can be found in the [SDK](https://github.com/stellar/rs-soroban-sdk/blob/main/soroban-token-spec/src/lib.rs). It
extends the common [token interface](../common-interfaces/token.mdx).

## Interacting with the token contract in tests

See [interacting with contracts in tests](../learn/interacting-with-contracts#interacting-with-contracts-in-tests)
for more general information on this topic.
Loading