Skip to main content

Set a custom admin account for a Stellar Asset Contract (SAC)

The Stellar Asset Contract (SAC) 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.

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.

Example

The following example will create a new Stellar asset, STAR:GCS5NEHKJALCSVJAKIORXXVS554QQV5FNDLBK33CCAH6UIRYPXYZFC34.

Enable the built-in SAC contract

First, we'll enable the SAC contract using the Stellar CLI:

stellar contract asset deploy \
--source starIssuer --network testnet \
--asset STAR:GCS5NEHKJALCSVJAKIORXXVS554QQV5FNDLBK33CCAH6UIRYPXYZFC34
# CBVYF2KJ72BRPLVPCUL3PGWDO5RK2XP4AJDHKX7GDDBJW42L2C6VT3SF

This gives us the SAC address of CBVYF2KJ72BRPLVPCUL3PGWDO5RK2XP4AJDHKX7GDDBJW42L2C6VT3SF.

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.

Check the initial Admin address

Now that we have the SAC deployed to the network, we can invoke the admin function to find out what its current Admin address is:

stellar contract invoke \
--source starIssuer --network testnet \
--id CBVYF2KJ72BRPLVPCUL3PGWDO5RK2XP4AJDHKX7GDDBJW42L2C6VT3SF \
-- \
admin
# GCS5NEHKJALCSVJAKIORXXVS554QQV5FNDLBK33CCAH6UIRYPXYZFC34

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.

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.

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:

#[contractimpl]
impl Contract {
pub fn __constructor(env: Env, sac_address: Address) {
env.storage().instance().set(&symbol_short!("SAC_ADDR"), &sac_address);
}

pub fn star_mint(env: Env, to: Address, amount: i128) {
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);
}
}

This contract gets deployed, and the address might be (for example) CCOQXM7XPEUZKAFEHBXBFS3VJVWJBOU6JK5B7B3Z6VUDX3OCESD3P6TI. We can now set the SAC Admin address to this contract:

stellar contract invoke \
--source newStarAdmin --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:

stellar contract invoke \
--source starIssuer --network testnet \
--id CBVYF2KJ72BRPLVPCUL3PGWDO5RK2XP4AJDHKX7GDDBJW42L2C6VT3SF \
-- \
admin
# 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.)

stellar contract invoke \
--source randomStarHolder --network testnet \
--id CCOQXM7XPEUZKAFEHBXBFS3VJVWJBOU6JK5B7B3Z6VUDX3OCESD3P6TI \
-- \
star_mint --to randomStarHolder --amount 1000000000

Now, this randomStarHolder account will have a balance of 100 STAR, and the token minting was authorized by the minter 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.

In the wild

A fun example of a project utilizing a custom administrator address on a SAC can be found with the KALE Project. The KALE issuer is GBDVX4VELCDSQ54KQJYTNHXAHFLBCA77ZY2USQBM4CSHTTV7DME7KALE, but you can see the Admin address for the SAC is set to another contract:

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

This CDL7... contract is the "homestead" contract created to facilitate the minting/burning/mining of the KALE asset.