Skip to content

stellarcarbon/sorocarbon

Repository files navigation

SOROCARBON

Home of Stellarcarbon's Soroban smart contracts

Project Structure

This repository uses the recommended structure for a Soroban project:

.
├── contracts
│   └── sink_carbon
│       ├── src
│       │   ├── tests/
│       │   ├── contract.rs
│       │   ├── errors.rs
│       │   ├── lib.rs
│       │   ├── storage_types.rs
│       │   └── utils.rs
│       ├── Cargo.toml
│       └── README.md
├── Cargo.toml
└── README.md

Soroban Setup

If you haven't worked on Soroban contracts before, you'll need to set up a local development environment. Start with the excellent Soroban documentation. We've reused some snippets here, under the Apache-2.0 license.

Testing

Run cargo test to run the test suite.

cargo test

Or, to display backtraces when there are failures:

RUST_BACKTRACE=1 cargo test

You should see output similar to:

running 16 tests
test tests::test_sink_carbon::test_quantize_to_kg ... ok
test tests::test_sink_carbon::test_funder_balance_too_low ... ok
test tests::test_sink_carbon::test_sink_carbon_separate_recipient ... ok
test tests::test_sink_carbon::test_funder_account_or_trustline_missing ... ok
...

Mutation testing

We use mutation testing to identify code that is poorly tested. Run cargo mutants to execute the test suite with mutants of the contract code. Contract code that can be mutated without having an effect on the test outcomes tends to indicate that this line isn't yet being tested properly.

First install cargo-mutants globally:

cargo install cargo-mutants

Then, you should be able to:

cargo mutants --profile=mutants

If such lack of test coverage is found, you should see output similar to:

Found 33 mutants to test
ok       Unmutated baseline in 15.7s build + 0.4s test
 INFO Auto-set test timeout to 20s
MISSED   contracts/sink_carbon/src/storage_types.rs:4:51: replace * with + in 0.8s build + 0.4s test
MISSED   contracts/sink_carbon/src/storage_types.rs:18:5: replace extend_instance_ttl with () in 0.8s build + 0.4s test
MISSED   contracts/sink_carbon/src/storage_types.rs:5:71: replace - with / in 0.8s build + 0.4s test
33 mutants tested in 52s: 3 missed, 28 caught, 2 unviable

Cargo-mutants can be slow to complete with a vanilla cargo build setup. See the guide on improving performance to speed up these runs.

Build the Contract

To build a smart contract to deploy or run, use the stellar contract build command.

stellar contract build

If you get an error like can't find crate for 'core', it means you didn't install the wasm32 target during the Soroban setup. You can fix it by running rustup target add wasm32v1-none.

Optimization

Use stellar contract optimize to further minimize the size of the .wasm. First, re-install stellar-cli with the opt feature:

cargo install --locked stellar-cli --features opt

Then build an optimized .wasm file:

stellar contract optimize --wasm target/wasm32v1-none/release/sink_carbon.wasm

This will optimize and output a new sink_carbon.optimized.wasm file in the same location as the input .wasm.

Release and Deploy

The release process is incorporated into CI/CD using the soroban-build-workflow. To deploy the latest release to testnet, first download it from GitHub. Deploying a locally built WASM can break the attestations that are generated by the workflow.

Upload

Upload the contract WASM bytes to the network with stellar-cli:

stellar contract upload \
  --network testnet \
  --source <SOURCE_ACCOUNT> \
  --wasm ~/Downloads/sink-carbon_v0.4.0.wasm

The (stdout) output is the WASM hash:

ℹ️  Simulating install transaction…
ℹ️  Signing transaction: d8de6f2a24633ab73d0d37bcc0c4a4c75d5dbbd281d837ec82daad49771b6cec
🌎 Submitting install transaction…
0f82a7cacf4085a42905b9a54767ecc06d1132ee03ffef7018fbfb15f32be217

Deploy

The contract configuration is very important. The CarbonSINK issuer must be set as the contract admin, because it's going to delegate its own admin privileges to the SinkContract. There is a recovery mechanism that can set the CarbonSINK SAC admin, which expects the contract admin to be the CarbonSINK issuer.

PREV_SINK=$(stellar contract alias show sink --network testnet)  # only applies for upgrades
CARBON_ISSUER="GDT5XM5C5STQZS5R3F4CEGKJWKDVWBIWBEV4TIYV5MDVVMKA775T4OKY"
CSINK_ISSUER="GBO66IRGFZE7UP7MAM5H5IBMZLTM64XE6YNOL4KSL2BFVH7JW6AEKZHO"
CARBON_SAC="$(stellar contract id asset --network testnet --asset CARBON:$CARBON_ISSUER)"
CSINK_SAC="$(stellar contract id asset --network testnet --asset CarbonSINK:$CSINK_ISSUER)"

