Skip to content

Commit

Permalink
Merge branch 'main' into add-migrate-horizon-rpc-doc
Browse files Browse the repository at this point in the history
  • Loading branch information
leighmcculloch committed Feb 4, 2025
2 parents fa21fd8 + 4d1d52c commit 7ee0076
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 58 deletions.
104 changes: 50 additions & 54 deletions docs/build/guides/tokens/custom-sac-admin.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,44 @@ hide_table_of_contents: true
description: Set a custom administrator account on a deployed SAC
---

The [Stellar Asset Contract (SAC)](../../../tokens/stellar-asset-contract.mdx) includes functionality to set a custom administration account on the contract itself. This can be seen as a security precaution, similar to locking an asset's issuer account after creating the total supply of tokens. It should also be noted that an asset's issuer account can have a distinct set of signatures and weights, and these are unrelated to the SAC admin address.
The [Stellar Asset Contract (SAC)](../../../tokens/stellar-asset-contract.mdx) includes functionality to set a custom administration account on the contract itself. This can allow for flexible arrangements of asset administration, which can be configured to suit many distinct use-cases.

For example, you can set a custom SAC admin, and then lock the issuer account, allowing for token administration to be _exclusively_ performed through the SAC contract. Or, you could set a custom SAC admin and still keep the issuer account unlocked, allowing for a hybrid approach to token administration.

:::info

It should be understood that an asset's issuer account can have a distinct set of signatures and weights, and these are unrelated to the SAC admin address.

:::

## Considerations

To effectively utilize the SAC admin functionality, you should be aware of a few things first:

- When a SAC is initially enabled for an issued asset, the `Admin` address on the contract defaults to the issuer account.
- A SAC `Admin` address can be either a regular Stellar account (`G...`), or it can be a smart contract (`C...`) address. This opens up the possibility of programmatically minting and taking other administrative actions for an asset by way of a smart contract invocation.
- Changing a SAC `Admin` address (initially) requires authorization from the asset's issuer account. After the `Admin` address has been set the first time, subsequent changes will require authorization from the _current_ `Admin` address.
- If an asset's issuer account is locked while the SAC `Admin` address has not been changed, it will _never_ be possible to change the SAC `Admin` address.
- If an asset's issuer account is locked after the SAC `Admin` address has been changed, tokens will still be mint-able from the SAC as long as it's authorized by the _current_ `Admin` address.
- A SAC `Admin` address can be either a regular Stellar account (`G...`), or it can be a smart contract (`C...`) address. The use-cases requiring a smart contract to act as a SAC `Admin` tend to be more common. This opens up the possibility of programmatically minting and taking other administrative actions for an asset by way of a smart contract invocation.
- Changing a SAC `Admin` address requires authorization from the asset's _current_ `Admin` address, which will be the issuer account the first time the action is performed.

Depending on the use-case, it can be beneficial for asset issuers to mint an entire supply of tokens up front, and then lock down the issuer account. This would keep the total token supply capped forever. You can learn more about this practice on the [asset design considerations](../../../tokens/control-asset-access.mdx#limiting-the-supply-of-an-asset) page. However, since the issuer account and a SAC `Admin` address act independently, there are some interesting points to make that might seem counterintuitive at first glance.

- If an asset's issuer account is locked while the SAC `Admin` address has not been changed, it will _never_ be possible to change the SAC `Admin` address. This is because the issuer account can no longer authorize the first `set_admin` invocation.
- If an asset's issuer account is locked after the SAC `Admin` address has been changed, tokens will still be mint-able and/or clawback-able (if enabled) from the SAC as long as it's authorized by the _current_ `Admin` address.

:::danger

When changing a SAC `Admin` address, the new admin address provided is not validated at that time. This means you can lock down administration from the SAC **forever**. Consider your choice of SAC `Admin` address carefully and thoroughly.

:::

## Example

The following example will create a new Stellar asset, `STAR:GCS5NEHKJALCSVJAKIORXXVS554QQV5FNDLBK33CCAH6UIRYPXYZFC34`.
The following example will create a new Stellar asset, `STAR:GCS5NEHKJALCSVJAKIORXXVS554QQV5FNDLBK33CCAH6UIRYPXYZFC34`. Then, we will create a simple contract to regulate a hypothetical airdrop for the token. This contract will be configured as the SAC `Admin` address for the `STAR` asset, and it will be able to perform any administrative functions we want.

:::note

We will not demonstrate setting a new `G...` account as a SAC admin in this guide. Any use-case that needs asset administration delegated to another `G...` account will likely be better served by taking advantage of the existing [multisig capabilities](../../../learn/encyclopedia/security/signatures-multisig.mdx) of Stellar accounts.

:::

### Enable the built-in SAC contract

Expand All @@ -35,7 +58,7 @@ This gives us the SAC address of `CBVYF2KJ72BRPLVPCUL3PGWDO5RK2XP4AJDHKX7GDDBJW4

:::note

We're using the asset's issuer account here to enable the SAC on the Testnet network, but this could be done using _any_ account.
We're using the asset's issuer account here to enable the SAC on the Testnet network, but this action can be performed using _any_ account.

:::

Expand All @@ -54,44 +77,9 @@ stellar contract invoke \

Unsurprisingly, it's set to the issuer's `GCS5...` account. Let's change that.

### Set the `Admin` address to a new `G...` account

We can set this `Admin` address to any account that we want. Including an account that's un-funded on the network. As long as you're able to provide a valid signature for the account, which would take into consideration any multisig or signature weights that have been set up, you can use this event for future administration of the asset from within the contract.

:::info

Ensure that whatever account you're using for this `Admin` address has a way to sign transactions. That would mean you have a secret key or seed phrase for it.

:::

```sh
stellar contract invoke \
--source starIssuer --network testnet \
--id CBVYF2KJ72BRPLVPCUL3PGWDO5RK2XP4AJDHKX7GDDBJW42L2C6VT3SF \
-- \
set_admin --new_admin GBL3IQ6KA3I7CS7C5ABTCU7CJJA7X76SBZKTTQVJ4APW5646DXEIQKHB
```

Now, invoking the `admin` function of the contract will return this new `GBL3...` address, rather than the original issuer of the asset.

```shell
stellar contract invoke \
--source starIssuer --network testnet \
--id CBVYF2KJ72BRPLVPCUL3PGWDO5RK2XP4AJDHKX7GDDBJW42L2C6VT3SF \
-- \
admin
# GBL3IQ6KA3I7CS7C5ABTCU7CJJA7X76SBZKTTQVJ4APW5646DXEIQKHB
```

:::info

If you examine the asset's `GCS5...` issuer account, you won't see anything different. The signers/weights will be exactly the same. The only place this change is seen is _within_ the SAC for this asset.

:::

### Set the `Admin` address to some contract `C...` address

For this part of the example, we'll use a very simple "minter" contract as the `Admin` address. It has a very simple implementation, and only one main function, `start_mint`:
For this part of the example, we'll use a simple "airdrop" contract as the `Admin` address. It has a very simple implementation, and only one main function, `claim_airdrop`. Whenever someone invokes that function, 12.3456789 `STAR` will be minted to their account.

```rust
#[contractimpl]
Expand All @@ -100,10 +88,18 @@ impl Contract {
env.storage().instance().set(&symbol_short!("SAC_ADDR"), &sac_address);
}

pub fn star_mint(env: Env, to: Address, amount: i128) {
pub fn claim_airdrop(env: Env, receiver: Address) {
if env.storage().persistent().has(&receiver) {
panic!("receiver has already claimed")
}

receiver.require_auth();
let amount: i128 = 123456789;
env.storage().persistent().set(&receiver, &amount);

let sac_address: Address = env.storage().instance().get(&symbol_short!("SAC_ADDR")).unwrap();
let token_client = token::StellarAssetClient::new(&env, &sac_address);
token_client.mint(&to, &amount);
token_client.mint(&receiver, &amount);
}
}
```
Expand All @@ -112,13 +108,13 @@ This contract gets deployed, and the address might be (for example) `CCOQXM7XPEU

```sh
stellar contract invoke \
--source newStarAdmin --network testnet \
--source starIssuer --network testnet \
--id CBVYF2KJ72BRPLVPCUL3PGWDO5RK2XP4AJDHKX7GDDBJW42L2C6VT3SF \
-- \
set_admin --new_admin CCOQXM7XPEUZKAFEHBXBFS3VJVWJBOU6JK5B7B3Z6VUDX3OCESD3P6TI
```

Double-checking our work with the `admin` function of the SAC, we'll see that our minter contract is now the `Admin` address:
Double-checking our work with the `admin` function of the SAC, we'll see that our airdrop contract is now the `Admin` address:

```shell
stellar contract invoke \
Expand All @@ -129,33 +125,33 @@ stellar contract invoke \
# CCOQXM7XPEUZKAFEHBXBFS3VJVWJBOU6JK5B7B3Z6VUDX3OCESD3P6TI
```

Now, since the minter contract is the administrator of the SAC, we can invoke its `star_mint` function from any account we like. (Reminder: if you're using a `G...` address with the `mint` function of a SAC, it will need a trustline created for the asset beforehand.)
Now, since the airdrop contract is the administrator of the SAC, we can invoke its `claim_airdrop` function from any account we like. (Reminder: if you're using a `G...` address as a destination for the `mint` function of a SAC, it will need a trustline created for the asset beforehand.)

```sh
stellar contract invoke \
--source randomStarHolder --network testnet \
--id CCOQXM7XPEUZKAFEHBXBFS3VJVWJBOU6JK5B7B3Z6VUDX3OCESD3P6TI \
-- \
star_mint --to randomStarHolder --amount 1000000000
claim_airdrop --receiver randomStarHolder
```

Now, this `randomStarHolder` account will have a balance of 100 STAR, and the token minting was authorized by the minter contract itself.
Now, this `randomStarHolder` account will have a balance of 12.3456789 `STAR`, and the token minting was executed by the airdrop contract itself.

### Making a `payment` operation from the issuer account

Since we haven't locked down the signer(s) of our issuer account, it's still entirely possible for the `GCS5...` issuer account to create and submit to the network any `payment` operations it wants. This means tokens could still be minted with a `payment` operation, or burned with a `clawback` operation, or trustline flags modified, all using the original asset issuer's account. The `Admin` address of the SAC and the signing permissions of the account operate and function independently of one another.
Since we haven't locked down the signer(s) of our issuer account, it's still entirely possible for the `GCS5...` issuer account to create and submit to the network any `payment` operations it wants. This means tokens could still be minted with a `payment` operation, or burned with a `clawback` operation, or trustline flags modified, etc. all using the original asset issuer's account. The `Admin` address of the SAC and the signing permissions of the issuer account operate and function independently of one another.

## In the wild

A fun example of a project utilizing a custom administrator address on a SAC can be found with the [KALE Project](https://github.com/kalepail/KALE-sc). The KALE issuer is `GBDVX4VELCDSQ54KQJYTNHXAHFLBCA77ZY2USQBM4CSHTTV7DME7KALE`, but you can see the `Admin` address for the SAC is set to another contract:
A fun example of a project utilizing a custom administrator address on a SAC can be found with the [`KALE` Project](https://github.com/kalepail/KALE-sc). The KALE issuer is `GBDVX4VELCDSQ54KQJYTNHXAHFLBCA77ZY2USQBM4CSHTTV7DME7KALE`, but you can see the `Admin` address for the SAC is set to another contract:

```sh
stellar contract invoke \
--source S... --network mainnet \
--source S...ECRETKEY --network mainnet \
--id CB23WRDQWGSP6YPMY4UV5C4OW5CBTXKYN3XEATG7KJEZCXMJBYEHOUOV \
-- \
admin
# CDL74RF5BLYR2YBLCCI7F5FB6TPSCLKEJUBSD2RSVWZ4YHF3VMFAIGWA
```

This [`CDL7...` contract](https://stellar.expert/explorer/public/contract/CDL74RF5BLYR2YBLCCI7F5FB6TPSCLKEJUBSD2RSVWZ4YHF3VMFAIGWA) is the "homestead" contract created to facilitate the minting/burning/mining of the KALE asset.
This [`CDL7...` contract](https://stellar.expert/explorer/public/contract/CDL74RF5BLYR2YBLCCI7F5FB6TPSCLKEJUBSD2RSVWZ4YHF3VMFAIGWA) is the "homestead" contract created to facilitate the minting/burning/mining of the `KALE` asset.
1 change: 1 addition & 0 deletions docs/data/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ This section will walk you through the differences between the various platforms
| Smart Contracts |||||
| API |||||
| Transaction Submission |||||
| Transaction Simulation |||||
| Curated and Parsed Data |||||
| Ad Hoc Data Analysis |||||

Expand Down
6 changes: 4 additions & 2 deletions docs/learn/encyclopedia/data-format/xdr.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: XDR

import { CodeExample } from "@site/src/components/CodeExample";

Stellar stores and communicates ledger data, transactions, results, history, and messages in a binary format called External Data Representation (XDR). XDR is optimized for network performance but not human readable. Horizon and the Stellar SDKs convert XDRs into friendlier formats.
Stellar stores and communicates ledger data, transactions, results, history, and messages in a binary format called External Data Representation (XDR). XDR is defined in [RFC4506]. XDR is optimized for network performance but not human readable. Horizon and the Stellar SDKs convert XDRs into friendlier formats.

## .X files

Expand Down Expand Up @@ -34,7 +34,7 @@ The defined schema (linked above) is **not** backwards compatible between a give

## More About XDR

XDR is specified in [RFC 4506](http://tools.ietf.org/html/rfc4506.html) and is similar to tools like Protocol Buffers or Thrift. XDR provides a few important features:
XDR is similar to tools like Protocol Buffers or Thrift. XDR provides a few important features:

- It is very compact, so it can be transmitted quickly and stored with minimal disk space.
- Data encoded in XDR is reliably and predictably stored. Fields are always in the same order, which makes cryptographically signing and verifying XDR messages simple.
Expand Down Expand Up @@ -235,3 +235,5 @@ There are many cases in which the different union arms share structure, and `.va
This overview should give you a strong baseline on understanding how to inspect XDR in your respective SDK to dig into the fields that you're interested in. Specifics will, of course, be language dependent, but if you start at the foundation--that being the raw [.x files](#.x-files) themselves--you will get an understanding of the structure itself and should be able to access that same structure directly in your language of choice, as we've outlined here.

{/* TODO: Room to expand much more: Tools -> CLI Visualization, JSON Visualization, Stellar Lab */}

[RFC 4506]: http://tools.ietf.org/html/rfc4506.html
26 changes: 24 additions & 2 deletions docs/tools/sdks/library.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ title: "SDK Library"
sidebar_position: 10
---

Interact with the Stellar network using the SDK in your preferred language. The JavaScript, Go, and Rust SDKs are maintained by SDF and the rest are maintained by dedicated community developers. All SDKs are open-source; file a GitHub issue or pull request in the specific SDK repository if you have questions or suggestions.
The list of SDKs is separated into two categories: Contract SDKs (used to build and interact with smart contracts on the network) and Client & XDR SDKs (used by applications to interact with the network).

Each SDK has its own source code and documentation. Learn how to use a specific SDK by referring to the documentation- most docs offer practical examples that demonstrate how to construct and submit transactions and interact with Horizon endpoints.
The JavaScript, Go, and Rust SDKs are maintained by SDF and the rest are maintained by dedicated community developers. All SDKs are open-source; file a GitHub issue or pull request in the specific SDK repository if you have questions or suggestions.

Each SDK has its own source code and documentation. Learn how to use a specific SDK by referring to the documentation.

## Contract SDKs

### Soroban Rust SDK

Expand Down Expand Up @@ -35,6 +39,8 @@ The `as-soroban-sdk` is an open source SDK that supports writing programs for th

The AssemblyScript Soroban SDK is maintained by dedicated community developer, Soneso. Report issues and share feedback [here](https://github.com/Soneso/as-soroban-sdk/issues/new).

## Client & XDR SDKs

### JavaScript SDK

[JavaScript SDK](https://github.com/stellar/js-stellar-sdk) | [Docs](https://stellar.github.io/js-stellar-sdk/) | [NPM](https://www.npmjs.com/package/@stellar/stellar-sdk)
Expand All @@ -59,6 +65,22 @@ It provides:
- A networking layer API for Horizon endpoints.
- Facilities for building and signing transactions, for communicating with a Stellar Horizon instance, and for submitting transactions or querying network history.

### Rust

Functionality for interacting with Stellar data can be found in the following Rust crates:

- `stellar-xdr`[Code](https://github.com/stellar/rs-stellar-xdr) | [Docs](https://docs.rs/stellar-xdr)

Provides [XDR] encode/decode and the reference implementation of [XDR-JSON].

- `stellar-strkey`[Code](https://github.com/stellar/rs-stellar-strkey) | [Docs](https://docs.rs/stellar-strkey)

Provides Stellar Strkey (Address) [SEP-23] encoding/decoding.

[XDR]: ../../learn/encyclopedia/data-format/xdr
[XDR-JSON]: ../../learn/encyclopedia/data-format/xdr#json-and-xdr-conversion-schema
[SEP-23]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0023.md

### iOS SDK

[iOS SDK](https://github.com/Soneso/stellar-ios-mac-sdk) | [Docs](https://github.com/Soneso/stellar-ios-mac-sdk/tree/master/docs) | [Smart Contract Docs](https://github.com/Soneso/stellar-ios-mac-sdk/blob/master/soroban.md)
Expand Down

0 comments on commit 7ee0076

Please sign in to comment.