stellar contract deploy \
  --wasm-hash <HASH> \
  --network testnet \
  --source <SOURCE_ACCOUNT> \
  --alias sink \
  -- \
  --admin $CSINK_ISSUER \
  --carbon_id $CARBON_SAC \
  --carbonsink_id $CSINK_SAC

The (stdout) output is the contract address of the instance you've just deployed:

ℹ️ Contract alias 'sink' references CAVS7HEUNFCMOW6DC7EBY7J6HNFJ5JJ7LV4H7RPUC6V5QO5OMS7AQLD5 on network 'Test SDF Network ; September 2015'
ℹ️ Using wasm hash 0f82a7cacf4085a42905b9a54767ecc06d1132ee03ffef7018fbfb15f32be217
ℹ️ Simulating deploy transaction…
ℹ️ Transaction hash is 824b0ec0402b31ae5d1ca3db4cbff72ac098f6036a6e0af6df436995fc771c11
🔗 https://stellar.expert/explorer/testnet/tx/824b0ec0402b31ae5d1ca3db4cbff72ac098f6036a6e0af6df436995fc771c11
ℹ️ Signing transaction: 824b0ec0402b31ae5d1ca3db4cbff72ac098f6036a6e0af6df436995fc771c11
🌎 Submitting deploy transaction…
🔗 https://stellar.expert/explorer/testnet/contract/CBDWJLGQPU3DOYCMVPYF56QFC7ISSC633QSJUSBJIXM6RJBTGDZVA27P
✅ Deployed!
⚠️ Overwriting existing alias "sink" that currently links to contract ID: CAVS7HEUNFCMOW6DC7EBY7J6HNFJ5JJ7LV4H7RPUC6V5QO5OMS7AQLD5
CBDWJLGQPU3DOYCMVPYF56QFC7ISSC633QSJUSBJIXM6RJBTGDZVA27P

Within stellar-cli, the contract is now also available under the sink alias.

Finally, we need to make the contract address the CarbonSINK SAC admin. Configuring the contracts this way, achieves that the CarbonSINK SAC can automatically authorize the SAC sub-calls within sink_carbon.

# Reset CarbonSINK SAC admin to its own issuer account
if [ -n "$PREV_SINK" ]; then
  stellar contract invoke \
    --network testnet \
    --source <CSINK_ISSUER_SECRET> \
    --id $PREV_SINK \
    -- \
    reset_admin
fi

# Set the new SinkContract as the CarbonSINK SAC admin
stellar contract invoke \
  --network testnet \
  --source <CSINK_ISSUER_SECRET> \
  --id $CSINK_SAC \
  -- \
  set_admin \
  --new_admin $(stellar contract alias show sink --network testnet)

When successful, the output shows a set_admin event:

Contract alias 'sink' references CBDWJLGQPU3DOYCMVPYF56QFC7ISSC633QSJUSBJIXM6RJBTGDZVA27P
 on network 'Test SDF Network ; September 2015'
ℹ️ Signing transaction: d4a213b34b787da798c508a5f149b812bd8b04a09011fc4701698bb8cb4933a7

📅 CCUQDX22YTF72Q2F5C4HZSWVMBFTPTLIYXOC3BSNTBSZVJWKMMNUOWXH - Event:
  [
    {"symbol":"set_admin"},
    {"address":"GBO66IRGFZE7UP7MAM5H5IBMZLTM64XE6YNOL4KSL2BFVH7JW6AEKZHO"},
    {"string":"CarbonSINK:GBO66IRGFZE7UP7MAM5H5IBMZLTM64XE6YNOL4KSL2BFVH7JW6AEKZHO"}
  ] =
    {"address":"CBDWJLGQPU3DOYCMVPYF56QFC7ISSC633QSJUSBJIXM6RJBTGDZVA27P"}

If the new contract replaces a previously deployed contract, set its successor to complete the upgrade process:

stellar contract invoke \
  --network testnet \
  --source <CSINK_ISSUER_SECRET> \
  --id $PREV_SINK \
  -- \
  set_contract_successor
  --successor $(stellar contract alias show sink --network testnet)

Mercury Retroshades

We use Retroshades to emit events instead of native Soroban events. Deploy a slimmed-down version of the sink carbon contract to Mercury with:

./deploy-retroshades.sh

You'll need to have your own Mercury account and API key to do this. The retroshade will listen to the invocations of the "sink" alias from the stellar-cli by default.

About

Home of Stellarcarbon's Soroban smart contracts

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •