├── .github └── workflows │ ├── check-generate-latest.yaml │ ├── linter-testing-lib.yaml │ ├── linter.yml │ └── release-templates.yaml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── concordium-cis2 ├── CHANGELOG.md ├── Cargo.toml ├── README.md └── src │ ├── cis2_client.rs │ └── lib.rs ├── concordium-std-derive ├── CHANGELOG.md ├── Cargo.toml ├── src │ └── lib.rs └── tests │ ├── test-programs │ ├── fail-acc-invalid-base58.rs │ ├── fail-acc-invalid-base58.stderr │ ├── fail-acc-multiple-arguments.rs │ ├── fail-acc-multiple-arguments.stderr │ ├── fail-acc-not-a-string.rs │ ├── fail-acc-not-a-string.stderr │ ├── fail-contract-invalid.rs │ ├── fail-contract-invalid.stderr │ ├── fail-missing-env.rs │ ├── fail-missing-env.stderr │ ├── fail-pk25519-invalid-hex.rs │ ├── fail-pk25519-invalid-hex.stderr │ ├── fail-pk25519-length.rs │ ├── fail-pk25519-length.stderr │ └── success.rs │ └── test.rs ├── concordium-std ├── CHANGELOG.md ├── Cargo.toml ├── README.md ├── src │ ├── bump_alloc.rs │ ├── constants.rs │ ├── impls.rs │ ├── lib.rs │ ├── prims.rs │ ├── state_btree.rs │ ├── test_env.rs │ ├── test_infrastructure.rs │ ├── test_infrastructure │ │ └── trie.rs │ ├── traits.rs │ └── types.rs └── tests │ ├── dbg.rs │ ├── dbg │ └── success.rs │ ├── derive-deletable │ ├── success-assoc-type.rs │ └── success-ident-param.rs │ ├── derive-deserial-with-state │ ├── fail-colliding-forward.rs │ ├── fail-colliding-forward.stderr │ ├── fail-colliding-tag-forward.rs │ ├── fail-colliding-tag-forward.stderr │ ├── fail-colliding-tag.rs │ ├── fail-colliding-tag.stderr │ ├── fail-forward-collide-with-inferred.rs │ ├── fail-forward-collide-with-inferred.stderr │ ├── fail-forward-gt-repr.rs │ ├── fail-forward-gt-repr.stderr │ ├── fail-forward-without-repr.rs │ ├── fail-forward-without-repr.stderr │ ├── fail-tag-collide-with-inferred.rs │ ├── fail-tag-collide-with-inferred.stderr │ ├── fail-tag-gt-repr.rs │ ├── fail-tag-gt-repr.stderr │ ├── fail-tag-without-repr.rs │ ├── fail-tag-without-repr.stderr │ ├── success-assoc-type.rs │ ├── success-generics.rs │ └── success-ident-param.rs │ ├── derive-deserial │ ├── fail-colliding-forward.rs │ ├── fail-colliding-forward.stderr │ ├── fail-colliding-tag-forward.rs │ ├── fail-colliding-tag-forward.stderr │ ├── fail-colliding-tag.rs │ ├── fail-colliding-tag.stderr │ ├── fail-forward-collide-with-inferred.rs │ ├── fail-forward-collide-with-inferred.stderr │ ├── fail-forward-gt-repr.rs │ ├── fail-forward-gt-repr.stderr │ ├── fail-forward-without-repr.rs │ ├── fail-forward-without-repr.stderr │ ├── fail-tag-collide-with-inferred.rs │ ├── fail-tag-collide-with-inferred.stderr │ ├── fail-tag-gt-repr.rs │ ├── fail-tag-gt-repr.stderr │ ├── fail-tag-without-repr.rs │ ├── fail-tag-without-repr.stderr │ ├── success-attributes.rs │ ├── success-forward-attribute.rs │ ├── success-generics.rs │ └── success-simple.rs │ ├── derive-schema-type │ ├── fail-colliding-forward.rs │ ├── fail-colliding-forward.stderr │ ├── fail-colliding-tag-forward.rs │ ├── fail-colliding-tag-forward.stderr │ ├── fail-colliding-tag.rs │ ├── fail-colliding-tag.stderr │ ├── fail-forward-collide-with-inferred.rs │ ├── fail-forward-collide-with-inferred.stderr │ ├── fail-forward-gt-repr.rs │ ├── fail-forward-gt-repr.stderr │ ├── fail-forward-without-repr.rs │ ├── fail-forward-without-repr.stderr │ ├── fail-tag-collide-with-inferred.rs │ ├── fail-tag-collide-with-inferred.stderr │ ├── fail-tag-gt-repr.rs │ ├── fail-tag-gt-repr.stderr │ ├── fail-tag-without-repr.rs │ ├── fail-tag-without-repr.stderr │ ├── success-attributes.rs │ ├── success-forward-attribute.rs │ ├── success-generics.rs │ ├── success-simple.rs │ └── success-transparent.rs │ ├── derive-serial │ ├── fail-colliding-forward.rs │ ├── fail-colliding-forward.stderr │ ├── fail-colliding-tag-forward.rs │ ├── fail-colliding-tag-forward.stderr │ ├── fail-colliding-tag.rs │ ├── fail-colliding-tag.stderr │ ├── fail-forward-collide-with-inferred.rs │ ├── fail-forward-collide-with-inferred.stderr │ ├── fail-forward-gt-repr.rs │ ├── fail-forward-gt-repr.stderr │ ├── fail-forward-without-repr.rs │ ├── fail-forward-without-repr.stderr │ ├── fail-tag-collide-with-inferred.rs │ ├── fail-tag-collide-with-inferred.stderr │ ├── fail-tag-gt-repr.rs │ ├── fail-tag-gt-repr.stderr │ ├── fail-tag-without-repr.rs │ ├── fail-tag-without-repr.stderr │ ├── success-attributes.rs │ ├── success-forward-attribute.rs │ ├── success-generics.rs │ └── success-simple.rs │ ├── derives.rs │ └── state │ ├── map-multiple-entries.rs │ ├── map-multiple-entries.stderr │ ├── map-multiple-state-ref-mut.rs │ └── map-multiple-state-ref-mut.stderr ├── contract-testing ├── CHANGELOG.md ├── Cargo.toml ├── README.md ├── src │ ├── constants.rs │ ├── impls.rs │ ├── invocation │ │ ├── impls.rs │ │ ├── mod.rs │ │ └── types.rs │ ├── lib.rs │ └── types.rs └── tests │ ├── account-signature-checks.rs │ ├── all_new_host_functions.rs │ ├── basics.rs │ ├── checkpointing.rs │ ├── contract_queries.rs │ ├── counter.rs │ ├── error_codes.rs │ ├── fallback.rs │ ├── helpers │ └── mod.rs │ ├── iterator.rs │ ├── queries.rs │ ├── recorder.rs │ ├── relaxed_restrictions.rs │ ├── self_balance.rs │ ├── transfer.rs │ └── upgrades.rs ├── examples ├── LICENSE ├── README.md ├── account-signature-checks │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── auction │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── bump-alloc-tests │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── cis2-dynamic-nft │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── cis2-multi-royalties │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── cis2-multi │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── cis2-nft │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── cis2-wccd │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── cis3-nft-sponsored-txs │ ├── Cargo.toml │ ├── README.md │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── cis5-smart-contract-wallet │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── counter-notify │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── credential-registry │ ├── Cargo.toml │ ├── README.md │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── eSealing │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── factory │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── fib │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── icecream │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── memo │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── nametoken │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── offchain-transfers │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── lib.rs ├── piggy-bank │ ├── README.md │ ├── part1 │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ └── part2 │ │ ├── Cargo.toml │ │ ├── src │ │ └── lib.rs │ │ └── tests │ │ └── tests.rs ├── proxy │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── recorder │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── signature-verifier │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── smart-contract-upgrade │ ├── contract-version1 │ │ ├── Cargo.toml │ │ ├── src │ │ │ └── lib.rs │ │ └── tests │ │ │ └── tests.rs │ └── contract-version2 │ │ ├── Cargo.toml │ │ └── src │ │ └── lib.rs ├── sponsored-tx-enabled-auction │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── transfer-policy-check │ ├── Cargo.toml │ ├── src │ │ └── lib.rs │ └── tests │ │ └── tests.rs ├── two-step-transfer │ ├── Cargo.toml │ └── src │ │ └── lib.rs └── voting │ ├── Cargo.toml │ ├── src │ └── lib.rs │ └── tests │ └── tests.rs ├── rustfmt.toml └── templates ├── README.md ├── cis2-nft ├── Cargo.toml ├── cargo-generate.toml ├── src │ └── lib.rs └── tests │ └── tests.rs ├── credential-registry ├── Cargo.toml ├── README.md ├── cargo-generate.toml ├── pre-script.rhai ├── src │ └── lib.rs └── tests │ └── tests.rs ├── default ├── Cargo.toml ├── cargo-generate.toml ├── deploy-scripts │ ├── Cargo.toml │ ├── README.md │ └── src │ │ ├── deployer.rs │ │ └── main.rs ├── src │ └── lib.rs └── tests │ └── tests.rs ├── issue-template.md └── resources ├── compile.gif ├── init.gif ├── simulation_init.gif ├── simulation_receive_throw_error_false.gif ├── simulation_receive_throw_error_true.gif ├── simulation_view.gif └── test.gif /.github/workflows/check-generate-latest.yaml: -------------------------------------------------------------------------------- 1 | # The purpose of this workflow is to make sure that our templates also work with 2 | # the latest version of cargo-generate. It is run daily at 12 and creates an 3 | # issue on failure. 4 | 5 | on: 6 | # Trigger the workflow on push or pull request, 7 | # but only for the main branch 8 | schedule: 9 | - cron: '0 12 * * *' # run every day at 12 10 | 11 | workflow_dispatch: # allows manual trigger 12 | 13 | name: Check cargo-generate in all templates with the latest version. 14 | 15 | jobs: 16 | # All templates are generated with the `cargo-generate` command and it is checked that the 'cargo test' command 17 | # can be executed without errors on the generated smart contracts. 18 | cargo-generate-templates: 19 | name: Smart contract template generation 20 | runs-on: ubuntu-latest 21 | outputs: 22 | version: ${{ steps.generate.outputs.version }} 23 | strategy: 24 | matrix: 25 | crates: 26 | - templates/default 27 | - templates/cis2-nft 28 | env: 29 | PROJECT_NAME: my-project 30 | 31 | steps: 32 | - name: Checkout sources 33 | uses: actions/checkout@v4 34 | with: 35 | submodules: recursive 36 | 37 | - name: Run cargo-generate 38 | # Use latest version to make sure our templates build with that. 39 | uses: actions-rust-lang/setup-rust-toolchain@v1 40 | 41 | - id: generate 42 | run: | 43 | cargo install cargo-generate --features=vendored-openssl --locked 44 | export VERSION=$(cargo generate --version) 45 | echo "version=${VERSION}" >> "$GITHUB_OUTPUT" 46 | cargo generate --name ${{ env.PROJECT_NAME }} -d description=myProject -d tokenMetadataBaseURL=https://some.example/token/ ${{ matrix.crates }} 47 | 48 | # The credential registry template is used to generate code for all 49 | # combinations of parameters. 50 | cargo-generate-credential-registry-template: 51 | name: Credential registry template tests 52 | runs-on: ubuntu-latest 53 | outputs: 54 | version: ${{ steps.generate.outputs.version }} 55 | strategy: 56 | matrix: 57 | restorable: ["true", "false"] 58 | revocable_by_others: ["true", "false"] 59 | env: 60 | PROJECT_NAME: my-project 61 | 62 | steps: 63 | - name: Checkout sources 64 | uses: actions/checkout@v4 65 | with: 66 | submodules: recursive 67 | - uses: actions-rust-lang/setup-rust-toolchain@v1 68 | - id: generate 69 | run: | 70 | cargo install cargo-generate --features=vendored-openssl --locked 71 | export VERSION=$(cargo generate --version) 72 | echo "version=${VERSION}" >> "$GITHUB_OUTPUT" 73 | cargo generate --name ${{ env.PROJECT_NAME }} -d description=myProject -d template_type=custom -d restorable=${{ matrix.restorable }} -d revocable_by_others=${{ matrix.revocable_by_others }} templates/credential-registry 74 | 75 | create-issue: 76 | runs-on: ubuntu-latest 77 | needs: [cargo-generate-templates, cargo-generate-credential-registry-template] 78 | if: | 79 | always() && 80 | contains(needs.*.result, 'failure') 81 | steps: 82 | - uses: actions/checkout@v4 83 | - uses: JasonEtco/create-an-issue@v2 84 | env: 85 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 86 | VERSION: ${{ needs.cargo-generate-templates.outputs.version }} 87 | with: 88 | filename: ./templates/issue-template.md 89 | update_existing: true 90 | search_existing: open # only search open issues 91 | -------------------------------------------------------------------------------- /.github/workflows/linter-testing-lib.yaml: -------------------------------------------------------------------------------- 1 | name: "Testing library: Format, lint, build, and test" 2 | 3 | # This job runs: 4 | # - rustfmt 5 | # - rustdoc 6 | # - clippy linting 7 | # - tests 8 | # for the smart contract testing library. 9 | 10 | on: 11 | push: 12 | branches: main 13 | 14 | pull_request: 15 | branches: main 16 | types: 17 | - opened 18 | - reopened 19 | - synchronize 20 | - ready_for_review 21 | paths: 22 | - 'contract-testing/**/*.rs' 23 | - 'contract-testing/**/*.toml' 24 | - 'rustfmt.toml' 25 | - 'concordium-rust-sdk' 26 | - 'concordium-std-derive' 27 | 28 | workflow_dispatch: # allows manual trigger 29 | 30 | env: 31 | RUST_FMT: nightly-2023-04-01-x86_64-unknown-linux-gnu 32 | RUST_CLIPPY: 1.73 33 | 34 | jobs: 35 | "lint_fmt": 36 | name: ${{ matrix.build-dir }} lint:fmt 37 | # Don't run on draft pull requests 38 | if: ${{ !github.event.pull_request.draft }} 39 | runs-on: ubuntu-latest 40 | strategy: 41 | matrix: 42 | build-dir: 43 | - 'contract-testing' 44 | steps: 45 | - name: Checkout 46 | uses: actions/checkout@v3 47 | - name: Install Rust 48 | uses: actions-rs/toolchain@v1 49 | with: 50 | profile: minimal 51 | toolchain: ${{ env.RUST_FMT }} 52 | override: true 53 | components: rustfmt 54 | - name: Format 55 | working-directory: ${{ matrix.build-dir }} 56 | run: | 57 | cargo fmt -- --color=always --check 58 | 59 | "lint_doc": 60 | name: ${{ matrix.build-dir }} lint:doc 61 | # Don't run on draft pull requests 62 | if: ${{ !github.event.pull_request.draft }} 63 | runs-on: ubuntu-latest 64 | strategy: 65 | matrix: 66 | build-dir: 67 | - 'contract-testing' 68 | steps: 69 | - name: Checkout 70 | uses: actions/checkout@v3 71 | with: 72 | submodules: recursive 73 | - name: Install Rust 74 | uses: actions-rs/toolchain@v1 75 | with: 76 | profile: minimal 77 | toolchain: ${{ env.RUST_CLIPPY }} 78 | override: true 79 | - name: Docs 80 | working-directory: ${{ matrix.build-dir }} 81 | run: | 82 | RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features --color=always 83 | 84 | "lint_clippy": 85 | name: ${{ matrix.build-dir }} lint:clippy 86 | # Don't run on draft pull requests 87 | if: ${{ !github.event.pull_request.draft }} 88 | runs-on: ubuntu-latest 89 | strategy: 90 | matrix: 91 | build-dir: 92 | - 'contract-testing' 93 | steps: 94 | - name: Checkout 95 | uses: actions/checkout@v3 96 | with: 97 | submodules: recursive 98 | - name: Install Rust 99 | uses: actions-rs/toolchain@v1 100 | with: 101 | profile: minimal 102 | toolchain: ${{ env.RUST_CLIPPY }} 103 | override: true 104 | components: clippy 105 | - name: Clippy 106 | working-directory: ${{ matrix.build-dir }} 107 | run: | 108 | git config --global url."https://github.com/".insteadOf "git@github.com:" 109 | cargo clippy --color=always --tests --benches -- -Dclippy::all 110 | 111 | "cargo_test": 112 | name: ${{ matrix.build-dir }} cargo:test 113 | runs-on: ubuntu-latest 114 | needs: "lint_fmt" 115 | strategy: 116 | matrix: 117 | build-dir: 118 | - 'contract-testing' 119 | steps: 120 | - name: Checkout 121 | uses: actions/checkout@v3 122 | with: 123 | submodules: recursive 124 | - name: Install Rust 125 | uses: actions-rs/toolchain@v1 126 | with: 127 | profile: minimal 128 | toolchain: ${{ env.RUST_CLIPPY }} 129 | override: true 130 | - name: Test 131 | working-directory: ${{ matrix.build-dir }} 132 | run: cargo test -- --skip io_tests # Skip the I/O tests in the testing library. 133 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .stack-work/ 2 | *~ 3 | *.swp 4 | *.out 5 | *.dll 6 | *.exe 7 | *.a 8 | *.pdf 9 | *.csv 10 | 11 | .stack-work 12 | target 13 | *.json 14 | /.dir-locals.el 15 | *.bin 16 | pkg 17 | *.hie 18 | *.iml 19 | *.state-* 20 | *.state 21 | 22 | Cargo.lock 23 | 24 | *.wasm.v1 25 | *.wasm.v0 26 | 27 | # Editor specific 28 | **/.helix 29 | 30 | # Nix artifacts 31 | **/*.nix 32 | **/flake.lock 33 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "concordium-rust-sdk"] 2 | path = concordium-rust-sdk 3 | url = ../concordium-rust-sdk.git 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Standard library for writing smart contracts for the Concordium blockchain 2 | 3 | [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.0-4baaaa.svg)](https://github.com/Concordium/.github/blob/main/.github/CODE_OF_CONDUCT.md) 4 | 5 | This repository consists of libraries for writing and testing smart contracts for the Concordium blockchain in the Rust programming language. 6 | It also contains some sample smart contracts. 7 | The core library is 8 | [concordium-std](./concordium-std), and the testing library is [concordium-smart-contract-testing](./contract-testing). 9 | 10 | The core library provides procedural macros to reduce the amount of boilerplate the user needs to write, 11 | while the `concordium-std` library exposes a high-level API that smart contract 12 | writers can use when writing contracts, alleviating them from the need to deal 13 | with low-level details of how the interaction with the chain works. 14 | 15 | ## Versions 16 | 17 | - `concordium-std` **prior to** version 3 supported version 0 contracts 18 | - `concordium-std` version 3 only supports building version 1 contracts 19 | 20 | ### `cargo-concordium` version dependencies 21 | - `concordium-std` version 4 only works with `cargo-concordium` version 2.1+. 22 | - `concordium-std` version 5 only works with `cargo-concordium` version 2.4+. 23 | 24 | ## Examples 25 | 26 | The [examples](./examples) directory contains some smart contracts that are used 27 | to test the standard library. 28 | 29 | These contracts are not meant for production, they are used to illustrate how to use 30 | the standard library and the tooling Concordium provides. There is no claim that 31 | the logic of the contract is reasonable, or safe. 32 | 33 | **Do not use these contracts as-is for anything other then experimenting.** 34 | 35 | ## Submodules 36 | 37 | The repository has 38 | [concordium-rust-sdk](https://github.com/Concordium/concordium-rust-sdk) 39 | as a submodule, and testing and builds are set-up to use the submodule version. 40 | When changes are made in `concordium-rust-sdk` they should be propagated 41 | to this repository. 42 | 43 | ## Contributing 44 | 45 | [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.0-4baaaa.svg)](https://github.com/Concordium/.github/blob/main/.github/CODE_OF_CONDUCT.md) 46 | 47 | This repository's CI automatically checks formatting and common problems in rust. 48 | Changes to any of the packages must be such that 49 | 50 | - ```cargo clippy --all``` produces no warnings 51 | - ```rustfmt``` makes no changes. 52 | 53 | Everything in this repository should build with rust version 1.67 however the `fmt` tool must be from a nightly release since some of the configuration options are not stable. One way to run the `fmt` tool is 54 | ``` 55 | cargo +nightly-2023-04-01 fmt 56 | ``` 57 | 58 | (the exact version used by the CI can be found in [.github/workflows/linter.yml](.github/workflows/linter.yml) file). 59 | You will need to have a recent enough nightly version installed, which can be done via 60 | 61 | ``` 62 | rustup toolchain install nightly-2023-04-01 63 | ``` 64 | 65 | or similar, using the [rustup](https://rustup.rs/) tool. See the documentation of the tool for more details. 66 | 67 | In order to contribute you should make a pull request and ask at least two people familiar with the code to do a review. 68 | -------------------------------------------------------------------------------- /concordium-cis2/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## concordium-cis2 6.2.0 (2024-09-19) 4 | 5 | - Bump MSRV to 1.72 6 | - Add `FromStr` implementations for `TokenId` types. 7 | - Add a `serde` feature that derives `serde::Serialize` and `serde::Deserialize` for `TokenId` types, `TokenAmount` types, `OnReceivingCis2DataParams`, `OnReceivingCis2Params`, `AdditionalData`, and `Receiver`. 8 | - Fix `SchemaType` implementation of `OnReceivingCis2DataParams` so that it matches `Serial` and `Deserial` implementations. 9 | 10 | ## concordium-cis2 6.1.0 (2024-02-22) 11 | 12 | - Support version 10 of concordium-std. 13 | 14 | ## concordium-cis2 6.0.0 (2024-01-22) 15 | 16 | - Add `Clone` trait for `StandardIdentifierOwned`. 17 | - Add specific parameter type `OnReceivingCis2DataParams` for a contract function which receives CIS2 tokens with a specific type D for the AdditionalData. 18 | - Add `Deserial` trait for `OnReceivingCis2DataParams`. 19 | - Add `Serial` trait for `OnReceivingCis2DataParams`. 20 | - Update `concordium-std` version to `9`. 21 | 22 | ## concordium-cis2 5.1.0 (2023-10-18) 23 | 24 | - Derive `PartialEq` and `Eq` for `Cis2Event`, `BalanceOfQueryResponse`, and `OperatorOfQueryResponse`. 25 | 26 | ## concordium-cis2 5.0.0 (2023-08-21) 27 | 28 | - Derive `PartialEq` and `Eq` for the `TransferEvent`, `MintEvent`, `BurnEvent`, `UpdateOperatorEvent`, `TokenMetadataEvent`, `OperatorUpdate`, and `UpdateOperator` types. 29 | - Added `Cis2Client` to the library. This can be used from one smart contract to 30 | call into other cis2 compatible smart contracts in a type safe way. 31 | - Bump concordium-std to version 8. 32 | 33 | ## concordium-cis2 4.0.0 (2023-06-16) 34 | 35 | - Bump concordium-std to version 7. 36 | 37 | ## concordium-cis2 3.1.0 (2023-05-08) 38 | 39 | - Derive `PartialEq` and `Eq` for the `MetadataUrl` from the CIS2 library. 40 | - Update `concordium-std` dependency to 6.2. 41 | 42 | ## concordium-cis2 3.0.0 (2023-02-08) 43 | 44 | - Update `concordium-std` to version 6. 45 | 46 | ## concordium-cis2 2.0.0 (2022-11-21) 47 | 48 | - Update `concordium-std` to version 5. 49 | - Add `From` implementation from types implementing `From`, `From` or `From` to `Cis2Error`. 50 | - Add SchemaType for Cis2Event 51 | 52 | ## concordium-cis2 1.2.0 (2022-09-01) 53 | 54 | - Add `TokenAmountU256` 55 | - Fix overflow during deserialization of amounts. 56 | 57 | ## concordium-cis2 1.1.0 (2022-08-24) 58 | 59 | - Update `concordium-std` to version 4. 60 | - Support schemas for error types defined in the library. 61 | 62 | ## concordium-cis2 1.0.0 63 | 64 | Initial release of the library. 65 | -------------------------------------------------------------------------------- /concordium-cis2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "concordium-cis2" 3 | version = "6.2.0" 4 | authors = ["Concordium "] 5 | rust-version = "1.73" 6 | edition = "2021" 7 | license = "MPL-2.0" 8 | description = "A collection of types for implementing CIS-2 Concordium Token Standard." 9 | homepage = "https://github.com/Concordium/concordium-rust-smart-contracts/" 10 | repository = "https://github.com/Concordium/concordium-rust-smart-contracts/" 11 | readme = "./README.md" 12 | 13 | [dependencies.concordium-std] 14 | path = "../concordium-std" 15 | version = "10.0" 16 | default-features = false 17 | 18 | [dependencies.primitive-types] 19 | version = "0.11" 20 | default-features = false 21 | 22 | [dependencies.serde] 23 | version = "1.0" 24 | features = ["alloc", "derive"] 25 | optional = true 26 | default-features = false 27 | 28 | [dependencies.concordium-contracts-common] 29 | path = "../concordium-rust-sdk/concordium-base/smart-contracts/contracts-common/concordium-contracts-common" 30 | version = "9.0" 31 | optional = true 32 | default-features = false 33 | 34 | [features] 35 | default = ["std"] 36 | std = ["concordium-std/std"] 37 | u256_amount = [] 38 | serde = [ 39 | "dep:serde", 40 | "concordium-contracts-common/derive-serde", 41 | "primitive-types/impl-serde", 42 | ] 43 | 44 | [lib] 45 | crate-type = ["rlib"] 46 | 47 | [profile.release] 48 | opt-level = "s" 49 | 50 | [package.metadata.docs.rs] 51 | # This sets the default target to `wasm32-unknown-unknown` and only builds that 52 | # target on docs.rs. This is useful because the some parts of documentation only 53 | # exist on that platform. 54 | targets = ["wasm32-unknown-unknown"] 55 | # Default features to build documentation for. 56 | features = ["std", "u256_amount", "serde"] 57 | rustc-args = ["--cfg", "docsrs"] 58 | -------------------------------------------------------------------------------- /concordium-cis2/README.md: -------------------------------------------------------------------------------- 1 | A library that simplifies working with the [Concordium Token Standard 2 | CIS2](https://proposals.concordium.software/CIS/cis-2.html) on-chain. 3 | 4 | Links: 5 | - [Documentation](https://docs.rs/concordium-cis2/latest/concordium_cis2/) 6 | - [Crates.io](https://crates.io/crates/concordium-cis2) 7 | 8 | -------------------------------------------------------------------------------- /concordium-std-derive/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Unreleased changes 4 | 5 | ## concordium-std-derive 6.0.0 (2024-04-04) 6 | 7 | - Macros for creating constant values from strings for the following types: 8 | - `AccountAddress` 9 | - `ContractAddress` 10 | - `ModuleReference` 11 | - `PublicKeyEcdsaSecp256k1` 12 | - `PublicKeyEd25519` 13 | - `SignatureEcdsaSecp256k1` 14 | - `SignatureEd25519` 15 | -------------------------------------------------------------------------------- /concordium-std-derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "concordium-std-derive" 3 | authors = ["Concordium "] 4 | version = "6.0.0" 5 | edition = "2021" 6 | rust-version = "1.73" 7 | license = "MPL-2.0" 8 | description = "Procedural macros to generate concordium type constants from strings, that makes writing smart contracts on the Concordium blockchain easier." 9 | homepage = "https://github.com/Concordium/concordium-rust-smart-contracts/" 10 | repository = "https://github.com/Concordium/concordium-rust-smart-contracts/" 11 | 12 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 13 | [lib] 14 | proc-macro = true 15 | 16 | [dependencies] 17 | concordium-contracts-common = { path = "../concordium-rust-sdk/concordium-base/smart-contracts/contracts-common/concordium-contracts-common", features = [ "derive-serde" ], version = "9" } 18 | syn = "2.0" 19 | proc-macro2 = "1.0" 20 | quote = "1.0" 21 | 22 | [dev-dependencies] 23 | trybuild = "1.0" 24 | 25 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/fail-acc-invalid-base58.rs: -------------------------------------------------------------------------------- 1 | //! Ensure that the macros generate compilable code. 2 | 3 | use concordium_contracts_common::*; 4 | use concordium_std_derive::*; 5 | 6 | const ACC: AccountAddress = account_address!("30Bx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G"); 7 | 8 | fn f() { 9 | println!("{:?}", ACC.to_string()); 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/fail-acc-invalid-base58.stderr: -------------------------------------------------------------------------------- 1 | error: Invalid account address: Invalid Base58Check encoding. 2 | --> tests/test-programs/fail-acc-invalid-base58.rs:6:46 3 | | 4 | 6 | const ACC: AccountAddress = account_address!("30Bx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G"); 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/fail-acc-multiple-arguments.rs: -------------------------------------------------------------------------------- 1 | //! Ensure that the macros generate compilable code. 2 | 3 | use concordium_contracts_common::*; 4 | use concordium_std_derive::*; 5 | 6 | const ACC: AccountAddress = account_address!("3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G", "3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G"); 7 | 8 | fn f() { 9 | println!("{:?}", ACC.to_string()); 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/fail-acc-multiple-arguments.stderr: -------------------------------------------------------------------------------- 1 | error: Expected a string literal of a hex-encoded account address 2 | --> tests/test-programs/fail-acc-multiple-arguments.rs:6:29 3 | | 4 | 6 | ...ss = account_address!("3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G", "3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G"); 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | | 7 | = note: this error originates in the macro `account_address` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/fail-acc-not-a-string.rs: -------------------------------------------------------------------------------- 1 | //! Ensure that the macros generate compilable code. 2 | 3 | use concordium_contracts_common::*; 4 | use concordium_std_derive::*; 5 | 6 | const ACC: AccountAddress = account_address!(0); 7 | 8 | fn f() { 9 | println!("{:?}", ACC.to_string()); 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/fail-acc-not-a-string.stderr: -------------------------------------------------------------------------------- 1 | error: Expected a string literal of a hex-encoded account address 2 | --> tests/test-programs/fail-acc-not-a-string.rs:6:29 3 | | 4 | 6 | const ACC: AccountAddress = account_address!(0); 5 | | ^^^^^^^^^^^^^^^^^^^ 6 | | 7 | = note: this error originates in the macro `account_address` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/fail-contract-invalid.rs: -------------------------------------------------------------------------------- 1 | //! Ensure that the macros generate compilable code. 2 | 3 | use concordium_contracts_common::*; 4 | use concordium_std_derive::*; 5 | 6 | const CONTRACT: ContractAddress = contract_address!("<0, 0>"); 7 | 8 | fn f() { 9 | println!("{:?}", CONTRACT.to_string()); 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/fail-contract-invalid.stderr: -------------------------------------------------------------------------------- 1 | error: Invalid contract address: Failed to parse the subindex integer: invalid digit found in string 2 | --> tests/test-programs/fail-contract-invalid.rs:6:53 3 | | 4 | 6 | const CONTRACT: ContractAddress = contract_address!("<0, 0>"); 5 | | ^^^^^^^^ 6 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/fail-missing-env.rs: -------------------------------------------------------------------------------- 1 | //! Ensure that the macros generate compilable code. 2 | 3 | use concordium_contracts_common::*; 4 | use concordium_std_derive::*; 5 | 6 | const ACC: AccountAddress = account_address_env!("TEST"); 7 | 8 | fn f() { 9 | println!("{:?}", ACC.to_string()); 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/fail-missing-env.stderr: -------------------------------------------------------------------------------- 1 | error: Environment variable error: NotPresent 2 | --> tests/test-programs/fail-missing-env.rs:6:50 3 | | 4 | 6 | const ACC: AccountAddress = account_address_env!("TEST"); 5 | | ^^^^^^ 6 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/fail-pk25519-invalid-hex.rs: -------------------------------------------------------------------------------- 1 | //! Ensure that the macros generate compilable code. 2 | 3 | use concordium_contracts_common::*; 4 | use concordium_std_derive::*; 5 | 6 | const PK_25519: PublicKeyEd25519 = public_key_ed25519!("0l2a7e286063ae5dfcebce40636c0546d367d8c65cd4cb69aae1af77a4d61412"); 7 | 8 | fn f() { 9 | println!("{:?}", PK_25519.to_string()); 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/fail-pk25519-invalid-hex.stderr: -------------------------------------------------------------------------------- 1 | error: Invalid Ed25519 public key: Parsing failed 2 | --> tests/test-programs/fail-pk25519-invalid-hex.rs:6:56 3 | | 4 | 6 | const PK_25519: PublicKeyEd25519 = public_key_ed25519!("0l2a7e286063ae5dfcebce40636c0546d367d8c65cd4cb69aae1af77a4d61412"); 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/fail-pk25519-length.rs: -------------------------------------------------------------------------------- 1 | //! Ensure that the macros generate compilable code. 2 | 3 | use concordium_contracts_common::*; 4 | use concordium_std_derive::*; 5 | 6 | const PK_25519: PublicKeyEd25519 = public_key_ed25519!("012a7e286063ae5dfcebce40636c0546d367d8c65cd4cb69aae1af77a4d6141201"); 7 | 8 | fn f() { 9 | println!("{:?}", PK_25519.to_string()); 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/fail-pk25519-length.stderr: -------------------------------------------------------------------------------- 1 | error: Invalid Ed25519 public key: Parsing failed 2 | --> tests/test-programs/fail-pk25519-length.rs:6:56 3 | | 4 | 6 | const PK_25519: PublicKeyEd25519 = public_key_ed25519!("012a7e286063ae5dfcebce40636c0546d367d8c65cd4cb69aae1af77a4d6141201"); 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test-programs/success.rs: -------------------------------------------------------------------------------- 1 | //! Ensure that the macros generate compilable code. 2 | 3 | use concordium_contracts_common as concordium_std; 4 | use concordium_contracts_common::*; 5 | use concordium_std_derive::*; 6 | 7 | const ACC: AccountAddress = account_address!("3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G"); 8 | const REF: ModuleReference = 9 | module_reference!("0000000000000000000000000000000000000000000000000000000000000000"); 10 | const CONTRACT: ContractAddress = contract_address!("<1234,0>"); 11 | const PK_25519: PublicKeyEd25519 = 12 | public_key_ed25519!("012a7e286063ae5dfcebce40636c0546d367d8c65cd4cb69aae1af77a4d61412"); 13 | const PK_ECDSA: PublicKeyEcdsaSecp256k1 = 14 | public_key_ecdsa!("0214e6a60b8fc58ea707d8ee8fa6ca7b28626d4f6f80b170982644c95d12111853"); 15 | const SG_25519: SignatureEd25519 = signature_ed25519!("ec076ae7adaf0a8b921cf2bad86a1a5b5346226618637aa0d6b30f9616f108f9f482640a4ceb14235569cd3af05fac00be2c82dc81c6f6b4a6ba4ea7c3b51a0b"); 16 | const SG_ECDSA: SignatureEcdsaSecp256k1 = signature_ecdsa!("EC076AE7ADAF0A8B921CF2BAD86A1A5B5346226618637AA0D6B30F9616F108F9F482640A4CEB14235569CD3AF05FAC00BE2C82DC81C6F6B4A6BA4EA7C3B51A0B"); 17 | 18 | const ACC_ENV: AccountAddress = account_address_env!("ACC"); 19 | const REF_ENV: ModuleReference = module_reference_env!("REF"); 20 | const CONTRACT_ENV: ContractAddress = contract_address_env!("CONTRACT"); 21 | const PK_25519_ENV: PublicKeyEd25519 = public_key_ed25519_env!("PK_25519"); 22 | const PK_ECDSA_ENV: PublicKeyEcdsaSecp256k1 = public_key_ecdsa_env!("PK_ECDSA"); 23 | const SG_25519_ENV: SignatureEd25519 = signature_ed25519_env!("SG_25519"); 24 | const SG_ECDSA_ENV: SignatureEcdsaSecp256k1 = signature_ecdsa_env!("SG_ECDSA"); 25 | 26 | fn main() { 27 | assert_eq!(ACC, ACC_ENV); 28 | assert_eq!(REF, REF_ENV); 29 | assert_eq!(CONTRACT, CONTRACT_ENV); 30 | assert_eq!(PK_25519, PK_25519_ENV); 31 | assert_eq!(PK_ECDSA, PK_ECDSA_ENV); 32 | assert_eq!(SG_25519, SG_25519_ENV); 33 | assert_eq!(SG_ECDSA, SG_ECDSA_ENV); 34 | } 35 | -------------------------------------------------------------------------------- /concordium-std-derive/tests/test.rs: -------------------------------------------------------------------------------- 1 | //! Test that the macros generates compilable code. 2 | #[test] 3 | fn tests() { 4 | std::env::set_var("MY_CUSTOM_FEATURE", "true"); 5 | std::env::set_var("ACC", "3kBx2h5Y2veb4hZgAJWPrr8RyQESKm5TjzF3ti1QQ4VSYLwK1G"); 6 | std::env::set_var("REF", "0000000000000000000000000000000000000000000000000000000000000000"); 7 | std::env::set_var("CONTRACT", "<1234,0>"); 8 | std::env::set_var( 9 | "PK_25519", 10 | "012a7e286063ae5dfcebce40636c0546d367d8c65cd4cb69aae1af77a4d61412", 11 | ); 12 | std::env::set_var( 13 | "PK_ECDSA", 14 | "0214e6a60b8fc58ea707d8ee8fa6ca7b28626d4f6f80b170982644c95d12111853", 15 | ); 16 | std::env::set_var("SG_25519", "ec076ae7adaf0a8b921cf2bad86a1a5b5346226618637aa0d6b30f9616f108f9f482640a4ceb14235569cd3af05fac00be2c82dc81c6f6b4a6ba4ea7c3b51a0b"); 17 | std::env::set_var("SG_ECDSA", "EC076AE7ADAF0A8B921CF2BAD86A1A5B5346226618637AA0D6B30F9616F108F9F482640A4CEB14235569CD3AF05FAC00BE2C82DC81C6F6B4A6BA4EA7C3B51A0B"); 18 | 19 | let t = trybuild::TestCases::new(); 20 | t.pass("tests/test-programs/success.rs"); 21 | t.compile_fail("tests/test-programs/fail-*.rs"); 22 | } 23 | -------------------------------------------------------------------------------- /concordium-std/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "concordium-std" 3 | version = "10.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | rust-version = "1.73" 7 | license = "MPL-2.0" 8 | description = "A standard library for writing smart contracts for the Concordium blockchain in Rust." 9 | homepage = "https://github.com/Concordium/concordium-rust-smart-contracts/" 10 | repository = "https://github.com/Concordium/concordium-rust-smart-contracts/" 11 | readme = "./README.md" 12 | 13 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 14 | [dependencies] 15 | sha2 = { version = "0.10", optional = true } 16 | sha3 = { version = "0.10", optional = true } 17 | secp256k1 = { version = "0.22", optional = true, features = ["lowmemory"] } 18 | ed25519-zebra = { version = "2.2", optional = true } 19 | quickcheck = {version = "1", optional = true } 20 | getrandom = { version = "0.2", features = ["custom"], optional = true } 21 | 22 | [dependencies.concordium-contracts-common] 23 | path = "../concordium-rust-sdk/concordium-base/smart-contracts/contracts-common/concordium-contracts-common" 24 | version = "9.0" 25 | default-features = false 26 | features = ["smart-contract"] 27 | 28 | [features] 29 | default = ["std"] 30 | std = ["concordium-contracts-common/std"] 31 | wasm-test = ["concordium-contracts-common/wasm-test"] 32 | # Own internal wasm-tests leak out to the smart contracts using this library, 33 | # so a separate feature 'internal-wasm-test' is introduced for these. 34 | internal-wasm-test = ["wasm-test", "concordium-quickcheck"] 35 | build-schema = ["concordium-contracts-common/build-schema"] 36 | crypto-primitives = ["sha2", "sha3", "secp256k1", "ed25519-zebra"] 37 | concordium-quickcheck = ["getrandom", "quickcheck", "concordium-contracts-common/concordium-quickcheck", "std"] 38 | debug = [] 39 | bump_alloc = [] 40 | # p7 enables support for functionality introduced in protocol version 7. 41 | p7 = [] 42 | 43 | [lib] 44 | # cdylib is needed below to compile into a wasm module with internal unit tests. 45 | crate-type = ["cdylib", "rlib"] 46 | 47 | [profile.release] 48 | # Tell `rustc` to optimize for small code size. 49 | opt-level = "s" 50 | 51 | [dev-dependencies] 52 | trybuild = "1.0" 53 | # Don't unwind on panics, just trap. 54 | # panic = "abort" 55 | 56 | 57 | 58 | [package.metadata.docs.rs] 59 | # This sets the default target to `wasm32-unknown-unknown` and only builds that 60 | # target on docs.rs. This is useful because the some parts of documentation only 61 | # exist on that platform. 62 | targets = ["wasm32-unknown-unknown"] 63 | -------------------------------------------------------------------------------- /concordium-std/src/constants.rs: -------------------------------------------------------------------------------- 1 | //! Chain constants that impose limits on various aspects of smart contract 2 | //! execution. 3 | 4 | /// Maximum log size. 5 | pub const MAX_LOG_SIZE: usize = 512; 6 | 7 | /// Maximum number of log items. 8 | pub const MAX_NUM_LOGS: usize = 64; 9 | -------------------------------------------------------------------------------- /concordium-std/tests/dbg.rs: -------------------------------------------------------------------------------- 1 | //! Test that the debug macro generates compilable code. 2 | #[test] 3 | fn dbg() { 4 | let t = trybuild::TestCases::new(); 5 | t.pass("tests/dbg/success.rs"); 6 | } 7 | -------------------------------------------------------------------------------- /concordium-std/tests/dbg/success.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `concordium_dbg` generates compilable code. 2 | use concordium_std::*; 3 | 4 | fn f() { 5 | let one: u32 = 3; 6 | let two: Option = Some(3); 7 | concordium_dbg!("Hello {one:?}, {}", two.unwrap()); 8 | concordium_dbg!("Hello {one:?}, {}", two.unwrap(),); 9 | concordium_dbg!(); 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deletable/success-assoc-type.rs: -------------------------------------------------------------------------------- 1 | //! Ensure that `derive(Deletable)` can generate trait implementation 2 | //! when `#[concordium(state_parameter)]` attribute value is not just 3 | //! a type identifier but a type path to trait's associated type 4 | use concordium_std::{Deletable, HasStateApi, StateMap}; 5 | 6 | pub trait ProxyTrait { 7 | type State: HasStateApi; 8 | } 9 | 10 | #[derive(Deletable)] 11 | #[concordium(state_parameter = "T::State")] 12 | pub struct TestDeserial { 13 | pub test_map: StateMap, 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deletable/success-ident-param.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Deletable)` generates code successfully for the simplest 2 | //! case when `#[concordium(state_parameter)]` is just a type identifier 3 | use concordium_std::{Deletable, HasStateApi, StateMap}; 4 | 5 | #[derive(Deletable)] 6 | #[concordium(state_parameter = "S")] 7 | pub struct TestDeserial { 8 | pub test_map: StateMap, 9 | } 10 | 11 | fn main() {} 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-colliding-forward.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(DeserialWithState)` fails when 'forward' attributes are 2 | //! colliding. 3 | use concordium_std::*; 4 | 5 | #[derive(DeserialWithState)] 6 | #[concordium(state_parameter = "S", repr(u8))] 7 | enum Count { 8 | One { 9 | field: StateSet, 10 | }, 11 | #[concordium(forward = [5, 6])] 12 | Two(Inner), 13 | 14 | #[concordium(forward = 5)] 15 | Three(Inner), 16 | } 17 | 18 | #[derive(Deserial)] 19 | #[concordium(repr(u8))] 20 | enum Inner { 21 | #[concordium(tag = 5)] 22 | Alpha { 23 | balance: u32, 24 | }, 25 | #[concordium(tag = 6)] 26 | Beta(u16), 27 | } 28 | 29 | fn main() {} 30 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-colliding-forward.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Three' collides with the tag of 'Two'. 2 | --> tests/derive-deserial-with-state/fail-colliding-forward.rs:14:28 3 | | 4 | 14 | #[concordium(forward = 5)] 5 | | ^ 6 | 7 | error: The tag of 'Two' collides with the tag of 'Three'. 8 | --> tests/derive-deserial-with-state/fail-colliding-forward.rs:11:29 9 | | 10 | 11 | #[concordium(forward = [5, 6])] 11 | | ^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-colliding-tag-forward.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(DeserialWithState)` fails when 'forward' and 'tag' attributes 2 | //! are colliding. 3 | use concordium_std::*; 4 | 5 | #[derive(DeserialWithState)] 6 | #[concordium(state_parameter = "S", repr(u8))] 7 | enum Count { 8 | One { 9 | field: StateSet, 10 | }, 11 | #[concordium(forward = [5, 6])] 12 | Two(Inner), 13 | 14 | #[concordium(tag = 5)] 15 | Three(Inner), 16 | } 17 | 18 | #[derive(Deserial)] 19 | #[concordium(repr(u8))] 20 | enum Inner { 21 | #[concordium(tag = 5)] 22 | Alpha { 23 | balance: u32, 24 | }, 25 | #[concordium(tag = 6)] 26 | Beta(u16), 27 | } 28 | 29 | fn main() {} 30 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-colliding-tag-forward.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Three' collides with the tag of 'Two'. 2 | --> tests/derive-deserial-with-state/fail-colliding-tag-forward.rs:14:18 3 | | 4 | 14 | #[concordium(tag = 5)] 5 | | ^^^ 6 | 7 | error: The tag of 'Two' collides with the tag of 'Three'. 8 | --> tests/derive-deserial-with-state/fail-colliding-tag-forward.rs:11:29 9 | | 10 | 11 | #[concordium(forward = [5, 6])] 11 | | ^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-colliding-tag.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(DeserialWithState)` fails when two 'tag' attributes are 2 | //! colliding. 3 | use concordium_std::*; 4 | 5 | #[derive(DeserialWithState)] 6 | #[concordium(repr(u8))] 7 | #[concordium(state_parameter = "S")] 8 | enum MyTaggedEnum { 9 | #[concordium(tag = 42)] 10 | One(StateMap), 11 | #[concordium(tag = 42)] 12 | Two, 13 | } 14 | 15 | fn main() {} 16 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-colliding-tag.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Two' collides with the tag of 'One'. 2 | --> tests/derive-deserial-with-state/fail-colliding-tag.rs:11:18 3 | | 4 | 11 | #[concordium(tag = 42)] 5 | | ^^^ 6 | 7 | error: The tag of 'One' collides with the tag of 'Two'. 8 | --> tests/derive-deserial-with-state/fail-colliding-tag.rs:9:18 9 | | 10 | 9 | #[concordium(tag = 42)] 11 | | ^^^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-forward-collide-with-inferred.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(DeserialWithState)` fails when a 'forward' attribute collides 2 | //! with the default tag for another variant. 3 | use concordium_std::*; 4 | 5 | #[derive(DeserialWithState)] 6 | #[concordium(state_parameter = "S", repr(u8))] 7 | enum Count { 8 | One { 9 | field: StateSet, 10 | }, 11 | #[concordium(forward = [0, 6])] 12 | Two(Inner), 13 | } 14 | 15 | #[derive(Deserial)] 16 | #[concordium(repr(u8))] 17 | enum Inner { 18 | Alpha { 19 | balance: u32, 20 | }, 21 | #[concordium(tag = 6)] 22 | Beta(u16), 23 | } 24 | 25 | fn main() {} 26 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-forward-collide-with-inferred.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Two' collides with the tag of 'One'. 2 | --> tests/derive-deserial-with-state/fail-forward-collide-with-inferred.rs:11:29 3 | | 4 | 11 | #[concordium(forward = [0, 6])] 5 | | ^ 6 | 7 | error: The tag of 'One' collides with the tag of 'Two'. 8 | --> tests/derive-deserial-with-state/fail-forward-collide-with-inferred.rs:8:5 9 | | 10 | 8 | One { 11 | | ^^^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-forward-gt-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(DeserialWithState)` fails when a 'forward' attribute is 2 | //! greater than what 'repr(u8)' can represent. 3 | use concordium_std::*; 4 | 5 | #[derive(DeserialWithState)] 6 | #[concordium(state_parameter = "S", repr(u8))] 7 | enum Count { 8 | One { 9 | field: StateSet, 10 | }, 11 | #[concordium(forward = [500, 6])] 12 | Two(Inner), 13 | } 14 | 15 | #[derive(Deserial)] 16 | #[concordium(repr(u16))] 17 | enum Inner { 18 | #[concordium(tag = 500)] 19 | Alpha { 20 | balance: u32, 21 | }, 22 | #[concordium(tag = 6)] 23 | Beta(u16), 24 | } 25 | 26 | fn main() {} 27 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-forward-gt-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'forward' attribute tag value of 500 cannot be represented by the type u8 set in 'repr(u8)' 2 | --> tests/derive-deserial-with-state/fail-forward-gt-repr.rs:11:29 3 | | 4 | 11 | #[concordium(forward = [500, 6])] 5 | | ^^^ 6 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-forward-without-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(DeserialWithState)` fails when using 'forward' attribute 2 | //! without a 'repr' attribute. 3 | use concordium_std::*; 4 | 5 | #[derive(DeserialWithState)] 6 | #[concordium(state_parameter = "S")] 7 | enum Count { 8 | One { 9 | field: StateSet, 10 | }, 11 | #[concordium(forward = [5, 6])] 12 | Two(Inner), 13 | } 14 | 15 | #[derive(Deserial)] 16 | #[concordium(repr(u8))] 17 | enum Inner { 18 | #[concordium(tag = 5)] 19 | Alpha { 20 | balance: u32, 21 | }, 22 | #[concordium(tag = 6)] 23 | Beta(u16), 24 | } 25 | 26 | fn main() {} 27 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-forward-without-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'repr(..)' attribute must be set on the type when using 'forward' attribute 2 | --> tests/derive-deserial-with-state/fail-forward-without-repr.rs:5:10 3 | | 4 | 5 | #[derive(DeserialWithState)] 5 | | ^^^^^^^^^^^^^^^^^ 6 | | 7 | = note: this error originates in the derive macro `DeserialWithState` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-tag-collide-with-inferred.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(DeserialWithState)` fails when 'tag' attribute are collides 2 | //! with the default tag for another variant. 3 | use concordium_std::*; 4 | 5 | #[derive(DeserialWithState)] 6 | #[concordium(repr(u8))] 7 | #[concordium(state_parameter = "S")] 8 | enum MyTaggedEnum { 9 | One(StateSet), 10 | #[concordium(tag = 0)] 11 | Two, 12 | } 13 | 14 | fn main() {} 15 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-tag-collide-with-inferred.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Two' collides with the tag of 'One'. 2 | --> tests/derive-deserial-with-state/fail-tag-collide-with-inferred.rs:10:18 3 | | 4 | 10 | #[concordium(tag = 0)] 5 | | ^^^ 6 | 7 | error: The tag of 'One' collides with the tag of 'Two'. 8 | --> tests/derive-deserial-with-state/fail-tag-collide-with-inferred.rs:9:5 9 | | 10 | 9 | One(StateSet), 11 | | ^^^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-tag-gt-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(DeserialWithState)` fails when a 'tag' attribute is greater 2 | //! than what 'repr(u8)' can represent. 3 | use concordium_std::*; 4 | 5 | #[derive(DeserialWithState)] 6 | #[concordium(repr(u8))] 7 | #[concordium(state_parameter = "S")] 8 | enum MyTaggedEnum { 9 | #[concordium(tag = 256)] 10 | One(StateSet), 11 | Two, 12 | } 13 | 14 | fn main() {} 15 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-tag-gt-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'tag' attribute value of 256 cannot be represented by the type u8 set in 'repr(u8)' 2 | --> tests/derive-deserial-with-state/fail-tag-gt-repr.rs:9:18 3 | | 4 | 9 | #[concordium(tag = 256)] 5 | | ^^^ 6 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-tag-without-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(DeserialWithState)` fails when using 'tag' attribute without 2 | //! a 'repr' attribute. 3 | use concordium_std::*; 4 | 5 | #[derive(DeserialWithState)] 6 | #[concordium(state_parameter = "S")] 7 | enum MyTaggedEnum { 8 | #[concordium(tag = 42)] 9 | One(StateSet), 10 | Two, 11 | } 12 | 13 | fn main() {} 14 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/fail-tag-without-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'repr(..)' attribute must be set on the type when using 'tag' attribute 2 | --> tests/derive-deserial-with-state/fail-tag-without-repr.rs:5:10 3 | | 4 | 5 | #[derive(DeserialWithState)] 5 | | ^^^^^^^^^^^^^^^^^ 6 | | 7 | = note: this error originates in the derive macro `DeserialWithState` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/success-assoc-type.rs: -------------------------------------------------------------------------------- 1 | //! Ensure that `derive(DeserialWithState)` can generate trait implementation 2 | //! when `#[concordium(state_parameter)]` attribute value is not just 3 | //! a type identifier but a type path to trait's associated type 4 | use concordium_std::{DeserialWithState, HasStateApi, StateMap}; 5 | 6 | pub trait ProxyTrait { 7 | type State: HasStateApi; 8 | } 9 | 10 | #[derive(DeserialWithState)] 11 | #[concordium(state_parameter = "T::State")] 12 | pub struct TestDeserial { 13 | pub test_map: StateMap, 14 | } 15 | 16 | fn main() {} 17 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/success-generics.rs: -------------------------------------------------------------------------------- 1 | //! Ensure that `derive(DeserialWithState)` can generate a trait implementation 2 | //! when `#[concordium(state_parameter)]` attribute value is not just 3 | //! a type identifier but a type path to the trait's associated type. 4 | use concordium_std::*; 5 | 6 | #[derive(DeserialWithState)] 7 | #[concordium(state_parameter = "T")] 8 | struct State1 { 9 | map: StateMap, 10 | other: A, 11 | } 12 | 13 | #[derive(DeserialWithState)] 14 | #[concordium(state_parameter = "S")] 15 | struct WithStateParameterWhere 16 | where 17 | S: HasStateApi, 18 | S: Clone, { 19 | test_map: StateMap, 20 | } 21 | 22 | #[rustfmt::skip] // maintain lack of trailing comma, and empty where clause 23 | mod inner { 24 | use super::*; 25 | #[derive(DeserialWithState)] 26 | #[concordium(state_parameter = "S")] 27 | struct WithStateParameterWhereTwo 28 | where 29 | S: HasStateApi, 30 | S: Clone { // no trailing comma 31 | test_map: StateMap, 32 | } 33 | 34 | #[derive(DeserialWithState)] 35 | #[concordium(state_parameter = "S")] 36 | struct WithStateParameterWhereThree 37 | where //empty where clause 38 | { 39 | test: S, 40 | } 41 | } 42 | 43 | trait ProxyTrait { 44 | type State: HasStateApi; 45 | } 46 | 47 | #[derive(DeserialWithState)] 48 | #[concordium(state_parameter = "T::State")] 49 | struct State2 { 50 | test_map: StateMap, 51 | field: A, 52 | } 53 | 54 | fn main() {} 55 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial-with-state/success-ident-param.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(DeserialWithState)` generates code successfully for the 2 | //! simplest case when `#[concordium(state_parameter)]` is just a type 3 | //! identifier 4 | use concordium_std::{DeserialWithState, HasStateApi, StateMap}; 5 | 6 | #[derive(DeserialWithState)] 7 | #[concordium(state_parameter = "S")] 8 | pub struct TestDeserial { 9 | pub test_map: StateMap, 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-colliding-forward.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Deserial)` fails when 'forward' attributes are colliding. 2 | use concordium_std::*; 3 | 4 | #[derive(Deserial)] 5 | #[concordium(repr(u8))] 6 | enum Count { 7 | One { 8 | field: u32, 9 | }, 10 | #[concordium(forward = [5, 6])] 11 | Two(Inner), 12 | 13 | #[concordium(forward = 5)] 14 | Three(Inner), 15 | } 16 | 17 | #[derive(Deserial)] 18 | #[concordium(repr(u8))] 19 | enum Inner { 20 | #[concordium(tag = 5)] 21 | Alpha { 22 | balance: u32, 23 | }, 24 | #[concordium(tag = 6)] 25 | Beta(u16), 26 | } 27 | 28 | fn main() {} 29 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-colliding-forward.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Three' collides with the tag of 'Two'. 2 | --> tests/derive-deserial/fail-colliding-forward.rs:13:28 3 | | 4 | 13 | #[concordium(forward = 5)] 5 | | ^ 6 | 7 | error: The tag of 'Two' collides with the tag of 'Three'. 8 | --> tests/derive-deserial/fail-colliding-forward.rs:10:29 9 | | 10 | 10 | #[concordium(forward = [5, 6])] 11 | | ^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-colliding-tag-forward.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Deserial)` fails when 'forward' and 'tag' attributes are 2 | //! colliding. 3 | use concordium_std::*; 4 | 5 | #[derive(Deserial)] 6 | #[concordium(repr(u8))] 7 | enum Count { 8 | One { 9 | field: u32, 10 | }, 11 | #[concordium(forward = [5, 6])] 12 | Two(Inner), 13 | 14 | #[concordium(tag = 5)] 15 | Three(Inner), 16 | } 17 | 18 | #[derive(Deserial)] 19 | #[concordium(repr(u8))] 20 | enum Inner { 21 | #[concordium(tag = 5)] 22 | Alpha { 23 | balance: u32, 24 | }, 25 | #[concordium(tag = 6)] 26 | Beta(u16), 27 | } 28 | 29 | fn main() {} 30 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-colliding-tag-forward.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Three' collides with the tag of 'Two'. 2 | --> tests/derive-deserial/fail-colliding-tag-forward.rs:14:18 3 | | 4 | 14 | #[concordium(tag = 5)] 5 | | ^^^ 6 | 7 | error: The tag of 'Two' collides with the tag of 'Three'. 8 | --> tests/derive-deserial/fail-colliding-tag-forward.rs:11:29 9 | | 10 | 11 | #[concordium(forward = [5, 6])] 11 | | ^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-colliding-tag.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Deserial)` fails when two 'tag' attributes are colliding. 2 | use concordium_std::*; 3 | 4 | #[derive(Deserial)] 5 | #[concordium(repr(u8))] 6 | enum MyTaggedEnum { 7 | #[concordium(tag = 42)] 8 | One, 9 | #[concordium(tag = 42)] 10 | Two, 11 | } 12 | 13 | fn main() {} 14 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-colliding-tag.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Two' collides with the tag of 'One'. 2 | --> tests/derive-deserial/fail-colliding-tag.rs:9:18 3 | | 4 | 9 | #[concordium(tag = 42)] 5 | | ^^^ 6 | 7 | error: The tag of 'One' collides with the tag of 'Two'. 8 | --> tests/derive-deserial/fail-colliding-tag.rs:7:18 9 | | 10 | 7 | #[concordium(tag = 42)] 11 | | ^^^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-forward-collide-with-inferred.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Deserial)` fails when a 'forward' attribute collides with the 2 | //! default tag for another variant. 3 | use concordium_std::*; 4 | 5 | #[derive(Deserial)] 6 | #[concordium(repr(u8))] 7 | enum Count { 8 | One { 9 | field: u32, 10 | }, 11 | #[concordium(forward = [0, 6])] 12 | Two(Inner), 13 | } 14 | 15 | #[derive(Deserial)] 16 | #[concordium(repr(u8))] 17 | enum Inner { 18 | Alpha { 19 | balance: u32, 20 | }, 21 | #[concordium(tag = 6)] 22 | Beta(u16), 23 | } 24 | 25 | fn main() {} 26 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-forward-collide-with-inferred.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Two' collides with the tag of 'One'. 2 | --> tests/derive-deserial/fail-forward-collide-with-inferred.rs:11:29 3 | | 4 | 11 | #[concordium(forward = [0, 6])] 5 | | ^ 6 | 7 | error: The tag of 'One' collides with the tag of 'Two'. 8 | --> tests/derive-deserial/fail-forward-collide-with-inferred.rs:8:5 9 | | 10 | 8 | One { 11 | | ^^^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-forward-gt-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Deserial)` fails when a 'forward' attribute is greater than 2 | //! what 'repr(u8)' can represent. 3 | use concordium_std::*; 4 | 5 | #[derive(Deserial)] 6 | #[concordium(repr(u8))] 7 | enum Count { 8 | One { 9 | field: u32, 10 | }, 11 | #[concordium(forward = [500, 6])] 12 | Two(Inner), 13 | } 14 | 15 | #[derive(Deserial)] 16 | #[concordium(repr(u16))] 17 | enum Inner { 18 | #[concordium(tag = 500)] 19 | Alpha { 20 | balance: u32, 21 | }, 22 | #[concordium(tag = 6)] 23 | Beta(u16), 24 | } 25 | 26 | fn main() {} 27 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-forward-gt-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'forward' attribute tag value of 500 cannot be represented by the type u8 set in 'repr(u8)' 2 | --> tests/derive-deserial/fail-forward-gt-repr.rs:11:29 3 | | 4 | 11 | #[concordium(forward = [500, 6])] 5 | | ^^^ 6 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-forward-without-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Deserial)` fails when using 'forward' attribute without a 2 | //! 'repr' attribute. 3 | use concordium_std::*; 4 | 5 | #[derive(Deserial)] 6 | enum Count { 7 | One { 8 | field: u32, 9 | }, 10 | #[concordium(forward = [5, 6])] 11 | Two(Inner), 12 | } 13 | 14 | #[derive(Deserial)] 15 | #[concordium(repr(u8))] 16 | enum Inner { 17 | #[concordium(tag = 5)] 18 | Alpha { 19 | balance: u32, 20 | }, 21 | #[concordium(tag = 6)] 22 | Beta(u16), 23 | } 24 | 25 | fn main() {} 26 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-forward-without-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'repr(..)' attribute must be set on the type when using 'forward' attribute 2 | --> tests/derive-deserial/fail-forward-without-repr.rs:5:10 3 | | 4 | 5 | #[derive(Deserial)] 5 | | ^^^^^^^^ 6 | | 7 | = note: this error originates in the derive macro `Deserial` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-tag-collide-with-inferred.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Deserial)` fails when a 'tag' attribute collides with the 2 | //! default tag for another variant. 3 | use concordium_std::*; 4 | 5 | #[derive(Deserial)] 6 | #[concordium(repr(u8))] 7 | enum MyTaggedEnum { 8 | One, 9 | #[concordium(tag = 0)] 10 | Two, 11 | } 12 | 13 | fn main() {} 14 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-tag-collide-with-inferred.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Two' collides with the tag of 'One'. 2 | --> tests/derive-deserial/fail-tag-collide-with-inferred.rs:9:18 3 | | 4 | 9 | #[concordium(tag = 0)] 5 | | ^^^ 6 | 7 | error: The tag of 'One' collides with the tag of 'Two'. 8 | --> tests/derive-deserial/fail-tag-collide-with-inferred.rs:8:5 9 | | 10 | 8 | One, 11 | | ^^^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-tag-gt-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Deserial)` fails when a 'tag' attribute is greater than what 2 | //! 'repr(u8)' can represent. 3 | use concordium_std::*; 4 | 5 | #[derive(Deserial)] 6 | #[concordium(repr(u8))] 7 | enum MyTaggedEnum { 8 | #[concordium(tag = 256)] 9 | One, 10 | Two, 11 | } 12 | 13 | fn main() {} 14 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-tag-gt-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'tag' attribute value of 256 cannot be represented by the type u8 set in 'repr(u8)' 2 | --> tests/derive-deserial/fail-tag-gt-repr.rs:8:18 3 | | 4 | 8 | #[concordium(tag = 256)] 5 | | ^^^ 6 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-tag-without-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Deserial)` fails when using 'tag' attribute without a 2 | //! 'repr' attribute. 3 | use concordium_std::*; 4 | 5 | #[derive(Deserial)] 6 | enum MyTaggedEnum { 7 | #[concordium(tag = 42)] 8 | One, 9 | Two, 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/fail-tag-without-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'repr(..)' attribute must be set on the type when using 'tag' attribute 2 | --> tests/derive-deserial/fail-tag-without-repr.rs:5:10 3 | | 4 | 5 | #[derive(Deserial)] 5 | | ^^^^^^^^ 6 | | 7 | = note: this error originates in the derive macro `Deserial` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/success-attributes.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Deserial)` generates code successfully for types using 2 | //! attributes. 3 | use concordium_std::*; 4 | 5 | #[derive(Debug, Deserial, PartialEq, Eq)] 6 | #[concordium(repr(u8))] 7 | enum MyTaggedEnum { 8 | #[concordium(tag = 42)] 9 | One(u8), 10 | Two(u8), 11 | } 12 | 13 | #[derive(Debug, Deserial, PartialEq, Eq)] 14 | #[concordium(repr(u16))] 15 | enum MyTaggedEnumU16 { 16 | #[concordium(tag = 42)] 17 | One(u8), 18 | Two(u8), 19 | } 20 | 21 | fn main() { 22 | { 23 | let bytes = [42u8, 3]; 24 | let value: MyTaggedEnum = from_bytes(&bytes).expect("Deserialize MyTaggedEnum"); 25 | assert_eq!(MyTaggedEnum::One(3), value); 26 | } 27 | { 28 | let bytes = [1u8, 255]; 29 | let value: MyTaggedEnum = from_bytes(&bytes).expect("Deserialize MyTaggedEnum"); 30 | assert_eq!(MyTaggedEnum::Two(255), value); 31 | } 32 | { 33 | let bytes = [42u8, 0, 3]; 34 | let value: MyTaggedEnumU16 = from_bytes(&bytes).expect("Deserialize MyTaggedEnumU16"); 35 | assert_eq!(MyTaggedEnumU16::One(3), value); 36 | } 37 | { 38 | let bytes = [1u8, 0, 255]; 39 | let value: MyTaggedEnumU16 = from_bytes(&bytes).expect("Deserialize MyTaggedEnumU16"); 40 | assert_eq!(MyTaggedEnumU16::Two(255), value); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/success-forward-attribute.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Deserial)` generates code successfully for types using 2 | //! attributes. 3 | use concordium_std::*; 4 | 5 | #[derive(Debug, Deserial, PartialEq, Eq)] 6 | #[concordium(repr(u8))] 7 | enum Count { 8 | One { 9 | field: u32, 10 | }, 11 | #[concordium(forward = [5, 6])] 12 | Two(Inner), 13 | } 14 | 15 | #[derive(Debug, Deserial, PartialEq, Eq)] 16 | #[concordium(repr(u8))] 17 | enum Inner { 18 | #[concordium(tag = 5)] 19 | Alpha { 20 | balance: u32, 21 | }, 22 | #[concordium(tag = 6)] 23 | Beta(u16), 24 | } 25 | 26 | // Example using predefined forwarded tags. 27 | 28 | #[derive(Debug, Deserial, PartialEq, Eq)] 29 | #[concordium(repr(u8))] 30 | enum Event { 31 | A { 32 | field: u32, 33 | }, 34 | #[concordium(forward = cis2_events)] 35 | B(Cis2Event), 36 | } 37 | 38 | #[derive(Debug, Deserial, PartialEq, Eq)] 39 | #[concordium(repr(u8))] 40 | enum Cis2Event { 41 | #[concordium(tag = 255)] 42 | Transfer, 43 | #[concordium(tag = 254)] 44 | Mint, 45 | #[concordium(tag = 253)] 46 | Burn, 47 | #[concordium(tag = 252)] 48 | UpdateOperator, 49 | #[concordium(tag = 251)] 50 | TokenMetadata, 51 | } 52 | 53 | fn main() { 54 | { 55 | let bytes = [0, 42, 0, 0, 0]; 56 | let value: Count = from_bytes(&bytes).unwrap(); 57 | assert_eq!( 58 | Count::One { 59 | field: 42, 60 | }, 61 | value 62 | ); 63 | } 64 | 65 | { 66 | let bytes = [5, 50, 0, 0, 0]; 67 | let value: Count = from_bytes(&bytes).unwrap(); 68 | assert_eq!( 69 | Count::Two(Inner::Alpha { 70 | balance: 50, 71 | }), 72 | value 73 | ); 74 | } 75 | 76 | { 77 | let bytes = [6, 8, 0]; 78 | let value: Count = from_bytes(&bytes).unwrap(); 79 | assert_eq!(Count::Two(Inner::Beta(8)), value); 80 | } 81 | 82 | { 83 | let bytes = [254]; 84 | let value: Event = from_bytes(&bytes).unwrap(); 85 | assert_eq!(Event::B(Cis2Event::Mint), value); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/success-generics.rs: -------------------------------------------------------------------------------- 1 | /// Test ensuring derivation works for types with type parameters. 2 | use concordium_std::*; 3 | 4 | #[derive(Deserial)] 5 | struct MyStruct { 6 | field: A, 7 | other_field: u8, 8 | } 9 | 10 | #[derive(Deserial)] 11 | struct MyOtherStruct { 12 | field: A, 13 | other_field: B, 14 | } 15 | 16 | #[derive(Deserial)] 17 | enum MyEnum { 18 | One(u32), 19 | Two(A), 20 | } 21 | 22 | #[derive(Deserial)] 23 | enum MyOtherEnum { 24 | One(u32), 25 | Two(A, B), 26 | } 27 | 28 | #[derive(Deserial)] 29 | struct WithStateParameterWhere 30 | where 31 | S: Clone, 32 | S: PartialOrd, { 33 | value: S, 34 | } 35 | 36 | #[rustfmt::skip] // skip formatting to maintain lack of trailing comma 37 | mod inner { 38 | use super::*; 39 | #[derive(Deserial)] 40 | struct WithStateParameterWhereTwo 41 | where 42 | S: Clone, 43 | // note the lack of comma compared to the test above 44 | S: PartialOrd { 45 | value: S, 46 | } 47 | 48 | #[derive(Deserial)] 49 | struct WithStateParameterWhereThree 50 | where // empty where clause 51 | { 52 | value: S, 53 | } 54 | } 55 | 56 | 57 | #[derive(Deserial)] 58 | #[concordium(bound(deserial = ""))] 59 | struct ExplicitBound { 60 | field: marker::PhantomData, 61 | } 62 | struct NotImplemtingDeserial; 63 | 64 | fn main() { 65 | { 66 | let bytes = [0u8; 9]; 67 | let _value: MyStruct = from_bytes(&bytes).expect("Deserialize MyStruct"); 68 | } 69 | { 70 | let bytes = [0u8; 9]; 71 | let _value: MyOtherStruct = from_bytes(&bytes).expect("Deserialize MyOtherStruct"); 72 | } 73 | { 74 | let bytes = [1u8; 9]; 75 | let _value: MyEnum = from_bytes(&bytes).expect("Deserialize MyOtherStruct"); 76 | } 77 | { 78 | let bytes = [1u8; 10]; 79 | let _value: MyOtherEnum = from_bytes(&bytes).expect("Deserialize MyOtherStruct"); 80 | } 81 | { 82 | let bytes = [0u8; 0]; 83 | let _value: ExplicitBound = 84 | from_bytes(&bytes).expect("Deserialize ExplicitBound"); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-deserial/success-simple.rs: -------------------------------------------------------------------------------- 1 | /// Test ensuring derivation works for simple types. 2 | use concordium_std::*; 3 | 4 | #[derive(Deserial)] 5 | struct MyStruct { 6 | field: u64, // 8 bytes 7 | other_field: u8, // 1 byte 8 | } 9 | 10 | #[derive(Deserial)] 11 | enum MyEnum { 12 | One(u64), 13 | Two(u16), 14 | } 15 | 16 | fn main() { 17 | { 18 | let bytes = [0u8; 9]; 19 | let _value: MyStruct = from_bytes(&bytes).expect("Deserialize MyStruct"); 20 | } 21 | { 22 | let bytes = [0u8; 9]; 23 | let _value: MyEnum = from_bytes(&bytes).expect("Deserialize MyEnum"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-colliding-forward.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(SchemaType)` fails when 'forward' attributes are colliding. 2 | use concordium_std::*; 3 | 4 | #[derive(SchemaType)] 5 | #[concordium(repr(u8))] 6 | enum Count { 7 | One { 8 | field: u32, 9 | }, 10 | #[concordium(forward = [5, 6])] 11 | Two(Inner), 12 | 13 | #[concordium(forward = 5)] 14 | Three(Inner), 15 | } 16 | 17 | #[derive(SchemaType)] 18 | #[concordium(repr(u8))] 19 | enum Inner { 20 | #[concordium(tag = 5)] 21 | Alpha { 22 | balance: u32, 23 | }, 24 | #[concordium(tag = 6)] 25 | Beta(u16), 26 | } 27 | 28 | fn main() {} 29 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-colliding-forward.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Three' collides with the tag of 'Two'. 2 | --> tests/derive-schema-type/fail-colliding-forward.rs:13:28 3 | | 4 | 13 | #[concordium(forward = 5)] 5 | | ^ 6 | 7 | error: The tag of 'Two' collides with the tag of 'Three'. 8 | --> tests/derive-schema-type/fail-colliding-forward.rs:10:29 9 | | 10 | 10 | #[concordium(forward = [5, 6])] 11 | | ^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-colliding-tag-forward.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(SchemaType)` fails when 'forward' and 'tag' attributes are 2 | //! colliding. 3 | use concordium_std::*; 4 | 5 | #[derive(SchemaType)] 6 | #[concordium(repr(u8))] 7 | enum Count { 8 | One { 9 | field: u32, 10 | }, 11 | #[concordium(forward = [5, 6])] 12 | Two(Inner), 13 | 14 | #[concordium(tag = 5)] 15 | Three(Inner), 16 | } 17 | 18 | #[derive(SchemaType)] 19 | #[concordium(repr(u8))] 20 | enum Inner { 21 | #[concordium(tag = 5)] 22 | Alpha { 23 | balance: u32, 24 | }, 25 | #[concordium(tag = 6)] 26 | Beta(u16), 27 | } 28 | 29 | fn main() {} 30 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-colliding-tag-forward.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Three' collides with the tag of 'Two'. 2 | --> tests/derive-schema-type/fail-colliding-tag-forward.rs:14:18 3 | | 4 | 14 | #[concordium(tag = 5)] 5 | | ^^^ 6 | 7 | error: The tag of 'Two' collides with the tag of 'Three'. 8 | --> tests/derive-schema-type/fail-colliding-tag-forward.rs:11:29 9 | | 10 | 11 | #[concordium(forward = [5, 6])] 11 | | ^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-colliding-tag.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(SchemaType)` fails when two 'tag' attributes are colliding. 2 | use concordium_std::*; 3 | 4 | #[derive(SchemaType)] 5 | #[concordium(repr(u8))] 6 | enum MyTaggedEnum { 7 | #[concordium(tag = 42)] 8 | One, 9 | #[concordium(tag = 42)] 10 | Two, 11 | } 12 | 13 | fn main() {} 14 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-colliding-tag.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Two' collides with the tag of 'One'. 2 | --> tests/derive-schema-type/fail-colliding-tag.rs:9:18 3 | | 4 | 9 | #[concordium(tag = 42)] 5 | | ^^^ 6 | 7 | error: The tag of 'One' collides with the tag of 'Two'. 8 | --> tests/derive-schema-type/fail-colliding-tag.rs:7:18 9 | | 10 | 7 | #[concordium(tag = 42)] 11 | | ^^^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-forward-collide-with-inferred.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(SchemaType)` fails when a 'forward' attribute collides with 2 | //! the default tag for another variant. 3 | use concordium_std::*; 4 | 5 | #[derive(SchemaType)] 6 | #[concordium(repr(u8))] 7 | enum Count { 8 | One { 9 | field: u32, 10 | }, 11 | #[concordium(forward = [0, 6])] 12 | Two(Inner), 13 | } 14 | 15 | #[derive(SchemaType)] 16 | #[concordium(repr(u8))] 17 | enum Inner { 18 | Alpha { 19 | balance: u32, 20 | }, 21 | #[concordium(tag = 6)] 22 | Beta(u16), 23 | } 24 | 25 | fn main() {} 26 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-forward-collide-with-inferred.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Two' collides with the tag of 'One'. 2 | --> tests/derive-schema-type/fail-forward-collide-with-inferred.rs:11:29 3 | | 4 | 11 | #[concordium(forward = [0, 6])] 5 | | ^ 6 | 7 | error: The tag of 'One' collides with the tag of 'Two'. 8 | --> tests/derive-schema-type/fail-forward-collide-with-inferred.rs:8:5 9 | | 10 | 8 | One { 11 | | ^^^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-forward-gt-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(SchemaType)` fails when a 'forward' attribute is greater than 2 | //! what 'repr(u8)' can represent. 3 | use concordium_std::*; 4 | 5 | #[derive(SchemaType)] 6 | #[concordium(repr(u8))] 7 | enum Count { 8 | One { 9 | field: u32, 10 | }, 11 | #[concordium(forward = [500, 6])] 12 | Two(Inner), 13 | } 14 | 15 | #[derive(SchemaType)] 16 | #[concordium(repr(u8))] 17 | enum Inner { 18 | #[concordium(tag = 5)] 19 | Alpha { 20 | balance: u32, 21 | }, 22 | #[concordium(tag = 6)] 23 | Beta(u16), 24 | } 25 | 26 | fn main() {} 27 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-forward-gt-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'forward' attribute tag value of 500 cannot be represented by the type u8 set in 'repr(u8)' 2 | --> tests/derive-schema-type/fail-forward-gt-repr.rs:11:29 3 | | 4 | 11 | #[concordium(forward = [500, 6])] 5 | | ^^^ 6 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-forward-without-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(SchemaType)` fails when using 'forward' attribute without a 2 | //! 'repr' attribute. 3 | use concordium_std::*; 4 | 5 | #[derive(SchemaType)] 6 | enum Count { 7 | One { 8 | field: u32, 9 | }, 10 | #[concordium(forward = [5, 6])] 11 | Two(Inner), 12 | } 13 | 14 | #[derive(SchemaType)] 15 | #[concordium(repr(u8))] 16 | enum Inner { 17 | #[concordium(tag = 5)] 18 | Alpha { 19 | balance: u32, 20 | }, 21 | #[concordium(tag = 6)] 22 | Beta(u16), 23 | } 24 | 25 | fn main() {} 26 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-forward-without-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'repr(..)' attribute must be set on the type when using 'forward' attribute 2 | --> tests/derive-schema-type/fail-forward-without-repr.rs:5:10 3 | | 4 | 5 | #[derive(SchemaType)] 5 | | ^^^^^^^^^^ 6 | | 7 | = note: this error originates in the derive macro `SchemaType` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-tag-collide-with-inferred.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(SchemaType)` fails when a 'tag' attribute collides with the 2 | //! default tag for another variant. 3 | use concordium_std::*; 4 | 5 | #[derive(SchemaType)] 6 | #[concordium(repr(u8))] 7 | enum MyTaggedEnum { 8 | One, 9 | #[concordium(tag = 0)] 10 | Two, 11 | } 12 | 13 | fn main() {} 14 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-tag-collide-with-inferred.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Two' collides with the tag of 'One'. 2 | --> tests/derive-schema-type/fail-tag-collide-with-inferred.rs:9:18 3 | | 4 | 9 | #[concordium(tag = 0)] 5 | | ^^^ 6 | 7 | error: The tag of 'One' collides with the tag of 'Two'. 8 | --> tests/derive-schema-type/fail-tag-collide-with-inferred.rs:8:5 9 | | 10 | 8 | One, 11 | | ^^^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-tag-gt-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(SchemaType)` fails when a 'tag' attribute is greater than 2 | //! what 'repr(u8)' can represent. 3 | use concordium_std::*; 4 | 5 | #[derive(SchemaType)] 6 | #[concordium(repr(u8))] 7 | enum MyTaggedEnum { 8 | #[concordium(tag = 256)] 9 | One, 10 | Two, 11 | } 12 | 13 | fn main() {} 14 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-tag-gt-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'tag' attribute value of 256 cannot be represented by the type u8 set in 'repr(u8)' 2 | --> tests/derive-schema-type/fail-tag-gt-repr.rs:8:18 3 | | 4 | 8 | #[concordium(tag = 256)] 5 | | ^^^ 6 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-tag-without-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(SchemaType)` fails when using 'tag' attribute without a 2 | //! 'repr' attribute. 3 | use concordium_std::*; 4 | 5 | #[derive(SchemaType)] 6 | enum MyTaggedEnum { 7 | #[concordium(tag = 42)] 8 | One, 9 | Two, 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/fail-tag-without-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'repr(..)' attribute must be set on the type when using 'tag' attribute 2 | --> tests/derive-schema-type/fail-tag-without-repr.rs:5:10 3 | | 4 | 5 | #[derive(SchemaType)] 5 | | ^^^^^^^^^^ 6 | | 7 | = note: this error originates in the derive macro `SchemaType` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/success-attributes.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(SchemaType)` generates code successfully for types using 2 | //! attributes. 3 | use concordium_std::*; 4 | 5 | #[derive(SchemaType)] 6 | #[concordium(repr(u8))] 7 | enum MyTaggedEnum { 8 | #[concordium(tag = 42)] 9 | One, 10 | Two, 11 | } 12 | 13 | #[derive(SchemaType)] 14 | enum MyUntaggedEnum { 15 | One, 16 | Two, 17 | } 18 | 19 | fn main() { 20 | { 21 | let schema_type = ::get_type(); 22 | assert_eq!( 23 | schema_type, 24 | schema::Type::TaggedEnum(collections::BTreeMap::from([ 25 | (42, (String::from("One"), schema::Fields::None)), 26 | (1, (String::from("Two"), schema::Fields::None)) 27 | ])) 28 | ); 29 | } 30 | 31 | { 32 | let schema_type = ::get_type(); 33 | assert_eq!( 34 | schema_type, 35 | schema::Type::Enum(vec![ 36 | (String::from("One"), schema::Fields::None), 37 | (String::from("Two"), schema::Fields::None) 38 | ]) 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/success-forward-attribute.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(SchemaType)` generates code successfully for types using 2 | //! attributes. 3 | use concordium_std::*; 4 | 5 | #[derive(SchemaType)] 6 | #[concordium(repr(u8))] 7 | enum Count { 8 | One, 9 | #[concordium(forward = [5, 6])] 10 | Two(Inner), 11 | } 12 | 13 | #[derive(SchemaType)] 14 | #[concordium(repr(u8))] 15 | enum Inner { 16 | #[concordium(tag = 5)] 17 | Alpha, 18 | #[concordium(tag = 6)] 19 | Beta(u8), 20 | } 21 | 22 | // Example using predefined forwarded tags. 23 | 24 | #[derive(SchemaType)] 25 | #[concordium(repr(u8))] 26 | enum Event { 27 | A { 28 | field: u32, 29 | }, 30 | #[concordium(forward = cis2_events)] 31 | B(Cis2Event), 32 | } 33 | 34 | #[derive(SchemaType)] 35 | #[concordium(repr(u8))] 36 | enum Cis2Event { 37 | #[concordium(tag = 255)] 38 | Transfer, 39 | #[concordium(tag = 254)] 40 | Mint, 41 | #[concordium(tag = 253)] 42 | Burn, 43 | #[concordium(tag = 252)] 44 | UpdateOperator, 45 | #[concordium(tag = 251)] 46 | TokenMetadata, 47 | } 48 | 49 | fn main() { 50 | { 51 | let schema_type = ::get_type(); 52 | assert_eq!( 53 | schema_type, 54 | schema::Type::TaggedEnum(collections::BTreeMap::from([ 55 | (0, (String::from("One"), schema::Fields::None)), 56 | (5, (String::from("Alpha"), schema::Fields::None)), 57 | (6, (String::from("Beta"), schema::Fields::Unnamed(vec![schema::Type::U8]))) 58 | ])) 59 | ); 60 | } 61 | 62 | { 63 | let schema_type = ::get_type(); 64 | assert_eq!( 65 | schema_type, 66 | schema::Type::TaggedEnum(collections::BTreeMap::from([ 67 | ( 68 | 0, 69 | ( 70 | String::from("A"), 71 | schema::Fields::Named(vec![(String::from("field"), schema::Type::U32)]) 72 | ) 73 | ), 74 | (255, (String::from("Transfer"), schema::Fields::None)), 75 | (254, (String::from("Mint"), schema::Fields::None)), 76 | (253, (String::from("Burn"), schema::Fields::None)), 77 | (252, (String::from("UpdateOperator"), schema::Fields::None)), 78 | (251, (String::from("TokenMetadata"), schema::Fields::None)) 79 | ])) 80 | ); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/success-generics.rs: -------------------------------------------------------------------------------- 1 | /// Test ensuring derivation works for types with type parameters. 2 | use concordium_std::*; 3 | 4 | #[derive(SchemaType)] 5 | struct MyStruct { 6 | field: A, 7 | other_field: u8, 8 | } 9 | 10 | #[derive(SchemaType)] 11 | struct MyOtherStruct { 12 | field: A, 13 | other_field: B, 14 | } 15 | 16 | #[derive(SchemaType)] 17 | enum MyEnum { 18 | One(u32), 19 | Two(A), 20 | } 21 | 22 | #[derive(SchemaType)] 23 | enum MyOtherEnum { 24 | One(u32), 25 | Two(A, B), 26 | } 27 | 28 | fn main() { 29 | let _type = as schema::SchemaType>::get_type(); 30 | let _type = as schema::SchemaType>::get_type(); 31 | let _type = as schema::SchemaType>::get_type(); 32 | let _type = as schema::SchemaType>::get_type(); 33 | } 34 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/success-simple.rs: -------------------------------------------------------------------------------- 1 | /// Test ensuring derivation works for simple types. 2 | use concordium_std::*; 3 | 4 | #[derive(SchemaType)] 5 | struct MyStruct { 6 | field: u32, 7 | other_field: u8, 8 | } 9 | 10 | #[derive(SchemaType)] 11 | enum MyEnum { 12 | One(u32), 13 | Two(u8), 14 | } 15 | 16 | fn main() { 17 | let _type = ::get_type(); 18 | let _type = ::get_type(); 19 | } 20 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-schema-type/success-transparent.rs: -------------------------------------------------------------------------------- 1 | /// Test ensuring derivation works for newtype wrappers with transparent 2 | use concordium_std::*; 3 | 4 | /// Simple struct 5 | #[derive(SchemaType)] 6 | #[concordium(transparent)] 7 | struct MyStruct { 8 | field: u32, 9 | } 10 | 11 | /// Nested struct 12 | #[derive(SchemaType)] 13 | #[concordium(transparent)] 14 | struct MyOtherStruct { 15 | field: MyStruct, 16 | } 17 | 18 | /// With field attributes 19 | #[derive(SchemaType)] 20 | #[concordium(transparent)] 21 | struct MyCollection { 22 | #[concordium(size_length = 1)] 23 | field: Vec, 24 | } 25 | 26 | fn main() { 27 | { 28 | let schema_type = ::get_type(); 29 | assert_eq!(schema_type, schema::Type::U32); 30 | } 31 | 32 | { 33 | let schema_type = ::get_type(); 34 | assert_eq!(schema_type, schema::Type::U32); 35 | } 36 | 37 | { 38 | let schema_type = ::get_type(); 39 | assert_eq!( 40 | schema_type, 41 | schema::Type::List(schema::SizeLength::U8, Box::new(schema::Type::U32)) 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-colliding-forward.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Serial)` fails when 'forward' attributes are colliding. 2 | use concordium_std::*; 3 | 4 | #[derive(Serial)] 5 | #[concordium(repr(u8))] 6 | enum Count { 7 | One { 8 | field: u32, 9 | }, 10 | #[concordium(forward = [5, 6])] 11 | Two(Inner), 12 | 13 | #[concordium(forward = 5)] 14 | Three(Inner), 15 | } 16 | 17 | #[derive(Serial)] 18 | #[concordium(repr(u8))] 19 | enum Inner { 20 | #[concordium(tag = 5)] 21 | Alpha { 22 | balance: u32, 23 | }, 24 | #[concordium(tag = 6)] 25 | Beta(u16), 26 | } 27 | 28 | fn main() {} 29 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-colliding-forward.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Three' collides with the tag of 'Two'. 2 | --> tests/derive-serial/fail-colliding-forward.rs:13:28 3 | | 4 | 13 | #[concordium(forward = 5)] 5 | | ^ 6 | 7 | error: The tag of 'Two' collides with the tag of 'Three'. 8 | --> tests/derive-serial/fail-colliding-forward.rs:10:29 9 | | 10 | 10 | #[concordium(forward = [5, 6])] 11 | | ^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-colliding-tag-forward.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Serial)` fails when 'forward' and 'tag' attributes are colliding. 2 | use concordium_std::*; 3 | 4 | #[derive(Serial)] 5 | #[concordium(repr(u8))] 6 | enum Count { 7 | One { 8 | field: u32, 9 | }, 10 | #[concordium(forward = [5, 6])] 11 | Two(Inner), 12 | 13 | #[concordium(tag = 5)] 14 | Three(Inner), 15 | } 16 | 17 | #[derive(Serial)] 18 | #[concordium(repr(u8))] 19 | enum Inner { 20 | #[concordium(tag = 5)] 21 | Alpha { 22 | balance: u32, 23 | }, 24 | #[concordium(tag = 6)] 25 | Beta(u16), 26 | } 27 | 28 | fn main() {} 29 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-colliding-tag-forward.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Three' collides with the tag of 'Two'. 2 | --> tests/derive-serial/fail-colliding-tag-forward.rs:13:18 3 | | 4 | 13 | #[concordium(tag = 5)] 5 | | ^^^ 6 | 7 | error: The tag of 'Two' collides with the tag of 'Three'. 8 | --> tests/derive-serial/fail-colliding-tag-forward.rs:10:29 9 | | 10 | 10 | #[concordium(forward = [5, 6])] 11 | | ^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-colliding-tag.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Serial)` fails when two 'tag' attributes are colliding. 2 | use concordium_std::*; 3 | 4 | #[derive(Serial)] 5 | #[concordium(repr(u8))] 6 | enum MyTaggedEnum { 7 | #[concordium(tag = 42)] 8 | One, 9 | #[concordium(tag = 42)] 10 | Two, 11 | } 12 | 13 | fn main() {} 14 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-colliding-tag.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Two' collides with the tag of 'One'. 2 | --> tests/derive-serial/fail-colliding-tag.rs:9:18 3 | | 4 | 9 | #[concordium(tag = 42)] 5 | | ^^^ 6 | 7 | error: The tag of 'One' collides with the tag of 'Two'. 8 | --> tests/derive-serial/fail-colliding-tag.rs:7:18 9 | | 10 | 7 | #[concordium(tag = 42)] 11 | | ^^^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-forward-collide-with-inferred.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Serial)` fails when a 'forward' attribute collides with the 2 | //! default tag for another variant. 3 | use concordium_std::*; 4 | 5 | #[derive(Serial)] 6 | #[concordium(repr(u8))] 7 | enum Count { 8 | One { 9 | field: u32, 10 | }, 11 | #[concordium(forward = [0, 6])] 12 | Two(Inner), 13 | } 14 | 15 | #[derive(Serial)] 16 | #[concordium(repr(u8))] 17 | enum Inner { 18 | Alpha { 19 | balance: u32, 20 | }, 21 | #[concordium(tag = 6)] 22 | Beta(u16), 23 | } 24 | 25 | fn main() {} 26 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-forward-collide-with-inferred.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Two' collides with the tag of 'One'. 2 | --> tests/derive-serial/fail-forward-collide-with-inferred.rs:11:29 3 | | 4 | 11 | #[concordium(forward = [0, 6])] 5 | | ^ 6 | 7 | error: The tag of 'One' collides with the tag of 'Two'. 8 | --> tests/derive-serial/fail-forward-collide-with-inferred.rs:8:5 9 | | 10 | 8 | One { 11 | | ^^^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-forward-gt-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Serial)` fails when a 'forward' attribute is greater than 2 | //! what 'repr(u8)' can represent. 3 | use concordium_std::*; 4 | 5 | #[derive(Serial)] 6 | #[concordium(repr(u8))] 7 | enum Count { 8 | One { 9 | field: u32, 10 | }, 11 | #[concordium(forward = [500, 6])] 12 | Two(Inner), 13 | } 14 | 15 | #[derive(Serial)] 16 | #[concordium(repr(u16))] 17 | enum Inner { 18 | #[concordium(tag = 500)] 19 | Alpha { 20 | balance: u32, 21 | }, 22 | #[concordium(tag = 6)] 23 | Beta(u16), 24 | } 25 | 26 | fn main() {} 27 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-forward-gt-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'forward' attribute tag value of 500 cannot be represented by the type u8 set in 'repr(u8)' 2 | --> tests/derive-serial/fail-forward-gt-repr.rs:11:29 3 | | 4 | 11 | #[concordium(forward = [500, 6])] 5 | | ^^^ 6 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-forward-without-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Serial)` fails when using 'forward' attribute without a 2 | //! 'repr' attribute. 3 | use concordium_std::*; 4 | 5 | #[derive(Serial)] 6 | enum Count { 7 | One { 8 | field: u32, 9 | }, 10 | #[concordium(forward = [5, 6])] 11 | Two(Inner), 12 | } 13 | 14 | #[derive(Serial)] 15 | #[concordium(repr(u8))] 16 | enum Inner { 17 | #[concordium(tag = 5)] 18 | Alpha { 19 | balance: u32, 20 | }, 21 | #[concordium(tag = 6)] 22 | Beta(u16), 23 | } 24 | 25 | fn main() {} 26 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-forward-without-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'repr(..)' attribute must be set on the type when using 'forward' attribute 2 | --> tests/derive-serial/fail-forward-without-repr.rs:5:10 3 | | 4 | 5 | #[derive(Serial)] 5 | | ^^^^^^ 6 | | 7 | = note: this error originates in the derive macro `Serial` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-tag-collide-with-inferred.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Serial)` fails when a 'tag' attribute collides with the 2 | //! default tag for another variant. 3 | use concordium_std::*; 4 | 5 | #[derive(Serial)] 6 | #[concordium(repr(u8))] 7 | enum MyTaggedEnum { 8 | One, 9 | #[concordium(tag = 0)] 10 | Two, 11 | } 12 | 13 | fn main() {} 14 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-tag-collide-with-inferred.stderr: -------------------------------------------------------------------------------- 1 | error: The tag of 'Two' collides with the tag of 'One'. 2 | --> tests/derive-serial/fail-tag-collide-with-inferred.rs:9:18 3 | | 4 | 9 | #[concordium(tag = 0)] 5 | | ^^^ 6 | 7 | error: The tag of 'One' collides with the tag of 'Two'. 8 | --> tests/derive-serial/fail-tag-collide-with-inferred.rs:8:5 9 | | 10 | 8 | One, 11 | | ^^^ 12 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-tag-gt-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Serial)` fails when a 'tag' attribute is greater than what 2 | //! 'repr(u8)' can represent. 3 | use concordium_std::*; 4 | 5 | #[derive(Serial)] 6 | #[concordium(repr(u8))] 7 | enum MyTaggedEnum { 8 | #[concordium(tag = 256)] 9 | One, 10 | Two, 11 | } 12 | 13 | fn main() {} 14 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-tag-gt-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'tag' attribute value of 256 cannot be represented by the type u8 set in 'repr(u8)' 2 | --> tests/derive-serial/fail-tag-gt-repr.rs:8:18 3 | | 4 | 8 | #[concordium(tag = 256)] 5 | | ^^^ 6 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-tag-without-repr.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Serial)` fails when using 'tag' attribute without a 2 | //! 'repr' attribute. 3 | use concordium_std::*; 4 | 5 | #[derive(Serial)] 6 | enum MyTaggedEnum { 7 | #[concordium(tag = 42)] 8 | One, 9 | Two, 10 | } 11 | 12 | fn main() {} 13 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/fail-tag-without-repr.stderr: -------------------------------------------------------------------------------- 1 | error: 'repr(..)' attribute must be set on the type when using 'tag' attribute 2 | --> tests/derive-serial/fail-tag-without-repr.rs:5:10 3 | | 4 | 5 | #[derive(Serial)] 5 | | ^^^^^^ 6 | | 7 | = note: this error originates in the derive macro `Serial` (in Nightly builds, run with -Z macro-backtrace for more info) 8 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/success-attributes.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Serial)` generates code successfully for types using 2 | //! attributes. 3 | use concordium_std::*; 4 | 5 | #[derive(Serial)] 6 | #[concordium(repr(u8))] 7 | enum MyTaggedEnum { 8 | #[concordium(tag = 42)] 9 | One(u8), 10 | Two(u8), 11 | } 12 | 13 | #[derive(Serial)] 14 | #[concordium(repr(u16))] 15 | enum MyTaggedEnumU16 { 16 | #[concordium(tag = 42)] 17 | One(u8), 18 | Two(u8), 19 | } 20 | 21 | fn main() { 22 | { 23 | let value = MyTaggedEnum::One(3); 24 | let bytes = to_bytes(&value); 25 | assert_eq!(bytes, vec![42, 3]); 26 | } 27 | 28 | { 29 | let value = MyTaggedEnum::Two(255); 30 | let bytes = to_bytes(&value); 31 | assert_eq!(bytes, vec![1, 255]); 32 | } 33 | 34 | { 35 | let value = MyTaggedEnumU16::One(3); 36 | let bytes = to_bytes(&value); 37 | assert_eq!(bytes, vec![42, 0, 3]); 38 | } 39 | 40 | { 41 | let value = MyTaggedEnumU16::Two(255); 42 | let bytes = to_bytes(&value); 43 | assert_eq!(bytes, vec![1, 0, 255]); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/success-forward-attribute.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Serial)` generates code successfully for enums using 2 | //! forward attribute. 3 | use concordium_std::*; 4 | 5 | #[derive(Serial)] 6 | #[concordium(repr(u8))] 7 | enum Count { 8 | One { 9 | field: u32, 10 | }, 11 | #[concordium(forward = [5, 6])] 12 | Two(Inner), 13 | } 14 | 15 | #[derive(Serial)] 16 | #[concordium(repr(u8))] 17 | enum Inner { 18 | #[concordium(tag = 5)] 19 | Alpha { 20 | balance: u32, 21 | }, 22 | #[concordium(tag = 6)] 23 | Beta(u16), 24 | } 25 | 26 | // Example using predefined forwarded tags. 27 | 28 | #[derive(Serial)] 29 | #[concordium(repr(u8))] 30 | enum Event { 31 | A { 32 | field: u32, 33 | }, 34 | #[concordium(forward = cis2_events)] 35 | B(Cis2Event), 36 | } 37 | 38 | #[derive(Serial)] 39 | #[concordium(repr(u8))] 40 | enum Cis2Event { 41 | #[concordium(tag = 255)] 42 | Transfer, 43 | #[concordium(tag = 254)] 44 | Mint, 45 | #[concordium(tag = 253)] 46 | Burn, 47 | #[concordium(tag = 252)] 48 | UpdateOperator, 49 | #[concordium(tag = 251)] 50 | TokenMetadata, 51 | } 52 | 53 | fn main() { 54 | { 55 | let value = Count::One { 56 | field: 42, 57 | }; 58 | let bytes = to_bytes(&value); 59 | assert_eq!(bytes, vec![0, 42, 0, 0, 0]); 60 | } 61 | { 62 | let value = Count::Two(Inner::Alpha { 63 | balance: 50, 64 | }); 65 | let bytes = to_bytes(&value); 66 | assert_eq!(bytes, vec![5, 50, 0, 0, 0]); 67 | } 68 | 69 | { 70 | let value = Count::Two(Inner::Beta(8)); 71 | let bytes = to_bytes(&value); 72 | assert_eq!(bytes, vec![6, 8, 0]); 73 | } 74 | 75 | { 76 | let value = Event::B(Cis2Event::Transfer); 77 | let bytes = to_bytes(&value); 78 | assert_eq!(bytes, vec![255]); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/success-generics.rs: -------------------------------------------------------------------------------- 1 | /// Test ensuring derivation works for types with type parameters. 2 | use concordium_std::*; 3 | 4 | #[derive(Serial)] 5 | struct MyStruct { 6 | field: A, 7 | other_field: u8, 8 | } 9 | 10 | #[derive(Serial)] 11 | struct MyOtherStruct { 12 | field: A, 13 | other_field: B, 14 | } 15 | 16 | #[derive(Serial)] 17 | enum MyEnum { 18 | One(u32), 19 | Two(A), 20 | } 21 | 22 | #[derive(Serial)] 23 | enum MyOtherEnum { 24 | One(u32), 25 | Two(A, B), 26 | } 27 | 28 | #[derive(Serial)] 29 | #[concordium(state_parameter = "S")] 30 | struct WithStateParameter { 31 | test_map: StateMap, 32 | } 33 | 34 | #[derive(Serial)] 35 | #[concordium(state_parameter = "S")] 36 | struct WithStateParameterWhere 37 | where 38 | S: HasStateApi, 39 | S: Clone, { 40 | test_map: StateMap, 41 | } 42 | 43 | #[rustfmt::skip] // skip formatting to maintain lack of trailing comma 44 | mod inner { 45 | use super::*; 46 | #[derive(Serial)] 47 | #[concordium(state_parameter = "S")] 48 | struct WithStateParameterWhereTwo 49 | where 50 | S: HasStateApi, 51 | S: Clone { // note the lack of comma compared to the test above 52 | test_map: StateMap, 53 | } 54 | 55 | #[derive(Serial)] 56 | #[concordium(state_parameter = "S")] 57 | struct WithStateParameterWhereThree 58 | where // empty where clause 59 | { 60 | test_map: StateMap, 61 | } 62 | } 63 | 64 | 65 | trait ProxyTrait { 66 | type State: HasStateApi; 67 | } 68 | 69 | #[derive(Serial)] 70 | #[concordium(state_parameter = "T::State")] 71 | struct WithAssocStateParameter { 72 | test_map: StateMap, 73 | } 74 | 75 | fn main() { 76 | { 77 | let value = MyStruct:: { 78 | field: 42, 79 | other_field: 5, 80 | }; 81 | let _bytes = to_bytes(&value); 82 | } 83 | { 84 | let value = MyOtherStruct:: { 85 | field: 42, 86 | other_field: 5, 87 | }; 88 | let _bytes = to_bytes(&value); 89 | } 90 | { 91 | let value = MyEnum::::Two(1); 92 | let _bytes = to_bytes(&value); 93 | } 94 | { 95 | let value = MyOtherEnum::::Two(1, 15); 96 | let _bytes = to_bytes(&value); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /concordium-std/tests/derive-serial/success-simple.rs: -------------------------------------------------------------------------------- 1 | //! Ensure `derive(Serial)` generates code successfully for the 2 | //! simplest case when `#[concordium(state_parameter)]` is set. 3 | use concordium_std::*; 4 | 5 | #[derive(Serial, DeserialWithState, Deletable)] 6 | #[concordium(state_parameter = "S")] 7 | struct State { 8 | map: StateMap, 9 | set: StateSet, 10 | } 11 | 12 | #[init(contract = "test")] 13 | fn contract_init( 14 | _ctx: &impl HasInitContext, 15 | state_builder: &mut StateBuilder, 16 | ) -> InitResult> { 17 | Ok(State { 18 | map: state_builder.new_map(), 19 | set: state_builder.new_set(), 20 | }) 21 | } 22 | 23 | fn main() {} 24 | -------------------------------------------------------------------------------- /concordium-std/tests/derives.rs: -------------------------------------------------------------------------------- 1 | //! Test correct functioning of trait deriving macros from 2 | //! `concordium-std-derive` package. Test cases presented here check successful 3 | //! (or failed) compilation for the code which uses macros, not its functioning. 4 | #[test] 5 | fn deserial_with_state() { 6 | let t = trybuild::TestCases::new(); 7 | t.pass("tests/derive-deserial-with-state/success-*.rs"); 8 | t.compile_fail("tests/derive-deserial-with-state/fail-*.rs"); 9 | } 10 | 11 | #[test] 12 | fn deletable() { 13 | let t = trybuild::TestCases::new(); 14 | t.pass("tests/derive-deletable/success-*.rs"); 15 | } 16 | 17 | #[test] 18 | fn serial() { 19 | let t = trybuild::TestCases::new(); 20 | t.pass("tests/derive-serial/success-*.rs"); 21 | t.compile_fail("tests/derive-serial/fail-*.rs"); 22 | } 23 | 24 | #[test] 25 | fn deserial() { 26 | let t = trybuild::TestCases::new(); 27 | t.pass("tests/derive-deserial/success-*.rs"); 28 | t.compile_fail("tests/derive-deserial/fail-*.rs"); 29 | } 30 | 31 | #[test] 32 | fn schema_type() { 33 | let t = trybuild::TestCases::new(); 34 | t.pass("tests/derive-schema-type/success-*.rs"); 35 | t.compile_fail("tests/derive-schema-type/fail-*.rs"); 36 | } 37 | -------------------------------------------------------------------------------- /concordium-std/tests/state/map-multiple-entries.rs: -------------------------------------------------------------------------------- 1 | //! This test checks that you cannot have multiple entries from a `StateMap` 2 | //! alive at the same time. 3 | //! 4 | //! When compiling it, the borrow-checker is supposed to throw an error. 5 | use concordium_std::*; 6 | 7 | pub fn main() { 8 | let mut state_builder = StateBuilder::open(ExternStateApi::open()); 9 | let mut map: StateMap = state_builder.new_map(); 10 | // Get two entries. 11 | let e1 = map.entry(0u8); 12 | let e2 = map.entry(1u8); 13 | // Use them, so we are certain that their lifetimes overlap. 14 | e1.or_insert(1); 15 | e2.or_insert(2); 16 | } 17 | -------------------------------------------------------------------------------- /concordium-std/tests/state/map-multiple-entries.stderr: -------------------------------------------------------------------------------- 1 | error[E0499]: cannot borrow `map` as mutable more than once at a time 2 | --> tests/state/map-multiple-entries.rs:12:14 3 | | 4 | 11 | let e1 = map.entry(0u8); 5 | | --- first mutable borrow occurs here 6 | 12 | let e2 = map.entry(1u8); 7 | | ^^^ second mutable borrow occurs here 8 | 13 | // Use them, so we are certain that their lifetimes overlap. 9 | 14 | e1.or_insert(1); 10 | | -- first borrow later used here 11 | -------------------------------------------------------------------------------- /concordium-std/tests/state/map-multiple-state-ref-mut.rs: -------------------------------------------------------------------------------- 1 | //! This test checks that you cannot have multiple `StateRefMut` from a 2 | //! `StateMap` alive at the same time. 3 | //! 4 | //! When compiling it, the borrow-checker is supposed to throw an error. 5 | use concordium_std::*; 6 | 7 | pub fn main() { 8 | let mut state_builder = StateBuilder::open(ExternStateApi::open()); 9 | let mut map: StateMap = state_builder.new_map(); 10 | map.insert(0, 1); 11 | map.insert(1, 2); 12 | // Get two mutable references and unwrap the options. 13 | let e1 = map.get_mut(&0u8).unwrap(); 14 | let e2 = map.get_mut(&1u8).unwrap(); 15 | // Use them, so we are certain that their lifetimes overlap. 16 | assert_eq!(*e1, *e2); 17 | } 18 | -------------------------------------------------------------------------------- /concordium-std/tests/state/map-multiple-state-ref-mut.stderr: -------------------------------------------------------------------------------- 1 | error[E0499]: cannot borrow `map` as mutable more than once at a time 2 | --> tests/state/map-multiple-state-ref-mut.rs:14:14 3 | | 4 | 13 | let e1 = map.get_mut(&0u8).unwrap(); 5 | | --- first mutable borrow occurs here 6 | 14 | let e2 = map.get_mut(&1u8).unwrap(); 7 | | ^^^ second mutable borrow occurs here 8 | 15 | // Use them, so we are certain that their lifetimes overlap. 9 | 16 | assert_eq!(*e1, *e2); 10 | | -- first borrow later used here 11 | -------------------------------------------------------------------------------- /contract-testing/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "concordium-smart-contract-testing" 3 | version = "4.4.0" 4 | edition = "2021" 5 | rust-version = "1.73" 6 | license = "MPL-2.0" 7 | readme = "README.md" 8 | description = "A companion crate to `concordium-std` that supports off-chain end-to-end testing of smart contracts." 9 | homepage = "https://github.com/Concordium/concordium-rust-smart-contracts" 10 | repository = "https://github.com/Concordium/concordium-rust-smart-contracts" 11 | exclude = ["tests"] # Do not publish tests. 12 | 13 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 14 | 15 | [dependencies] 16 | concordium-rust-sdk = { version = "6", path = "../concordium-rust-sdk" } 17 | tokio = { version = "1.28", features = ["rt-multi-thread", "time"] } 18 | sha2 = "0.10" 19 | anyhow = "1" 20 | # Pinned to version `1.6.0`, since otherwise rust version `1.73` would refuse to build. 21 | base64ct = "=1.6.0" 22 | thiserror = "1.0" 23 | num-bigint = "0.4" 24 | num-integer = "0.1" 25 | 26 | [dev-dependencies] 27 | rand = "0.8" 28 | -------------------------------------------------------------------------------- /contract-testing/README.md: -------------------------------------------------------------------------------- 1 | ## Concordium Smart Contract Testing 2 | 3 | A library that supports writing integration tests in Rust for Concordium smart 4 | contracts. 5 | 6 | This is a companion to [concordium-std](https://crates.io/crates/concordium-std) 7 | which is used to write smart contracts in Rust. 8 | 9 | ### Documentation 10 | 11 | - [docs.rs](https://docs.rs/concordium-smart-contract-testing) 12 | 13 | 14 | ### MSRV 15 | 16 | The minimum supported Rust version can be found in the `Cargo.toml` manifest 17 | file. Changes in MSRV will be accompanied by at least a minor version bump. 18 | -------------------------------------------------------------------------------- /contract-testing/src/constants.rs: -------------------------------------------------------------------------------- 1 | //! Various constants. 2 | 3 | use concordium_rust_sdk::base::base::Energy; 4 | 5 | // Energy constants from Cost.hs in concordium-base. 6 | 7 | /// Cost of querying the account balance from within a smart contract instance. 8 | pub(crate) const CONTRACT_INSTANCE_QUERY_ACCOUNT_BALANCE_COST: Energy = Energy { 9 | energy: 200, 10 | }; 11 | 12 | /// Cost of querying the contract balance from within a smart contract instance. 13 | pub(crate) const CONTRACT_INSTANCE_QUERY_CONTRACT_BALANCE_COST: Energy = Energy { 14 | energy: 200, 15 | }; 16 | 17 | /// Cost of querying the current exchange rates from within a smart contract 18 | /// instance. 19 | pub(crate) const CONTRACT_INSTANCE_QUERY_EXCHANGE_RATE_COST: Energy = Energy { 20 | energy: 100, 21 | }; 22 | 23 | /// Base cost querying account keys. In addition to this cost there is a cost 24 | /// based on the number of returned keys. 25 | pub(crate) const CONTRACT_INSTANCE_QUERY_ACCOUNT_KEYS_BASE_COST: Energy = Energy { 26 | energy: 200, 27 | }; 28 | 29 | /// Cost of returning the account keys, based on the number of keys. 30 | /// Each key is 32 bytes, and there is a bit of administrative overhead. 31 | pub(crate) fn contract_instance_query_account_keys_return_cost(num_keys: u32) -> Energy { 32 | Energy { 33 | energy: u64::from(num_keys) * 3, 34 | } 35 | } 36 | 37 | /// The cost of querying the contract module reference from a smart contract 38 | /// instance. 39 | pub(crate) const CONTRACT_INSTANCE_QUERY_CONTRACT_MODULE_REFERENCE_COST: Energy = Energy { 40 | energy: 200, 41 | }; 42 | 43 | /// The cost of querying the contract module name from a smart contract 44 | /// instance. While the length of a smart contract name is variable, it is at 45 | /// most 100 characters, so there is no real benefit to varying the cost based 46 | /// on the length. 47 | pub(crate) const CONTRACT_INSTANCE_QUERY_CONTRACT_NAME_COST: Energy = Energy { 48 | energy: 200, 49 | }; 50 | 51 | /// Cost **in energy** of verification of an ed25519 signature. 52 | /// This should match the cost of 53 | /// [`verify_ed22519_cost`](concordium_smart_contract_engine::constants::verify_ed25519_cost) 54 | /// except the latter is the cost in interpreter energy, and this on is in 55 | /// [`Energy`]. 56 | pub(crate) fn verify_ed25519_energy_cost(num_sigs: u32, message_len: u32) -> Energy { 57 | Energy { 58 | energy: u64::from(num_sigs) * (100 + u64::from(message_len) / 10), 59 | } 60 | } 61 | 62 | /// The base cost of initializing a contract instance to cover administrative 63 | /// costs. Even if no code is run and no instance created. 64 | pub(crate) const INITIALIZE_CONTRACT_INSTANCE_BASE_COST: Energy = Energy { 65 | energy: 300, 66 | }; 67 | 68 | /// Cost of creating an empty smart contract instance. 69 | pub(crate) const INITIALIZE_CONTRACT_INSTANCE_CREATE_COST: Energy = Energy { 70 | energy: 200, 71 | }; 72 | 73 | /// The base cost of updating a contract instance to cover administrative 74 | /// costs. Even if no code is run. 75 | pub(crate) const UPDATE_CONTRACT_INSTANCE_BASE_COST: Energy = Energy { 76 | energy: 300, 77 | }; 78 | 79 | /// The name of the environment variable that holds the path to the contract 80 | /// module file. To load the module, use the 81 | /// [`module_load_output`](crate::module_load_output) function. 82 | pub const CONTRACT_MODULE_OUTPUT_PATH_ENV_VAR: &str = "CARGO_CONCORDIUM_TEST_MODULE_OUTPUT_PATH"; 83 | -------------------------------------------------------------------------------- /contract-testing/src/invocation/mod.rs: -------------------------------------------------------------------------------- 1 | //! Functionality and types for invoking contract entrypoints. 2 | //! 3 | //! Contract invocation is effectful and transactional. 4 | //! We therefore keep track of changes during execution in a 5 | //! [`ChangeSet`][types::ChangeSet]. 6 | //! 7 | //! Once the execution (transaction) has finished, the changes can then be 8 | //! persisted (saved) or discarded, dependent on whether it succeeded or not. 9 | //! 10 | //! The changes that may occur are: 11 | //! - Mutations to contract state, 12 | //! - Contract upgrades (changing the module), 13 | //! - Balances of contracts and accounts. 14 | 15 | mod impls; 16 | mod types; 17 | pub(crate) use types::{ChangeSet, EntrypointInvocationHandler, TestConfigurationError}; 18 | -------------------------------------------------------------------------------- /contract-testing/tests/all_new_host_functions.rs: -------------------------------------------------------------------------------- 1 | //! This module tests that a module containing all the new V1 host functions is 2 | //! accepted. It serves as a basic integration test. Individual functions either 3 | //! have tests in wasm-chain-integration, or as part of other scheduler tests if 4 | //! they require more complex interactions with the chain. 5 | 6 | use concordium_smart_contract_testing::*; 7 | mod helpers; 8 | 9 | #[test] 10 | fn test_all_new_host_functions() { 11 | let mut chain = Chain::new(); 12 | let initial_balance = Amount::from_ccd(1000000); 13 | chain.create_account(Account::new(helpers::ACC_0, initial_balance)); 14 | 15 | chain 16 | .module_deploy_v1( 17 | Signer::with_one_key(), 18 | helpers::ACC_0, 19 | module_load_v1_raw(helpers::wasm_test_file("all-new-host-functions.wasm")) 20 | .expect("module should exist"), 21 | ) 22 | .expect("Deploying valid module should work"); 23 | } 24 | -------------------------------------------------------------------------------- /contract-testing/tests/basics.rs: -------------------------------------------------------------------------------- 1 | //! This module contains tests that test various basic things, such as state 2 | //! reentry and energy usage and amounts charged. 3 | use concordium_smart_contract_testing::*; 4 | mod helpers; 5 | 6 | #[test] 7 | fn basics() { 8 | let mut chain = Chain::new_with_time_and_rates( 9 | SlotTime::from_timestamp_millis(0), 10 | // Set a specific value, taken from testnet, to compare the exact amounts charged. 11 | ExchangeRate::new_unchecked(3127635127520773120, 24857286553), 12 | ExchangeRate::new_unchecked(1, 50000), 13 | ) 14 | .expect("Values known to be in range."); 15 | 16 | let initial_balance = Amount::from_ccd(100_000); 17 | chain.create_account(Account::new(helpers::ACC_0, initial_balance)); 18 | 19 | let deployment = chain 20 | .module_deploy_v1( 21 | Signer::with_one_key(), 22 | helpers::ACC_0, 23 | module_load_v1_raw(helpers::wasm_test_file("fib.wasm")).expect("Module should exist."), 24 | ) 25 | .expect("Deploying valid module should work"); 26 | 27 | let init = chain 28 | .contract_init( 29 | Signer::with_one_key(), 30 | helpers::ACC_0, 31 | Energy::from(10000), 32 | InitContractPayload { 33 | amount: Amount::zero(), 34 | mod_ref: deployment.module_reference, 35 | init_name: OwnedContractName::new_unchecked("init_fib".into()), 36 | param: OwnedParameter::empty(), 37 | }, 38 | ) 39 | .expect("Initializing valid contract should work"); 40 | 41 | let update = chain 42 | .contract_update( 43 | Signer::with_one_key(), 44 | helpers::ACC_0, 45 | Address::Account(helpers::ACC_0), 46 | Energy::from(100000), 47 | UpdateContractPayload { 48 | amount: Amount::zero(), 49 | address: init.contract_address, 50 | receive_name: OwnedReceiveName::new_unchecked("fib.receive".into()), 51 | message: OwnedParameter::from_serial(&6u64).expect("Parameter has valid size"), 52 | }, 53 | ) 54 | .expect("Updating valid contract should work"); 55 | 56 | let view = chain 57 | .contract_invoke( 58 | helpers::ACC_0, 59 | Address::Account(helpers::ACC_0), 60 | Energy::from(10000), 61 | UpdateContractPayload { 62 | amount: Amount::zero(), 63 | address: init.contract_address, 64 | receive_name: OwnedReceiveName::new_unchecked("fib.view".into()), 65 | message: OwnedParameter::empty(), 66 | }, 67 | ) 68 | .expect("Invoking get should work"); 69 | 70 | // Check the state and return values. 71 | assert!(chain.get_contract(init.contract_address).is_some()); 72 | assert!(update.state_changed); 73 | let expected_res = u64::to_le_bytes(13); 74 | assert_eq!(update.return_value, expected_res); 75 | // Assert that the updated state is persisted. 76 | assert_eq!(view.return_value, expected_res); 77 | 78 | // Check that the account was correctly charged for all transactions. 79 | // This also asserts that the account wasn't charged for the invoke. 80 | assert_eq!( 81 | chain.account_balance_available(helpers::ACC_0), 82 | Some( 83 | initial_balance 84 | - deployment.transaction_fee 85 | - init.transaction_fee 86 | - update.transaction_fee 87 | ) 88 | ); 89 | 90 | // Check that the energy usage matches the node. 91 | assert_eq!(deployment.energy_used, 1067.into()); 92 | assert_eq!(init.energy_used, 756.into()); 93 | assert_eq!(update.energy_used, 7787.into()); 94 | assert_eq!(view.energy_used, 301.into()); 95 | 96 | // Check that the amounts charged matches the node. 97 | assert_eq!(deployment.transaction_fee, Amount::from_micro_ccd(2_685_078)); 98 | assert_eq!(init.transaction_fee, Amount::from_micro_ccd(1_902_454)); 99 | assert_eq!(update.transaction_fee, Amount::from_micro_ccd(19_595_780)); 100 | } 101 | -------------------------------------------------------------------------------- /contract-testing/tests/counter.rs: -------------------------------------------------------------------------------- 1 | //! This module tests calling a contract from a contract and inspecting the 2 | //! return message. Concretely it invokes a counter contract that maintains a 3 | //! 64-bit counter in its state. 4 | 5 | use concordium_smart_contract_testing::*; 6 | mod helpers; 7 | 8 | #[test] 9 | fn test_counter() { 10 | let mut chain = Chain::new(); 11 | let initial_balance = Amount::from_ccd(1000000); 12 | chain.create_account(Account::new(helpers::ACC_0, initial_balance)); 13 | 14 | let res_deploy = chain 15 | .module_deploy_v1( 16 | Signer::with_one_key(), 17 | helpers::ACC_0, 18 | module_load_v1_raw(helpers::wasm_test_file("call-counter.wasm")) 19 | .expect("module should exist"), 20 | ) 21 | .expect("Deploying valid module should work"); 22 | 23 | let res_init = chain 24 | .contract_init( 25 | Signer::with_one_key(), 26 | helpers::ACC_0, 27 | Energy::from(10000), 28 | InitContractPayload { 29 | mod_ref: res_deploy.module_reference, 30 | init_name: OwnedContractName::new_unchecked("init_counter".into()), 31 | param: OwnedParameter::empty(), 32 | amount: Amount::zero(), 33 | }, 34 | ) 35 | .expect("Initializing valid contract should work"); 36 | 37 | chain 38 | .contract_update( 39 | Signer::with_one_key(), 40 | helpers::ACC_0, 41 | Address::Account(helpers::ACC_0), 42 | Energy::from(10000), 43 | UpdateContractPayload { 44 | address: res_init.contract_address, 45 | receive_name: OwnedReceiveName::new_unchecked("counter.inc".into()), 46 | message: OwnedParameter::empty(), 47 | amount: Amount::zero(), 48 | }, 49 | ) 50 | .expect("Updating valid contract should work"); 51 | assert_counter_state(&mut chain, res_init.contract_address, 1); 52 | 53 | chain 54 | .contract_update( 55 | Signer::with_one_key(), 56 | helpers::ACC_0, 57 | Address::Account(helpers::ACC_0), 58 | Energy::from(10000), 59 | UpdateContractPayload { 60 | address: res_init.contract_address, 61 | receive_name: OwnedReceiveName::new_unchecked("counter.inc".into()), 62 | message: OwnedParameter::empty(), 63 | amount: Amount::zero(), 64 | }, 65 | ) 66 | .expect("Updating valid contract should work"); 67 | assert_counter_state(&mut chain, res_init.contract_address, 2); 68 | 69 | let parameter = ( 70 | res_init.contract_address, 71 | OwnedParameter::empty(), 72 | EntrypointName::new_unchecked("inc"), 73 | Amount::zero(), 74 | ); 75 | chain 76 | .contract_update( 77 | Signer::with_one_key(), 78 | helpers::ACC_0, 79 | Address::Account(helpers::ACC_0), 80 | Energy::from(10000), 81 | UpdateContractPayload { 82 | address: res_init.contract_address, 83 | receive_name: OwnedReceiveName::new_unchecked("counter.inc10".into()), 84 | message: OwnedParameter::from_serial(¶meter) 85 | .expect("Parameter has valid size"), 86 | amount: Amount::zero(), 87 | }, 88 | ) 89 | .expect("Updating valid contract should work"); 90 | assert_counter_state(&mut chain, res_init.contract_address, 12); 91 | } 92 | 93 | /// Looks up in the root of the state trie and compares the value with the 94 | /// `expected`. 95 | fn assert_counter_state(chain: &mut Chain, contract_address: ContractAddress, expected: u64) { 96 | assert_eq!( 97 | chain.contract_state_lookup(contract_address, &[0, 0, 0, 0, 0, 0, 0, 0]).unwrap(), 98 | u64::to_le_bytes(expected) 99 | ); 100 | } 101 | -------------------------------------------------------------------------------- /contract-testing/tests/fallback.rs: -------------------------------------------------------------------------------- 1 | //! Tests for the contract default method/fallback functionality. 2 | 3 | use concordium_smart_contract_testing::*; 4 | mod helpers; 5 | 6 | #[test] 7 | fn test_fallback() { 8 | let mut chain = Chain::new(); 9 | let initial_balance = Amount::from_ccd(1000000); 10 | chain.create_account(Account::new(helpers::ACC_0, initial_balance)); 11 | 12 | let res_deploy = chain 13 | .module_deploy_v1( 14 | Signer::with_one_key(), 15 | helpers::ACC_0, 16 | module_load_v1_raw(helpers::wasm_test_file("fallback.wasm")) 17 | .expect("module should exist"), 18 | ) 19 | .expect("Deploying valid module should work"); 20 | 21 | let res_init_two = chain 22 | .contract_init( 23 | Signer::with_one_key(), 24 | helpers::ACC_0, 25 | Energy::from(10000), 26 | InitContractPayload { 27 | mod_ref: res_deploy.module_reference, 28 | init_name: OwnedContractName::new_unchecked("init_two".into()), 29 | param: OwnedParameter::empty(), 30 | amount: Amount::zero(), 31 | }, 32 | ) 33 | .expect("Initializing valid contract should work"); 34 | 35 | let res_init_one = chain 36 | .contract_init( 37 | Signer::with_one_key(), 38 | helpers::ACC_0, 39 | Energy::from(10000), 40 | InitContractPayload { 41 | mod_ref: res_deploy.module_reference, 42 | init_name: OwnedContractName::new_unchecked("init_one".into()), 43 | param: OwnedParameter::from_serial(&res_init_two.contract_address) 44 | .expect("Parameter has valid size"), /* Pass in address of contract 45 | * "two". */ 46 | amount: Amount::zero(), 47 | }, 48 | ) 49 | .expect("Initializing valid contract should work"); 50 | 51 | // Invoke the fallback directly. This should fail with execution failure/trap 52 | // because it will redirect to "two." which does not exist. Hence this will fail 53 | // and the fallback will try to look up a non-existing return value. 54 | let res_invoke_1 = chain 55 | .contract_invoke( 56 | helpers::ACC_0, 57 | Address::Account(helpers::ACC_0), 58 | Energy::from(10000), 59 | UpdateContractPayload { 60 | address: res_init_one.contract_address, 61 | receive_name: OwnedReceiveName::new_unchecked("one.".into()), 62 | message: OwnedParameter::empty(), 63 | amount: Amount::zero(), 64 | }, 65 | ) 66 | .expect_err("should fail"); 67 | match res_invoke_1.kind { 68 | ContractInvokeErrorKind::ExecutionError { 69 | failure_kind: InvokeFailure::RuntimeError, 70 | .. 71 | } => (), 72 | _ => panic!("Test failed, expected a runtime error."), 73 | } 74 | 75 | // Invoke "two.do" via "one.do" and the fallback. 76 | let parameter = OwnedParameter::from_serial(&"ASDF").expect("Parameter has valid size."); 77 | let res_invoke_2 = chain 78 | .contract_invoke( 79 | helpers::ACC_0, 80 | Address::Account(helpers::ACC_0), 81 | Energy::from(10000), 82 | UpdateContractPayload { 83 | address: res_init_one.contract_address, 84 | receive_name: OwnedReceiveName::new_unchecked("one.do".into()), 85 | message: parameter.clone(), 86 | amount: Amount::zero(), 87 | }, 88 | ) 89 | .expect("Invoke should succeed."); 90 | assert_eq!(res_invoke_2.return_value, parameter.as_ref()); // Parameter is 91 | // returned 92 | // via the fallback. 93 | } 94 | -------------------------------------------------------------------------------- /contract-testing/tests/helpers/mod.rs: -------------------------------------------------------------------------------- 1 | //! Some helpers and constants that are used in most or all of the tests in this 2 | //! folder. 3 | use concordium_smart_contract_testing::*; 4 | 5 | /// Relative path to the wasm test contracts. 6 | pub(crate) const WASM_TEST_FOLDER: &str = 7 | "../concordium-rust-sdk/concordium-base/smart-contracts/testdata/contracts/v1"; 8 | 9 | /// Test account 0. 10 | pub(crate) const ACC_0: AccountAddress = AccountAddress([0; 32]); 11 | 12 | /// Test account 1. 13 | /// Dead code is allowed to avoid a warning when running `cargo test`. 14 | /// `cargo test` compiles each test module independently and for the ones that 15 | /// do not use `ACC_1` a warning is produced. 16 | #[allow(dead_code)] 17 | pub(crate) const ACC_1: AccountAddress = AccountAddress([1; 32]); 18 | 19 | /// Get the path to a wasm test file in wasm test folder. 20 | /// 21 | /// This is simply prepends the test folder path to the file name: 22 | /// `WASM_TEST_FOLDER/{file_name}`. 23 | pub(crate) fn wasm_test_file(file_name: &str) -> String { 24 | format!("{WASM_TEST_FOLDER}/{file_name}") 25 | } 26 | -------------------------------------------------------------------------------- /contract-testing/tests/iterator.rs: -------------------------------------------------------------------------------- 1 | //! This module tests calling a contract which makes use of an iterator. 2 | //! The checks are being performed in the contract itself so if invoking the 3 | //! contract completes successfully then this implies that the tests have done 4 | //! so as well. Note. as per above no checks are being performed in this file 5 | //! wrt. the state etc. after execution etc. 6 | 7 | use concordium_smart_contract_testing::*; 8 | mod helpers; 9 | 10 | #[test] 11 | fn test_iterator() { 12 | let mut chain = Chain::new(); 13 | let initial_balance = Amount::from_ccd(1000000); 14 | chain.create_account(Account::new(helpers::ACC_0, initial_balance)); 15 | 16 | let res_deploy = chain 17 | .module_deploy_v1( 18 | Signer::with_one_key(), 19 | helpers::ACC_0, 20 | module_load_v1_raw(helpers::wasm_test_file("iterator.wasm")) 21 | .expect("module should exist"), 22 | ) 23 | .expect("Deploying valid module should work"); 24 | 25 | let res_init = chain 26 | .contract_init( 27 | Signer::with_one_key(), 28 | helpers::ACC_0, 29 | Energy::from(10000), 30 | InitContractPayload { 31 | mod_ref: res_deploy.module_reference, 32 | init_name: OwnedContractName::new_unchecked("init_iterator".into()), 33 | param: OwnedParameter::empty(), 34 | amount: Amount::zero(), 35 | }, 36 | ) 37 | .expect("Initializing valid contract should work"); 38 | 39 | chain 40 | .contract_update( 41 | Signer::with_one_key(), 42 | helpers::ACC_0, 43 | Address::Account(helpers::ACC_0), 44 | Energy::from(10000), 45 | UpdateContractPayload { 46 | address: res_init.contract_address, 47 | receive_name: OwnedReceiveName::new_unchecked("iterator.iteratetest".into()), 48 | message: OwnedParameter::empty(), 49 | amount: Amount::zero(), 50 | }, 51 | ) 52 | .expect("Should succeed"); 53 | chain 54 | .contract_update( 55 | Signer::with_one_key(), 56 | helpers::ACC_0, 57 | Address::Account(helpers::ACC_0), 58 | Energy::from(10000), 59 | UpdateContractPayload { 60 | address: res_init.contract_address, 61 | receive_name: OwnedReceiveName::new_unchecked("iterator.lockingtest".into()), 62 | message: OwnedParameter::empty(), 63 | amount: Amount::zero(), 64 | }, 65 | ) 66 | .expect("Should succeed."); 67 | } 68 | -------------------------------------------------------------------------------- /contract-testing/tests/recorder.rs: -------------------------------------------------------------------------------- 1 | //! This module tests basic V1 state operations with the recorder contract. 2 | 3 | use concordium_smart_contract_testing::*; 4 | mod helpers; 5 | 6 | #[test] 7 | fn test_recorder() { 8 | let mut chain = Chain::new(); 9 | let initial_balance = Amount::from_ccd(1000000); 10 | chain.create_account(Account::new(helpers::ACC_0, initial_balance)); 11 | 12 | let res_deploy = chain 13 | .module_deploy_v1( 14 | Signer::with_one_key(), 15 | helpers::ACC_0, 16 | module_load_v1_raw(helpers::wasm_test_file("record-parameters.wasm")) 17 | .expect("module should exist"), 18 | ) 19 | .expect("Deploying valid module should work"); 20 | 21 | let res_init = chain 22 | .contract_init( 23 | Signer::with_one_key(), 24 | helpers::ACC_0, 25 | Energy::from(10000), 26 | InitContractPayload { 27 | mod_ref: res_deploy.module_reference, 28 | init_name: OwnedContractName::new_unchecked("init_recorder".into()), 29 | param: OwnedParameter::empty(), 30 | amount: Amount::zero(), 31 | }, 32 | ) 33 | .expect("Initializing valid contract should work"); 34 | 35 | chain 36 | .contract_update( 37 | Signer::with_one_key(), 38 | helpers::ACC_0, 39 | Address::Account(helpers::ACC_0), 40 | Energy::from(100000), 41 | UpdateContractPayload { 42 | address: res_init.contract_address, 43 | receive_name: OwnedReceiveName::new_unchecked("recorder.record_u64".into()), 44 | message: OwnedParameter::from_serial(&20u64) 45 | .expect("Parameter has valid size"), 46 | amount: Amount::zero(), 47 | }, 48 | ) 49 | .expect("Update failed"); 50 | chain 51 | .contract_update( 52 | Signer::with_one_key(), 53 | helpers::ACC_0, 54 | Address::Account(helpers::ACC_0), 55 | Energy::from(100000), 56 | UpdateContractPayload { 57 | address: res_init.contract_address, 58 | receive_name: OwnedReceiveName::new_unchecked("recorder.record_u64".into()), 59 | message: OwnedParameter::from_serial(&40u64) 60 | .expect("Parameter has valid size"), 61 | amount: Amount::zero(), 62 | }, 63 | ) 64 | .expect("Update failed"); 65 | // Assert that all 60 values were inserted in the state. 66 | for key in 0..60u64 { 67 | assert!(chain 68 | .contract_state_lookup(res_init.contract_address, &u64::to_le_bytes(key)) 69 | .is_some()); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Example contracts 2 | 3 | Example smart contracts illustrating the use of the tools for developing smart 4 | contracts in Rust. 5 | 6 | Contracts are not meant for production, they are used to illustrate how to use 7 | the standard library and the tooling Concordium provides. There is no claim that 8 | the logic of the contract is reasonable, or safe. 9 | 10 | **Do not use these contracts as-is for anything other then experimenting.** 11 | 12 | ## The examples 13 | 14 | The list of contracts is as follows: 15 | 16 | - [account-signature-checks](./account-signature-checks) A simple contract that 17 | demonstrates how account signature checks can be performed in smart contracts. 18 | - [two-step-transfer](./two-step-transfer) A contract that acts like an account (can send, store and accept CCD), 19 | but requires n > 1 ordained accounts to agree to the sending of CCD before it is accepted. 20 | - [auction](./auction) A contract implementing an simple auction. 21 | - [piggy-bank](./piggy-bank) The smart contract created as part of the Piggy Bank tutorial. 22 | - [memo](./memo/) An extremely minimal contract that can be used to 23 | mimic the memo feature. Normally a transfer between accounts cannot add any 24 | information other than the amount being transferred. Making transfers to this 25 | intermediate contract instead works around this limitation. 26 | - [cis2-dynamic-nft](./cis2-dynamic-nft) An example implementation of the CIS-2 Concordium Token Standard 27 | containing dynamic NFTs. 28 | - [cis2-multi](./cis2-multi) An example implementation of the CIS-2 Concordium Token Standard and CIS-3 Concordium Sponsored Transaction Standard containing multiple token types. 29 | - [cis2-multi-royalties](./cis2-multi-royalties) An example implementation of the CIS-2 Concordium Token Standard which allows the token minter to be paid royalties 30 | containing multiple token types. 31 | - [cis2-nft](./cis2-nft) An example implementation of the CIS-2 Concordium Token Standard 32 | containing NFTs. 33 | - [cis2-wccd](./cis2-wccd) An upgradable example implementation of the CIS-2 Concordium Token Standard 34 | containing a single fungible token which is a wrapped CCD. 35 | - [counter-notify](./counter-notify) A contract that works as a counter and can invoke another contract with the current counter value. 36 | - [factory](./factory) An example of implementing a factory pattern with smart contracts. 37 | - [fib](./fib) A contract that calculates and stores the nth Fibonacci number by recursively calling itself. 38 | - [icecream](./icecream) A contract for buying ice cream only when it is sunny. A weather service oracle smart contract is used. 39 | - [proxy](./proxy) A proxy contract that can be put in front of another contract. It works with V0 as well as V1 smart contracts. 40 | - [recorder](./recorder) A contract that records account addresses, and has an entry point to invoke transfers to all those addresses. 41 | - [signature-verifier](./signature-verifier) An example of how to use `crypto_primitives`. The contract verifies an Ed25519 signature. 42 | - [cis5-smart-contract-wallet](./cis5-smart-contract-wallet) An example of how to implement a CIS5 compatible smart contract wallet. 43 | - [nametoken](./nametoken) An example of how to register and manage names as tokens in a smart contract. 44 | - [voting](./voting) An example of how to conduct an election using a smart contract. 45 | - [transfer-policy-check](./transfer-policy-check) A contract that showcases how to use policies. 46 | - [eSealing](./eSealing) A contract implementing an eSealing service. 47 | - [credential-registry](./credential-registry/) A contract for storing and managing public data of verifiable credentials. 48 | - [sponsoredTransactions](./cis3-nft-sponsored-txs) A contract implementing the sponsored transaction mechanism (CIS3 standard). 49 | - [smartContractUpgrade](./smart-contract-upgrade) An example of how to upgrade a smart contract. The state is migrated during the upgrade. 50 | 51 | ## Running the tests 52 | 53 | To run the tests for an example contract in the folder `EXAMPLE` open a terminal an run the following commands: 54 | 55 | 1. `cd EXAMPLE` 56 | 2. `cargo concordium test --out concordium-out/module.wasm.v1` 57 | 58 | The smart contract upgrade example has specific instructions for running the tests. See the module documentation in `./smart-contract-upgrade/contract-version1/tests/tests.rs`. 59 | 60 | To learn more about testing contracts, please refer to [our integration testing documentation](https://developer.concordium.software/en/mainnet/smart-contracts/guides/integration-test-contract.html). 61 | -------------------------------------------------------------------------------- /examples/account-signature-checks/Cargo.toml: -------------------------------------------------------------------------------- 1 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 2 | 3 | [package] 4 | name = "account_signature_checks" 5 | version = "0.1.0" 6 | edition = "2021" 7 | license = "MPL-2.0" 8 | authors = [ "Concordium " ] 9 | description = "An example of how to check account signatures" 10 | 11 | [features] 12 | default = ["std"] 13 | std = ["concordium-std/std"] 14 | bump_alloc = ["concordium-std/bump_alloc"] 15 | 16 | [dependencies] 17 | concordium-std = {path = "../../concordium-std", default-features = false} 18 | 19 | [lib] 20 | crate-type=["cdylib", "rlib"] 21 | 22 | [profile.release] 23 | opt-level = "s" 24 | codegen-units = 1 25 | -------------------------------------------------------------------------------- /examples/account-signature-checks/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | 3 | //! A basic example showing how to retrieve account keys, and check account 4 | //! signatures. 5 | use concordium_std::*; 6 | use core::fmt::Debug; 7 | 8 | #[derive(Debug, PartialEq, Eq, Reject, Serial, SchemaType)] 9 | enum Error { 10 | /// Failed parsing the parameter. 11 | #[from(ParseError)] 12 | ParseParams, 13 | /// Account that we wanted was not present. 14 | MissingAccount, 15 | /// Signature data was malformed. 16 | MalformedData, 17 | } 18 | 19 | impl From for Error { 20 | fn from(value: CheckAccountSignatureError) -> Self { 21 | match value { 22 | CheckAccountSignatureError::MissingAccount => Self::MissingAccount, 23 | CheckAccountSignatureError::MalformedData => Self::MalformedData, 24 | } 25 | } 26 | } 27 | 28 | impl From for Error { 29 | fn from(QueryAccountPublicKeysError: QueryAccountPublicKeysError) -> Self { 30 | Self::MissingAccount 31 | } 32 | } 33 | 34 | /// We don't need state for this specific demonstration. 35 | #[derive(Serialize)] 36 | struct State {} 37 | 38 | /// Init function that creates a new smart contract. 39 | #[init(contract = "account_signature_checks")] 40 | fn init(_ctx: &InitContext, _state_builder: &mut StateBuilder) -> InitResult { Ok(State {}) } 41 | 42 | #[derive(Deserial, SchemaType)] 43 | struct CheckParam { 44 | address: AccountAddress, 45 | sigs: AccountSignatures, 46 | #[concordium(size_length = 4)] 47 | data: Vec, 48 | } 49 | 50 | /// View function that checks the signature with account keys on the provided 51 | /// data. 52 | #[receive( 53 | contract = "account_signature_checks", 54 | name = "check", 55 | parameter = "CheckParam", 56 | error = "Error", 57 | return_value = "bool" 58 | )] 59 | fn check(ctx: &ReceiveContext, host: &Host) -> Result { 60 | let param: CheckParam = ctx.parameter_cursor().get()?; 61 | let r = host.check_account_signature(param.address, ¶m.sigs, ¶m.data)?; 62 | Ok(r) 63 | } 64 | 65 | /// View function that returns the account's public keys. 66 | #[receive( 67 | contract = "account_signature_checks", 68 | name = "view_keys", 69 | parameter = "AccountAddress", 70 | return_value = "AccountPublicKeys" 71 | )] 72 | fn view_keys(ctx: &ReceiveContext, host: &Host) -> Result { 73 | let param: AccountAddress = ctx.parameter_cursor().get()?; 74 | let pk = host.account_public_keys(param)?; 75 | Ok(pk) 76 | } 77 | -------------------------------------------------------------------------------- /examples/auction/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "auction-smart-contract" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | [features] 10 | default = ["std", "bump_alloc"] 11 | std = ["concordium-std/std"] 12 | bump_alloc = ["concordium-std/bump_alloc"] 13 | 14 | [dependencies] 15 | concordium-std = {path = "../../concordium-std", default-features = false} 16 | 17 | [dev-dependencies] 18 | concordium-smart-contract-testing = { path = "../../contract-testing" } 19 | concordium-std-derive = { path = "../../concordium-std-derive" } 20 | 21 | [lib] 22 | crate-type=["cdylib", "rlib"] 23 | -------------------------------------------------------------------------------- /examples/bump-alloc-tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bump_alloc_tests" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [features] 11 | default = ["std"] 12 | std = ["concordium-std/std"] 13 | bump_alloc = ["concordium-std/bump_alloc"] 14 | 15 | [dependencies] 16 | concordium-std = {path = "../../concordium-std", default-features = false, features = ["bump_alloc"]} 17 | 18 | [dev-dependencies] 19 | concordium-smart-contract-testing = { path = "../../contract-testing" } 20 | 21 | [lib] 22 | crate-type=["cdylib", "rlib"] 23 | -------------------------------------------------------------------------------- /examples/cis2-dynamic-nft/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cis2_dynamic_nft" 3 | version = "0.1.0" 4 | authors = [ "Concordium " ] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | description = "An example implementation of the CIS-2 Concordium Token Standard containing dynamic NFTs" 8 | 9 | [features] 10 | default = ["std"] 11 | std = ["concordium-std/std", "concordium-cis2/std"] 12 | bump_alloc = ["concordium-std/bump_alloc"] 13 | 14 | [dependencies] 15 | concordium-std = {path = "../../concordium-std", default-features = false} 16 | concordium-cis2 = {path = "../../concordium-cis2", default-features = false} 17 | 18 | [dev-dependencies] 19 | concordium-smart-contract-testing = { path = "../../contract-testing" } 20 | concordium-std-derive = { path = "../../concordium-std-derive" } 21 | 22 | [lib] 23 | crate-type=["cdylib", "rlib"] 24 | 25 | [profile.release] 26 | codegen-units = 1 27 | opt-level = "s" 28 | -------------------------------------------------------------------------------- /examples/cis2-multi-royalties/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cis2-multi-royalties" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | [features] 9 | default = ["std", "bump_alloc"] 10 | std = ["concordium-std/std", "concordium-cis2/std"] 11 | bump_alloc = ["concordium-std/bump_alloc"] 12 | 13 | [dependencies] 14 | concordium-std = {path = "../../concordium-std", default-features = false} 15 | concordium-cis2 = {path = "../../concordium-cis2", default-features = false} 16 | 17 | [dev-dependencies] 18 | concordium-smart-contract-testing = { path = "../../contract-testing" } 19 | concordium-std-derive = { path = "../../concordium-std-derive" } 20 | 21 | [lib] 22 | crate-type=["cdylib", "rlib"] 23 | 24 | [profile.release] 25 | codegen-units = 1 26 | opt-level = "s" 27 | -------------------------------------------------------------------------------- /examples/cis2-multi/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cis2-multi" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | [features] 9 | default = ["std", "bump_alloc"] 10 | std = ["concordium-std/std", "concordium-cis2/std"] 11 | bump_alloc = ["concordium-std/bump_alloc"] 12 | 13 | [dependencies] 14 | concordium-std = {path = "../../concordium-std", default-features = false} 15 | concordium-cis2 = {path = "../../concordium-cis2", default-features = false} 16 | 17 | [dev-dependencies] 18 | concordium-smart-contract-testing = {path = "../../contract-testing"} 19 | concordium-std-derive = { path = "../../concordium-std-derive" } 20 | rand = "0.8" 21 | 22 | [lib] 23 | crate-type=["cdylib", "rlib"] 24 | 25 | [profile.release] 26 | codegen-units = 1 27 | opt-level = "s" 28 | -------------------------------------------------------------------------------- /examples/cis2-nft/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cis2_nft" 3 | version = "0.1.0" 4 | authors = [ "Concordium " ] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | description = "cis2-nft-project" 8 | 9 | [features] 10 | default = ["std"] 11 | std = ["concordium-std/std", "concordium-cis2/std"] 12 | bump_alloc = ["concordium-std/bump_alloc"] 13 | 14 | [dependencies] 15 | concordium-std = {path = "../../concordium-std", default-features = false} 16 | concordium-cis2 = {path = "../../concordium-cis2", default-features = false} 17 | 18 | [dev-dependencies] 19 | concordium-smart-contract-testing = {path = "../../contract-testing"} 20 | concordium-std-derive = {path = "../../concordium-std-derive"} 21 | 22 | [lib] 23 | crate-type=["cdylib", "rlib"] 24 | 25 | [profile.release] 26 | codegen-units = 1 27 | opt-level = "s" 28 | -------------------------------------------------------------------------------- /examples/cis2-wccd/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cis2_wccd" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | [features] 9 | default = ["std", "bump_alloc"] 10 | std = ["concordium-std/std", "concordium-cis2/std"] 11 | bump_alloc = ["concordium-std/bump_alloc"] 12 | 13 | [dependencies] 14 | concordium-std = {path = "../../concordium-std", default-features = false} 15 | concordium-cis2 = {path = "../../concordium-cis2", default-features = false} 16 | 17 | [dev-dependencies] 18 | concordium-smart-contract-testing = { path = "../../contract-testing" } 19 | concordium-std-derive = { path = "../../concordium-std-derive" } 20 | 21 | [lib] 22 | crate-type=["cdylib", "rlib"] 23 | 24 | [profile.release] 25 | opt-level = "s" 26 | codegen-units = 1 27 | -------------------------------------------------------------------------------- /examples/cis3-nft-sponsored-txs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cis3_nft_sponsored_txs" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | [features] 9 | default = ["std", "bump_alloc"] 10 | std = ["concordium-std/std", "concordium-cis2/std"] 11 | bump_alloc = ["concordium-std/bump_alloc"] 12 | 13 | [dependencies] 14 | concordium-std = {path = "../../concordium-std", default-features = false} 15 | concordium-cis2 = {path = "../../concordium-cis2", default-features = false} 16 | 17 | [dev-dependencies] 18 | concordium-smart-contract-testing = { path = "../../contract-testing" } 19 | concordium-std-derive = { path = "../../concordium-std-derive" } 20 | rand = "0.8" 21 | 22 | [lib] 23 | crate-type=["cdylib", "rlib"] 24 | 25 | [profile.release] 26 | panic = "abort" 27 | opt-level = "s" 28 | codegen-units = 1 29 | -------------------------------------------------------------------------------- /examples/cis3-nft-sponsored-txs/README.md: -------------------------------------------------------------------------------- 1 | **Sponsored Transaction Smart Contract** 2 | 3 | **Prerequisites** 4 | 5 | `cargo/rustup` and `cargo-concordium` needs to be [set up](https://developer.concordium.software/en/mainnet/smart-contracts/guides/quick-start.html). 6 | 7 | **Commands** 8 | 9 | Run the following command to compile the smart contract into the wasm module `contract.wasm.v1` with embedded schema: 10 | 11 | ``` 12 | cargo concordium build -e --out contract.wasm.v1 13 | ``` 14 | 15 | Run the following command to run the unit and integration tests: 16 | 17 | ``` 18 | cargo concordium test 19 | ``` 20 | ``` 21 | cargo test 22 | ``` 23 | -------------------------------------------------------------------------------- /examples/cis5-smart-contract-wallet/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "smart-contract-wallet" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | [features] 9 | default = ["std", "bump_alloc"] 10 | std = ["concordium-std/std", "concordium-cis2/std"] 11 | bump_alloc = ["concordium-std/bump_alloc"] 12 | serde = [ 13 | "concordium-contracts-common/derive-serde", 14 | "concordium-cis2/serde", 15 | "dep:serde", 16 | ] 17 | 18 | [dependencies] 19 | concordium-std = { path = "../../concordium-std", default-features = false } 20 | concordium-cis2 = { path = "../../concordium-cis2", default-features = false, features = [ 21 | "u256_amount", 22 | ] } 23 | serde = { version = "1.0", optional = true, default-features = false, features = [ 24 | "derive", 25 | ] } 26 | concordium-contracts-common = "*" 27 | 28 | [dev-dependencies] 29 | concordium-smart-contract-testing = { path = "../../contract-testing" } 30 | cis2-multi = { path = "../cis2-multi" } 31 | ed25519-dalek = { version = "2.0", features = ["rand_core"] } 32 | rand = "0.8" 33 | 34 | [lib] 35 | crate-type = ["cdylib", "rlib"] 36 | 37 | [profile.release] 38 | codegen-units = 1 39 | opt-level = "s" 40 | -------------------------------------------------------------------------------- /examples/counter-notify/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "counter-notify" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [features] 11 | default = ["std", "bump_alloc"] 12 | std = ["concordium-std/std"] 13 | bump_alloc = ["concordium-std/bump_alloc"] 14 | 15 | [dependencies] 16 | concordium-std = {path = "../../concordium-std", default-features = false} 17 | 18 | [dev-dependencies] 19 | concordium-smart-contract-testing = { path = "../../contract-testing" } 20 | concordium-std-derive = { path = "../../concordium-std-derive" } 21 | 22 | [lib] 23 | crate-type=["cdylib", "rlib"] 24 | -------------------------------------------------------------------------------- /examples/counter-notify/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! An example of reentrancy attacks. 2 | //! 3 | //! Consists of two contracts: 4 | //! - `counter-notify` 5 | //! - A counter contract that also notifies some contract about increments. 6 | //! - After the notification call it checks to see that its counter hasn't 7 | //! been altered. 8 | //! - `reentrancy-attacker` 9 | //! - A contract that tries to make an reentrancy attack on the 10 | //! `counter-notify` contract. 11 | #![cfg_attr(not(feature = "std"), no_std)] 12 | use concordium_std::*; 13 | 14 | type State = u64; 15 | 16 | #[derive(Serial, Deserial, PartialEq)] 17 | pub enum ReentryOccurance { 18 | NoReentryAttack, 19 | ReentryAttack, 20 | } 21 | 22 | #[init(contract = "counter-notify")] 23 | #[inline(always)] 24 | fn contract_init(_ctx: &InitContext, _state_builder: &mut StateBuilder) -> InitResult { 25 | Ok(0u64) 26 | } 27 | 28 | #[receive(contract = "counter-notify", name = "just-increment", mutable)] 29 | fn just_increment(_ctx: &ReceiveContext, host: &mut Host) -> ReceiveResult<()> { 30 | *host.state_mut() += 1; 31 | Ok(()) 32 | } 33 | 34 | #[receive( 35 | contract = "counter-notify", 36 | name = "increment-and-notify", 37 | mutable, 38 | parameter = "(ContractAddress, OwnedEntrypointName)", 39 | return_value = "ReentryOccurance" 40 | )] 41 | fn increment_and_notify( 42 | ctx: &ReceiveContext, 43 | host: &mut Host, 44 | ) -> ReceiveResult { 45 | let (contract, entrypoint): (ContractAddress, OwnedEntrypointName) = 46 | ctx.parameter_cursor().get()?; 47 | 48 | // Increment counter 49 | *host.state_mut() += 1; 50 | let preinvoke_count = *host.state(); 51 | 52 | // Notify a contract about the new counter value. 53 | host.invoke_contract( 54 | &contract, 55 | &preinvoke_count, 56 | entrypoint.as_entrypoint_name(), 57 | Amount::zero(), 58 | ) 59 | .unwrap_abort(); 60 | 61 | let is_reentry = if preinvoke_count != *host.state() { 62 | ReentryOccurance::ReentryAttack 63 | } else { 64 | ReentryOccurance::NoReentryAttack 65 | }; 66 | 67 | Ok(is_reentry) 68 | } 69 | 70 | //////////////////////////////////////////////////////////////////////////////////////////////// 71 | 72 | #[init(contract = "reentrancy-attacker")] 73 | fn reentrancy_init(_ctx: &InitContext, _state_builder: &mut StateBuilder) -> InitResult<()> { 74 | Ok(()) 75 | } 76 | 77 | /// Tries to call the entrypoint `just-increment` on the sender iff it is a 78 | /// contract. Fails if the sender is an account or the `just-increment` call 79 | /// fails. 80 | #[receive(contract = "reentrancy-attacker", name = "call-just-increment", mutable)] 81 | fn reentrancy_receive(ctx: &ReceiveContext, host: &mut Host<()>) -> ReceiveResult<()> { 82 | match ctx.sender() { 83 | Address::Account(_) => fail!(), 84 | Address::Contract(contract) => { 85 | host.invoke_contract( 86 | &contract, 87 | &(), 88 | EntrypointName::new_unchecked("just-increment"), 89 | Amount::zero(), 90 | ) 91 | .unwrap(); 92 | Ok(()) 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /examples/credential-registry/Cargo.toml: -------------------------------------------------------------------------------- 1 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 2 | 3 | [package] 4 | name = "credential_registry" 5 | version = "0.1.0" 6 | edition = "2021" 7 | license = "MPL-2.0" 8 | authors = [ "Concordium " ] 9 | description = "Example-credential-registry" 10 | 11 | [features] 12 | default = ["std", "crypto-primitives", "bump_alloc"] 13 | std = ["concordium-std/std", "concordium-cis2/std"] 14 | bump_alloc = ["concordium-std/bump_alloc"] 15 | crypto-primitives = ["concordium-std/crypto-primitives"] 16 | 17 | [dependencies] 18 | concordium-std = {path = "../../concordium-std", version = "10.0", default-features = false, features = ["concordium-quickcheck"]} 19 | concordium-cis2 = {path = "../../concordium-cis2", version = "6.1", default-features = false} 20 | quickcheck = {version = "1"} 21 | 22 | [dev-dependencies] 23 | concordium-smart-contract-testing = {path = "../../contract-testing"} 24 | concordium-std-derive = {path = "../../concordium-std-derive"} 25 | 26 | [lib] 27 | crate-type=["cdylib", "rlib"] 28 | 29 | [profile.release] 30 | opt-level = "s" 31 | codegen-units = 1 32 | -------------------------------------------------------------------------------- /examples/credential-registry/README.md: -------------------------------------------------------------------------------- 1 | # Credential registry contract 2 | 3 | This smart contract implements an example on-chain registry for the public 4 | part of verifiable credentials (VCs). The contract follows CIS-4: Credential 5 | Registry Standard. 6 | 7 | The contract keeps track of credentials' public data, allows managing the 8 | VC life cycle, and querying VCs data and status. The intended users are 9 | issuers of VCs, holders of VCs, revocation authorities, and verifiers. 10 | 11 | When initializing a contract, the issuer provides a type and a schema 12 | reference for the credentials in the registry. The schema reference points 13 | to a JSON document describing the structure of verifiable credentials in the 14 | registry (attributes and their types). If the issuer wants to issue 15 | verifiable credentials of several types, they can deploy several instances 16 | of this contract with different credential types. 17 | 18 | ## Issuer's functionality 19 | 20 | - register/remove revocation authority keys; 21 | - register a new credential; 22 | - revoke a credential; 23 | - update the issuer's metadata; 24 | - update the credential metadata; 25 | - update credential schema reference; 26 | - upgrade the contract, set implementors; 27 | - restore (cancel revocation of) a revoked credential. 28 | 29 | ## Holder's functionality 30 | 31 | - revoke a credential by signing a revocation message. 32 | 33 | ## Revocation authority's functionality 34 | 35 | Revocation authorities are some entities chosen by the issuer that have 36 | revocation capabilities. Their public keys are registered by the issuer and 37 | a revocation authority signs a revocation message with the corresponding 38 | private key. 39 | 40 | - revoke a credential by signing a revocation message. 41 | 42 | ## Verifier's functionality 43 | 44 | - view credential status to verify VC validity; 45 | - view credential data to verify proofs (verifiable presentations) requested 46 | from holders. 47 | -------------------------------------------------------------------------------- /examples/eSealing/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "e_sealing" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | [features] 9 | default = ["std", "bump_alloc"] 10 | std = ["concordium-std/std"] 11 | bump_alloc = ["concordium-std/bump_alloc"] 12 | 13 | [dependencies] 14 | concordium-std = {path = "../../concordium-std", default-features = false} 15 | 16 | [dev-dependencies] 17 | concordium-smart-contract-testing = { path = "../../contract-testing" } 18 | concordium-std-derive = { path = "../../concordium-std-derive" } 19 | 20 | [lib] 21 | crate-type=["cdylib", "rlib"] 22 | 23 | [profile.release] 24 | opt-level = "s" 25 | codegen-units = 1 26 | -------------------------------------------------------------------------------- /examples/factory/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "factory-smart-contract" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | [features] 10 | default = ["std", "bump_alloc"] 11 | std = ["concordium-std/std"] 12 | bump_alloc = ["concordium-std/bump_alloc"] 13 | 14 | [dependencies] 15 | concordium-std = { path = "../../concordium-std", version = "10.0", default-features = false, features = [ 16 | "p7", 17 | ] } 18 | 19 | [dev-dependencies] 20 | concordium-smart-contract-testing = { path = "../../contract-testing" } 21 | 22 | [lib] 23 | crate-type = ["cdylib", "rlib"] 24 | -------------------------------------------------------------------------------- /examples/fib/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fib" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [features] 11 | default = ["std", "bump_alloc"] 12 | std = ["concordium-std/std"] 13 | bump_alloc = ["concordium-std/bump_alloc"] 14 | 15 | [dependencies] 16 | concordium-std = {path = "../../concordium-std", default-features = false} 17 | 18 | [dev-dependencies] 19 | concordium-smart-contract-testing = { path = "../../contract-testing"} 20 | concordium-std-derive = { path = "../../concordium-std-derive" } 21 | 22 | [lib] 23 | crate-type=["cdylib", "rlib"] 24 | -------------------------------------------------------------------------------- /examples/fib/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | use concordium_std::*; 3 | 4 | #[derive(Serialize, Clone)] 5 | pub struct State { 6 | result: u64, 7 | } 8 | 9 | #[init(contract = "fib")] 10 | #[inline(always)] 11 | fn contract_init(_ctx: &InitContext, _state_builder: &mut StateBuilder) -> InitResult { 12 | let state = State { 13 | result: 0, 14 | }; 15 | Ok(state) 16 | } 17 | 18 | // Add the the nth Fibonacci number F(n) to this contract's state. 19 | // This is achieved by recursively calling the contract itself. 20 | #[inline(always)] 21 | #[receive(contract = "fib", name = "receive", parameter = "u64", return_value = "u64", mutable)] 22 | fn contract_receive(ctx: &ReceiveContext, host: &mut Host) -> ReceiveResult { 23 | // Try to get the parameter (64bit unsigned integer). 24 | let n: u64 = ctx.parameter_cursor().get()?; 25 | if n <= 1 { 26 | host.state_mut().result = 1; 27 | Ok(1) 28 | } else { 29 | let self_address = ctx.self_address(); 30 | let mut n2 = host 31 | .invoke_contract_raw( 32 | &self_address, 33 | Parameter::new_unchecked(&(n - 2).to_le_bytes()[..]), 34 | EntrypointName::new_unchecked("receive"), 35 | Amount::zero(), 36 | ) 37 | .unwrap_abort() 38 | .1 39 | .unwrap_abort(); 40 | let cv2 = host.state().result; 41 | let n2: u64 = n2.get().unwrap_abort(); 42 | ensure_eq!(cv2, n2); 43 | let mut n1 = host 44 | .invoke_contract_raw( 45 | &self_address, 46 | Parameter::new_unchecked(&(n - 1).to_le_bytes()[..]), 47 | EntrypointName::new_unchecked("receive"), 48 | Amount::zero(), 49 | ) 50 | .unwrap_abort() 51 | .1 52 | .unwrap_abort(); 53 | let cv1 = host.state().result; 54 | let n1: u64 = n1.get().unwrap_abort(); 55 | ensure_eq!(cv1, n1); 56 | host.state_mut().result = cv1 + cv2; 57 | Ok(cv1 + cv2) 58 | } 59 | } 60 | 61 | /// Retrieve the value of the state. 62 | #[inline(always)] 63 | #[receive(contract = "fib", name = "view", return_value = "u64")] 64 | fn contract_view(_ctx: &ReceiveContext, host: &Host) -> ReceiveResult { 65 | Ok(host.state().result) 66 | } 67 | -------------------------------------------------------------------------------- /examples/fib/tests/tests.rs: -------------------------------------------------------------------------------- 1 | use concordium_smart_contract_testing::*; 2 | use concordium_std_derive::*; 3 | 4 | const ACC_0: AccountAddress = 5 | account_address!("2wkBET2rRgE8pahuaczxKbmv7ciehqsne57F9gtzf1PVdr2VP3"); 6 | const SIGNER: Signer = Signer::with_one_key(); 7 | 8 | /// Compute the n-th fibonacci number. 9 | fn fib(n: u64) -> u64 { 10 | let mut n1 = 1; 11 | let mut n2 = 1; 12 | for _ in 2..=n { 13 | let t = n1; 14 | n1 = n2; 15 | n2 += t; 16 | } 17 | n2 18 | } 19 | 20 | /// Test that calling the `receive` entrypoint produces the correct fib value in 21 | /// the state. 22 | #[test] 23 | fn test() { 24 | // Create the test chain. 25 | let mut chain = Chain::new(); 26 | 27 | // Create two accounts on the chain. 28 | chain.create_account(Account::new(ACC_0, Amount::from_ccd(1000))); 29 | 30 | // Load and deploy the module. 31 | let module = module_load_v1("concordium-out/module.wasm.v1").expect("Module exists"); 32 | let deployment = chain.module_deploy_v1(SIGNER, ACC_0, module).expect("Deploy valid module"); 33 | 34 | // Initialize the contract. 35 | let initialization = chain 36 | .contract_init(SIGNER, ACC_0, Energy::from(10000), InitContractPayload { 37 | amount: Amount::zero(), 38 | mod_ref: deployment.module_reference, 39 | init_name: OwnedContractName::new_unchecked("init_fib".to_string()), 40 | param: OwnedParameter::empty(), 41 | }) 42 | .expect("Init should succeed"); 43 | let contract_address = initialization.contract_address; 44 | 45 | // Call the `receive` entrypoint with `7` as input. 46 | let update = chain 47 | .contract_update( 48 | SIGNER, 49 | ACC_0, 50 | Address::Account(ACC_0), 51 | Energy::from(50000), 52 | UpdateContractPayload { 53 | amount: Amount::zero(), 54 | address: contract_address, 55 | receive_name: OwnedReceiveName::new_unchecked("fib.receive".to_string()), 56 | message: OwnedParameter::from_serial(&7u64) 57 | .expect("Parameter has valid size."), 58 | }, 59 | ) 60 | .expect("Calling receive"); 61 | 62 | let rv: u64 = update.parse_return_value().expect("Return value"); 63 | assert_eq!(rv, fib(7)); 64 | 65 | // Check that the result is persisted by invoking the `view` entrypoint. 66 | let update = chain 67 | .contract_invoke( 68 | ACC_0, 69 | Address::Account(ACC_0), 70 | Energy::from(50000), 71 | UpdateContractPayload { 72 | amount: Amount::zero(), 73 | address: contract_address, 74 | receive_name: OwnedReceiveName::new_unchecked("fib.view".to_string()), 75 | message: OwnedParameter::empty(), 76 | }, 77 | ) 78 | .expect("Calling receive"); 79 | 80 | let rv: u64 = update.parse_return_value().expect("Return value"); 81 | assert_eq!(rv, fib(7)); 82 | } 83 | -------------------------------------------------------------------------------- /examples/icecream/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "icecream" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | concordium-std = {path = "../../concordium-std"} 12 | 13 | [dev-dependencies] 14 | concordium-smart-contract-testing = { path = "../../contract-testing" } 15 | concordium-std-derive = { path = "../../concordium-std-derive" } 16 | 17 | [features] 18 | default = ["std", "bump_alloc"] 19 | std = ["concordium-std/std"] 20 | bump_alloc = ["concordium-std/bump_alloc"] 21 | 22 | [lib] 23 | crate-type=["cdylib", "rlib"] 24 | -------------------------------------------------------------------------------- /examples/memo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "memo-proxy-contract" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | # concordium-std = "*" 12 | concordium-std = {path = "../../concordium-std"} 13 | 14 | [features] 15 | default = ["std", "bump_alloc"] 16 | std = ["concordium-std/std"] 17 | bump_alloc = ["concordium-std/bump_alloc"] 18 | 19 | [lib] 20 | crate-type=["cdylib", "rlib"] 21 | 22 | 23 | [profile.release] 24 | opt-level = 3 25 | panic = "abort" 26 | -------------------------------------------------------------------------------- /examples/memo/src/lib.rs: -------------------------------------------------------------------------------- 1 | use concordium_std::*; 2 | 3 | /// # Implementation of a smart contract that can receive transfers with a memo 4 | /// message and forward them to the owner account. 5 | /// All this contract does is expose a single `receive` method which checks that 6 | /// 7 | /// - it is being invoked by an account 8 | /// - the message it is receiving is 32 bytes long 9 | /// 10 | /// And if both of these are valid it forwards the amount it received to the 11 | /// owner account. 12 | 13 | #[derive(Serialize, SchemaType)] 14 | /// The contract has no initialization parameters. 15 | struct InitParameter; 16 | 17 | /// Init function that creates a new contract. 18 | #[init(contract = "memo", parameter = "InitParameter")] 19 | fn memo_init(_ctx: &InitContext, _state_builder: &mut StateBuilder) -> InitResult<()> { Ok(()) } 20 | 21 | const EXPECTED_PARAMETER_SIZE: u32 = 32; 22 | 23 | pub type ReceiveParameter = [u8; 32]; 24 | 25 | /// The different errors the contract can produce. 26 | #[derive(Serialize, Debug, PartialEq, Eq, Reject, SchemaType)] 27 | enum CustomContractError { 28 | InvokeTransferError, 29 | } 30 | 31 | /// Mapping errors related to transfer invocations to CustomContractError. 32 | impl From for CustomContractError { 33 | fn from(_te: TransferError) -> Self { Self::InvokeTransferError } 34 | } 35 | 36 | #[derive(Serialize)] 37 | struct State; 38 | 39 | /// Receive a transaction with a message. This ensures that the message is 32 40 | /// bytes and that the sender of the message is an account. 41 | #[receive( 42 | contract = "memo", 43 | name = "receive", 44 | parameter = "ReceiveParameter", 45 | payable, 46 | error = "CustomContractError" 47 | )] 48 | fn memo_receive(ctx: &ReceiveContext, host: &Host, amount: Amount) -> ReceiveResult<()> { 49 | ensure!(matches!(ctx.sender(), Address::Account(..))); 50 | ensure!(ctx.parameter_cursor().size() == EXPECTED_PARAMETER_SIZE); 51 | host.invoke_transfer(&ctx.owner(), amount)?; 52 | Ok(()) 53 | } 54 | -------------------------------------------------------------------------------- /examples/nametoken/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "nametoken" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | [features] 9 | default = ["std", "bump_alloc"] 10 | std = ["concordium-std/std", "concordium-cis2/std"] 11 | bump_alloc = ["concordium-std/bump_alloc"] 12 | 13 | [dependencies] 14 | concordium-std = {path = "../../concordium-std", default-features = false} 15 | concordium-cis2 = {path = "../../concordium-cis2", default-features = false} 16 | 17 | [dev-dependencies] 18 | concordium-smart-contract-testing = { path = "../../contract-testing" } 19 | concordium-std-derive = { path = "../../concordium-std-derive" } 20 | 21 | [lib] 22 | crate-type=["cdylib", "rlib"] 23 | 24 | [profile.release] 25 | codegen-units = 1 26 | opt-level = "s" 27 | -------------------------------------------------------------------------------- /examples/offchain-transfers/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "offchain-transfer" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2018" 6 | license = "MPL-2.0" 7 | description = "Offchain transfer settlement smart contract." 8 | readme = "./README.md" 9 | 10 | [features] 11 | default = ["std"] 12 | std = ["concordium-std/std"] 13 | 14 | [dependencies] 15 | byteorder = "1.3" 16 | concordium-std = {path = "../../concordium-std", default-features = false} 17 | 18 | [lib] 19 | crate-type = ["cdylib", "rlib"] 20 | 21 | [profile.release] 22 | opt-level = 3 23 | -------------------------------------------------------------------------------- /examples/offchain-transfers/README.md: -------------------------------------------------------------------------------- 1 | # Settlement Layer for Off-Chain Transfers 2 | 3 | An example implementation of an optimistic settlement layer for off-chain transactions. 4 | 5 | **Warning** 6 | This contract is is **UNSUITABLE FOR DEPLOYMENT**, and **PROVIDED AS Proof-Of-Concept ONLY**. 7 | 8 | # Description 9 | This contract implements a simple settlement mechanism for off-chain payments. It is an example of so-called "rollups" since it allows to roll multiple off-chain transaction up into a single on-chain settlement transaction (and thereby save transaction fees). 10 | The intended use of the contract is as follows: 11 | * The smart contract is initialized by appointing a "judge" and a "validator", and setting a "time to finality" duration. 12 | * Users deposit a collateral to the smart contract. This adds the deposited amount to the available balance in the balance sheet of the smart contract. 13 | * Afterwards, users can transact off-chain using their deposited collateral as balance. 14 | * Once users are done with their off-chain transactions, the validator can settle the transactions by adding a settlement to the contract. A settlement is described by a transfer, i.e., addresses and amounts specifying which addresses have to pay which amounts and which addresses receive which amounts, respectively. Settlements can only be added by the validator to prevent DoS attacks. 15 | * After a settlement, users can already (optimistically) use the updated balances from that settlement off-chain and in future settlements. Withdrawing received amounts, however, is only possible after the settlement was finalized. 16 | * If users object to a published settlement, they can off-chain complain to the judge. If the judge deems a settlement invalid before it has been finalized, the judge can veto it. 17 | * Settlements that have not been vetoed for the "time to finality" duration become finalized and cannot be reverted anymore. 18 | * The smart contract can be called by anyone to execute all finalized settlements and to update the balance sheet accordingly. 19 | * Users can withdraw funds from the smart contract. The maximal allowed amount to withdraw corresponds to the worst-case amount that is guaranteed to be available no matter which outstanding settlements are vetoed. 20 | -------------------------------------------------------------------------------- /examples/piggy-bank/README.md: -------------------------------------------------------------------------------- 1 | # Piggy bank tutorial examples 2 | 3 | These examples are developed as part of an upcoming tutorial about smart 4 | contract development. 5 | 6 | The tutorial is split into parts with focus on a different topic: 7 | 8 | - **part1**: Writing the smart contract logic. 9 | - **part2**: Unit tests and simulating the smart contract. 10 | 11 | -------------------------------------------------------------------------------- /examples/piggy-bank/part1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "piggy-bank-part1" 3 | version = "0.1.1" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | description = "Piggy bank smart contract part 1." 8 | homepage = "https://github.com/concordium/concordium-rust-smart-contracts" 9 | repository = "https://github.com/concordium/concordium-rust-smart-contracts" 10 | readme = "../README.md" 11 | 12 | [lib] 13 | crate-type = ["cdylib", "rlib"] 14 | 15 | [features] 16 | default = ["std", "bump_alloc"] 17 | std = ["concordium-std/std"] 18 | bump_alloc = ["concordium-std/bump_alloc"] 19 | 20 | [dependencies.concordium-std] 21 | version = "10" 22 | path = "../../../concordium-std" 23 | default-features = false 24 | 25 | [profile.release] 26 | opt-level = 3 27 | -------------------------------------------------------------------------------- /examples/piggy-bank/part1/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Piggy bank smart contract. 2 | //! 3 | //! Allows anyone to insert CCD, but only the owner can "smash" it and 4 | //! retrieve the CCD. Prevents more CCD to be inserted after being smashed. 5 | //! 6 | //! This smart contract module is developed as part of the 7 | //! [Piggy Bank Tutorial](https://developer.concordium.software/en/mainnet/smart-contracts/tutorials/piggy-bank). 8 | //! 9 | //! Covers: 10 | //! - Reading owner, sender, and self_balance from the context and host. 11 | //! - The `ensure` macro. 12 | //! - The `payable` attribute. 13 | //! - The `mutable` attribute. 14 | //! - Invoking a transfer with the host. 15 | 16 | // Pulling in everything from the smart contract standard library. 17 | use concordium_std::*; 18 | 19 | /// The state of the piggy bank 20 | #[derive(Debug, SchemaType, Serialize, PartialEq, Eq, Clone, Copy)] 21 | enum PiggyBankState { 22 | /// Alive and well, allows for CCD to be inserted. 23 | Intact, 24 | /// The piggy bank has been emptied, preventing further CCD to be inserted. 25 | Smashed, 26 | } 27 | 28 | /// Setup a new Intact piggy bank. 29 | #[init(contract = "PiggyBank")] 30 | fn piggy_init(_ctx: &InitContext, _state_builder: &mut StateBuilder) -> InitResult { 31 | // Always succeeds 32 | Ok(PiggyBankState::Intact) 33 | } 34 | 35 | /// Insert some CCD into a piggy bank, allowed by anyone. 36 | #[receive(contract = "PiggyBank", name = "insert", payable)] 37 | fn piggy_insert( 38 | _ctx: &ReceiveContext, 39 | host: &Host, 40 | _amount: Amount, 41 | ) -> ReceiveResult<()> { 42 | // Ensure the piggy bank has not been smashed already. 43 | ensure!(*host.state() == PiggyBankState::Intact); 44 | // Just accept since the CCD balance is managed by the chain. 45 | Ok(()) 46 | } 47 | 48 | /// Smash a piggy bank retrieving the CCD, only allowed by the owner. 49 | #[receive(contract = "PiggyBank", name = "smash", mutable)] 50 | fn piggy_smash(ctx: &ReceiveContext, host: &mut Host) -> ReceiveResult<()> { 51 | // Get the contract owner, i.e. the account who initialized the contract. 52 | let owner = ctx.owner(); 53 | // Get the sender, who triggered this function, either a smart contract or 54 | // an account. 55 | let sender = ctx.sender(); 56 | 57 | // Ensure only the owner can smash the piggy bank. 58 | ensure!(sender.matches_account(&owner)); 59 | // Ensure the piggy bank has not been smashed already. 60 | ensure!(*host.state() == PiggyBankState::Intact); 61 | // Set the state to be smashed. 62 | *host.state_mut() = PiggyBankState::Smashed; 63 | 64 | // Get the current balance of the smart contract. 65 | let balance = host.self_balance(); 66 | // Result in a transfer of the whole balance to the contract owner. 67 | Ok(host.invoke_transfer(&owner, balance)?) 68 | } 69 | 70 | /// View the state and balance of the piggy bank. 71 | #[receive(contract = "PiggyBank", name = "view", return_value = "(PiggyBankState, Amount)")] 72 | fn piggy_view( 73 | _ctx: &ReceiveContext, 74 | host: &Host, 75 | ) -> ReceiveResult<(PiggyBankState, Amount)> { 76 | let current_state = *host.state(); 77 | let current_balance = host.self_balance(); 78 | Ok((current_state, current_balance)) 79 | } 80 | -------------------------------------------------------------------------------- /examples/piggy-bank/part2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "piggy-bank-part2" 3 | version = "0.1.1" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | description = "Piggy bank smart contract part 2." 8 | homepage = "https://github.com/concordium/concordium-rust-smart-contracts" 9 | repository = "https://github.com/concordium/concordium-rust-smart-contracts" 10 | readme = "../README.md" 11 | 12 | [lib] 13 | crate-type = ["cdylib", "rlib"] 14 | 15 | [features] 16 | default = ["std", "bump_alloc"] 17 | std = ["concordium-std/std"] 18 | bump_alloc = ["concordium-std/bump_alloc"] 19 | 20 | [dependencies.concordium-std] 21 | version = "10" 22 | path = "../../../concordium-std" 23 | default-features = false 24 | 25 | [dev-dependencies] 26 | concordium-smart-contract-testing = { path = "../../../contract-testing" } 27 | concordium-std-derive = { path = "../../../concordium-std-derive" } 28 | 29 | [profile.release] 30 | opt-level = 3 31 | -------------------------------------------------------------------------------- /examples/piggy-bank/part2/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Piggy bank smart contract. 2 | //! 3 | //! Allows anyone to insert CCD, but only the owner can "smash" it and 4 | //! retrieve the CCD. Prevents more CCD to be inserted after being smashed. 5 | //! 6 | //! This smart contract module is developed as part of the 7 | //! [Piggy Bank Tutorial](https://developer.concordium.software/en/mainnet/smart-contracts/tutorials/piggy-bank). 8 | //! 9 | //! Covers: 10 | //! - Reading owner, sender and self_balance from the context and host. 11 | //! - The `ensure` macro. 12 | //! - The `payable` attribute. 13 | //! - The `mutable` attribute. 14 | //! - Invoking a transfer with the host. 15 | //! - Integration testing (in the `/tests/tests.rs file`) 16 | //! - Custom errors. 17 | 18 | // Pulling in everything from the smart contract standard library. 19 | use concordium_std::*; 20 | 21 | /// The state of the piggy bank 22 | #[derive(Debug, SchemaType, Serialize, PartialEq, Eq, Clone, Copy)] 23 | pub enum PiggyBankState { 24 | /// Alive and well, allows for CCD to be inserted. 25 | Intact, 26 | /// The piggy bank has been emptied, preventing further CCD to be inserted. 27 | Smashed, 28 | } 29 | 30 | /// Setup a new Intact piggy bank. 31 | #[init(contract = "PiggyBank")] 32 | fn piggy_init(_ctx: &InitContext, _state_builder: &mut StateBuilder) -> InitResult { 33 | // Always succeeds 34 | Ok(PiggyBankState::Intact) 35 | } 36 | 37 | /// Insert some CCD into a piggy bank, allowed by anyone. 38 | #[receive(contract = "PiggyBank", name = "insert", payable)] 39 | fn piggy_insert( 40 | _ctx: &ReceiveContext, 41 | host: &Host, 42 | _amount: Amount, 43 | ) -> ReceiveResult<()> { 44 | // Ensure the piggy bank has not been smashed already. 45 | ensure!(*host.state() == PiggyBankState::Intact); 46 | // Just accept since the CCD balance is managed by the chain. 47 | Ok(()) 48 | } 49 | 50 | #[derive(Debug, PartialEq, Eq, Reject, Serialize)] 51 | pub enum SmashError { 52 | NotOwner, 53 | AlreadySmashed, 54 | TransferError, // If this occurs, there is a bug in the contract. 55 | } 56 | 57 | /// Smash a piggy bank retrieving the CCD, only allowed by the owner. 58 | #[receive(contract = "PiggyBank", name = "smash", mutable)] 59 | fn piggy_smash(ctx: &ReceiveContext, host: &mut Host) -> Result<(), SmashError> { 60 | // Get the contract owner, i.e. the account who initialized the contract. 61 | let owner = ctx.owner(); 62 | // Get the sender, who triggered this function, either a smart contract or 63 | // an account. 64 | let sender = ctx.sender(); 65 | 66 | // Ensure only the owner can smash the piggy bank. 67 | ensure!(sender.matches_account(&owner), SmashError::NotOwner); 68 | // Ensure the piggy bank has not been smashed already. 69 | ensure!(*host.state() == PiggyBankState::Intact, SmashError::AlreadySmashed); 70 | // Set the state to be smashed. 71 | *host.state_mut() = PiggyBankState::Smashed; 72 | 73 | // Get the current balance of the smart contract. 74 | let balance = host.self_balance(); 75 | 76 | // Transfer the whole balance to the contract owner. 77 | let transfer_result = host.invoke_transfer(&owner, balance); 78 | // The transfer can never fail, since the owner is known to exist, and the 79 | // contract has sufficient balance. 80 | ensure!(transfer_result.is_ok(), SmashError::TransferError); 81 | 82 | Ok(()) 83 | } 84 | 85 | /// View the state and balance of the piggy bank. 86 | #[receive(contract = "PiggyBank", name = "view", return_value = "(PiggyBankState, Amount)")] 87 | fn piggy_view( 88 | _ctx: &ReceiveContext, 89 | host: &Host, 90 | ) -> ReceiveResult<(PiggyBankState, Amount)> { 91 | let current_state = *host.state(); 92 | let current_balance = host.self_balance(); 93 | Ok((current_state, current_balance)) 94 | } 95 | -------------------------------------------------------------------------------- /examples/proxy/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "proxy" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [features] 11 | default = ["std", "bump_alloc"] 12 | 13 | std = ["concordium-std/std"] 14 | bump_alloc = ["concordium-std/bump_alloc"] 15 | 16 | [dependencies] 17 | concordium-std = {path = "../../concordium-std"} 18 | concordium-std-derive = { path = "../../concordium-std-derive" } 19 | 20 | [dev-dependencies] 21 | concordium-smart-contract-testing = { path = "../../contract-testing" } 22 | 23 | [lib] 24 | crate-type = ["cdylib", "rlib"] 25 | 26 | [profile.release] 27 | # Tell `rustc` to optimize for small code size. 28 | opt-level = 3 29 | # Don't unwind on panics, just trap. 30 | # panic = "abort" 31 | -------------------------------------------------------------------------------- /examples/proxy/tests/tests.rs: -------------------------------------------------------------------------------- 1 | //! Tests for the proxy example. 2 | use concordium_smart_contract_testing::*; 3 | use concordium_std_derive::*; 4 | 5 | const ALICE: AccountAddress = 6 | account_address!("2xBpaHottqhwFZURMZW4uZduQvpxNDSy46iXMYs9kceNGaPpZX"); 7 | const ALICE_ADDR: Address = Address::Account(ALICE); 8 | const SIGNER: Signer = Signer::with_one_key(); 9 | 10 | /// Tests that the proxy forwards the invocation to the proxied contract and 11 | /// that it returns the return value with any additional bytes prepended (see 12 | /// `RawReturnValue`s `Serial` implemenetation for details). 13 | #[test] 14 | fn test_forwards_and_returns_data_unaltered() { 15 | let mut chain = Chain::new(); 16 | 17 | // Create an account. 18 | chain.create_account(Account::new(ALICE, Amount::from_ccd(1000))); 19 | 20 | // Load and deploy the module. 21 | let module = module_load_v1("concordium-out/module.wasm.v1").expect("Module exists."); 22 | let deployment = chain.module_deploy_v1(SIGNER, ALICE, module).expect("Module deploys."); 23 | 24 | // Initialize the world_appender contract. 25 | let init_world_appender = chain 26 | .contract_init(SIGNER, ALICE, Energy::from(10_000), InitContractPayload { 27 | amount: Amount::zero(), 28 | mod_ref: deployment.module_reference, 29 | init_name: OwnedContractName::new_unchecked("init_world_appender".to_string()), 30 | param: OwnedParameter::empty(), 31 | }) 32 | .expect("Initialize world_appender contract"); 33 | 34 | // Create the proxy contract. 35 | let init_proxy = chain 36 | .contract_init(SIGNER, ALICE, Energy::from(10_000), InitContractPayload { 37 | amount: Amount::zero(), 38 | mod_ref: deployment.module_reference, 39 | init_name: OwnedContractName::new_unchecked("init_proxy".to_string()), 40 | param: OwnedParameter::from_serial(&init_world_appender.contract_address) 41 | .expect("Serialize appender contract address parameter"), 42 | }) 43 | .expect("Initialize proxy contract"); 44 | 45 | // Construct the parameter. 46 | let parameter = "hello"; 47 | 48 | // Call the `append` entrypoint via the proxy contract. Send `"hello"` as the 49 | // input parameter. 50 | let update = chain 51 | .contract_update(SIGNER, ALICE, ALICE_ADDR, Energy::from(10_000), UpdateContractPayload { 52 | amount: Amount::zero(), 53 | address: init_proxy.contract_address, // Note that this is the proxy address. 54 | receive_name: OwnedReceiveName::new_unchecked("proxy.append".to_string()), 55 | message: OwnedParameter::from_serial(¶meter).expect("Serialize parameter"), 56 | }) 57 | .expect("Invoke proxy contract"); 58 | 59 | // Check that the return value can be deserialized and is correct. 60 | // This ensures that the `RawReturnValue`s serial implementation is correct, 61 | // in that it *doesn't* include the option tag and length values in the return 62 | // value. If they were included, the string would have some extra bytes at 63 | // the beginning. 64 | let return_value: String = update.parse_return_value().expect("Deserialize return value"); 65 | assert_eq!(return_value, "hello, world"); 66 | } 67 | -------------------------------------------------------------------------------- /examples/recorder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "recorder" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [features] 11 | default = ["std", "bump_alloc"] 12 | std = ["concordium-std/std"] 13 | bump_alloc = ["concordium-std/bump_alloc"] 14 | 15 | [dependencies] 16 | concordium-std = {path = "../../concordium-std", default-features = false} 17 | concordium-std-derive = { path = "../../concordium-std-derive" } 18 | 19 | [dev-dependencies] 20 | concordium-smart-contract-testing = { path = "../../contract-testing" } 21 | 22 | [lib] 23 | crate-type=["cdylib", "rlib"] 24 | -------------------------------------------------------------------------------- /examples/recorder/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | 3 | //! A simple contract that records account addresses, and has 4 | //! an entrypoint to invoke transfers to all those addresses. 5 | //! The contract maintains a list of addresses. Addresses may be added with the 6 | //! "record" entrypoint, and removed with "delete" entrypoint. 7 | //! 8 | //! There is a "transfer" entrypoint that will trigger a transfer to all the 9 | //! current addresses, of 0CCD. After all the transfers the addresses are 10 | //! deleted from the state. 11 | //! 12 | //! This contract tests a reasonably small example of state interactions. 13 | //! 14 | //! Tests are located in the `./tests` folder. 15 | use concordium_std::*; 16 | 17 | #[derive(Serial, DeserialWithState)] 18 | #[concordium(state_parameter = "S")] 19 | struct State { 20 | addresses: StateSet, 21 | } 22 | 23 | #[init(contract = "recorder")] 24 | fn init(_ctx: &InitContext, state_builder: &mut StateBuilder) -> InitResult { 25 | Ok(State { 26 | addresses: state_builder.new_set(), 27 | }) 28 | } 29 | 30 | #[receive(contract = "recorder", name = "record", parameter = "AccountAddress", mutable)] 31 | fn receive_record(ctx: &ReceiveContext, host: &mut Host) -> ReceiveResult<()> { 32 | let address: AccountAddress = ctx.parameter_cursor().get()?; 33 | 34 | host.state_mut().addresses.insert(address); 35 | Ok(()) 36 | } 37 | 38 | #[receive( 39 | contract = "recorder", 40 | name = "delete", 41 | parameter = "AccountAddress", 42 | return_value = "bool", 43 | mutable 44 | )] 45 | fn receive_delete(ctx: &ReceiveContext, host: &mut Host) -> ReceiveResult { 46 | let addr_to_remove = ctx.parameter_cursor().get()?; 47 | let res = host.state_mut().addresses.remove(&addr_to_remove); 48 | Ok(res) 49 | } 50 | 51 | #[receive(contract = "recorder", name = "transfer", return_value = "u64", mutable)] 52 | fn receive_transfer(_ctx: &ReceiveContext, host: &mut Host) -> ReceiveResult { 53 | let addresses = &host.state().addresses; 54 | let mut count = 0; 55 | for addr in addresses.iter() { 56 | if host.invoke_transfer(&addr, Amount::from_micro_ccd(0)).is_ok() { 57 | count += 1; 58 | } 59 | } 60 | host.state_mut().addresses.clear(); 61 | Ok(count) 62 | } 63 | 64 | #[receive(contract = "recorder", name = "list", return_value = "Vec")] 65 | fn receive_list(_ctx: &ReceiveContext, host: &Host) -> ReceiveResult> { 66 | let mut ret: Vec = Vec::new(); 67 | for addr in host.state().addresses.iter() { 68 | ret.push(*addr); 69 | } 70 | Ok(ret) 71 | } 72 | -------------------------------------------------------------------------------- /examples/signature-verifier/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "signature-verifier" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | concordium-std = {path = "../../concordium-std"} 12 | 13 | [dev-dependencies] 14 | concordium-smart-contract-testing = { path = "../../contract-testing" } 15 | concordium-std-derive = { path = "../../concordium-std-derive" } 16 | ed25519-dalek = { version = "2.0", features = ["rand_core"] } 17 | rand = "0.8.5" 18 | 19 | [features] 20 | default = ["std", "bump_alloc"] 21 | std = ["concordium-std/std"] 22 | bump_alloc = ["concordium-std/bump_alloc"] 23 | 24 | [lib] 25 | crate-type=["cdylib", "rlib"] 26 | -------------------------------------------------------------------------------- /examples/signature-verifier/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # Signature Verifier contract for Ed25519 2 | //! 3 | //! This contract has a single receive function, which verifies a Ed25519 4 | //! signature. It shows off how to use the `crypto_primitives` attribute, which 5 | //! gives the function access to the cryptographic primitives from the 6 | //! [`HasCryptoPrimitives`] trait. 7 | use concordium_std::*; 8 | 9 | type State = (); 10 | 11 | #[derive(SchemaType, Serialize)] 12 | pub struct VerificationParameter { 13 | pub public_key: PublicKeyEd25519, 14 | pub signature: SignatureEd25519, 15 | pub message: Vec, 16 | } 17 | 18 | #[init(contract = "signature-verifier")] 19 | fn contract_init(_ctx: &InitContext, _state_builder: &mut StateBuilder) -> InitResult { 20 | Ok(()) 21 | } 22 | 23 | /// Verify a ed25519 signature and return the result as a bool. Expects a 24 | /// [`VerificationParameter`] as the parameter. 25 | #[receive( 26 | contract = "signature-verifier", 27 | name = "verify", 28 | crypto_primitives, 29 | parameter = "VerificationParameter", 30 | return_value = "bool" 31 | )] 32 | fn contract_receive( 33 | ctx: &ReceiveContext, 34 | _host: &Host, 35 | crypto_primitives: &impl HasCryptoPrimitives, 36 | ) -> ReceiveResult { 37 | let param: VerificationParameter = ctx.parameter_cursor().get()?; 38 | let is_valid = crypto_primitives.verify_ed25519_signature( 39 | param.public_key, 40 | param.signature, 41 | ¶m.message, 42 | ); 43 | Ok(is_valid) 44 | } 45 | -------------------------------------------------------------------------------- /examples/smart-contract-upgrade/contract-version1/Cargo.toml: -------------------------------------------------------------------------------- 1 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 2 | 3 | [package] 4 | name = "smart_contract_upgrade" 5 | version = "0.1.0" 6 | edition = "2021" 7 | license = "MPL-2.0" 8 | authors = ["Concordium "] 9 | description = "An example of how to upgrade a smart contract. The state is migrated during the upgrade." 10 | 11 | [features] 12 | default = ["std", "bump_alloc"] 13 | std = ["concordium-std/std"] 14 | bump_alloc = ["concordium-std/bump_alloc"] 15 | 16 | [dependencies] 17 | concordium-std = {path = "../../../concordium-std", default-features = false} 18 | 19 | [dev-dependencies] 20 | concordium-smart-contract-testing = { path = "../../../contract-testing" } 21 | concordium-std-derive = { path = "../../../concordium-std-derive" } 22 | 23 | [lib] 24 | crate-type=["cdylib", "rlib"] 25 | 26 | [profile.release] 27 | opt-level = "s" 28 | codegen-units = 1 29 | -------------------------------------------------------------------------------- /examples/smart-contract-upgrade/contract-version2/Cargo.toml: -------------------------------------------------------------------------------- 1 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 2 | 3 | [package] 4 | name = "smart_contract_upgrade" 5 | version = "0.2.0" 6 | edition = "2021" 7 | license = "MPL-2.0" 8 | authors = ["Concordium "] 9 | description = "An example of how to upgrade a smart contract. The state is migrated during the upgrade." 10 | 11 | [features] 12 | default = ["std", "bump_alloc"] 13 | std = ["concordium-std/std"] 14 | bump_alloc = ["concordium-std/bump_alloc"] 15 | 16 | [dependencies] 17 | concordium-std = {path = "../../../concordium-std", default-features = false} 18 | 19 | [lib] 20 | crate-type=["cdylib", "rlib"] 21 | 22 | [profile.release] 23 | opt-level = "s" 24 | codegen-units = 1 25 | -------------------------------------------------------------------------------- /examples/sponsored-tx-enabled-auction/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sponsored-tx-enabled-auction" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | [features] 9 | default = ["std", "bump_alloc"] 10 | std = ["concordium-std/std", "concordium-cis2/std"] 11 | bump_alloc = ["concordium-std/bump_alloc"] 12 | 13 | [dependencies] 14 | concordium-std = {path = "../../concordium-std", default-features = false} 15 | concordium-cis2 = {path = "../../concordium-cis2", default-features = false} 16 | 17 | [dev-dependencies] 18 | concordium-smart-contract-testing = { path = "../../contract-testing" } 19 | concordium-std-derive = { path = "../../concordium-std-derive" } 20 | cis2-multi = { path = "../cis2-multi/" } 21 | rand = "0.8" 22 | 23 | [lib] 24 | crate-type=["cdylib", "rlib"] 25 | -------------------------------------------------------------------------------- /examples/transfer-policy-check/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "transfer-policy-check" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | concordium-std = {path = "../../concordium-std", default-features = false} 12 | 13 | [dev-dependencies] 14 | concordium-smart-contract-testing = { path = "../../contract-testing" } 15 | concordium-std-derive = { path = "../../concordium-std-derive" } 16 | 17 | [features] 18 | default = ["std", "bump_alloc"] 19 | std = ["concordium-std/std"] 20 | bump_alloc = ["concordium-std/bump_alloc"] 21 | 22 | [lib] 23 | crate-type=["cdylib", "rlib"] 24 | 25 | [profile.release] 26 | opt-level = 3 27 | panic = "abort" 28 | -------------------------------------------------------------------------------- /examples/transfer-policy-check/src/lib.rs: -------------------------------------------------------------------------------- 1 | /*! A contract that showcases how to use policies. 2 | * 3 | * In particular, it can act as a filter for transfers to an account, 4 | * where the filter requires the sender to be from a specific country. 5 | * 6 | * The contract is initialised with `init`, in which an account address is 7 | * provided, which will be set as the state. 8 | * 9 | * The contract has a single receive entrypoint, `receive`, 10 | * which checks whether all sender policies have their country of residence 11 | * attribute set to `LOCAL_COUNTRY`. If that is the case, then the `amount` 12 | * will be forwarded to the account address held in the state. Otherwise, 13 | * the receive function will reject with `ContractError::NotLocalSender`. 14 | */ 15 | #![cfg_attr(not(feature = "std"), no_std)] 16 | use concordium_std::*; 17 | 18 | type State = AccountAddress; 19 | pub const LOCAL_COUNTRY: [u8; 2] = *b"DK"; 20 | 21 | #[derive(Serialize, Reject, PartialEq, Eq, Debug, SchemaType)] 22 | pub enum ContractError { 23 | NotLocalSender, 24 | TransferErrorAmountTooLarge, 25 | TransferErrorAccountMissing, 26 | } 27 | 28 | impl From for ContractError { 29 | fn from(e: TransferError) -> Self { 30 | match e { 31 | TransferError::AmountTooLarge => Self::TransferErrorAmountTooLarge, 32 | TransferError::MissingAccount => Self::TransferErrorAccountMissing, 33 | } 34 | } 35 | } 36 | 37 | /// Set the account address that `receive` will forward CCD to. 38 | #[init(contract = "transfer-policy-check", parameter = "AccountAddress")] 39 | fn init(ctx: &InitContext, _state_builder: &mut StateBuilder) -> InitResult { 40 | let parameter: AccountAddress = ctx.parameter_cursor().get()?; 41 | Ok(parameter) 42 | } 43 | 44 | /// Forward the `amount` to the account defined in the state iff all sender 45 | /// policies have the country of residence in `LOCAL_COUNTRY`. 46 | #[receive(contract = "transfer-policy-check", name = "receive", payable, error = "ContractError")] 47 | fn receive(ctx: &ReceiveContext, host: &Host, amount: Amount) -> Result<(), ContractError> { 48 | for policy in ctx.policies() { 49 | for (tag, value) in policy.attributes() { 50 | if tag == attributes::COUNTRY_OF_RESIDENCE && value.as_ref() != &LOCAL_COUNTRY[..] { 51 | return Err(ContractError::NotLocalSender); 52 | } 53 | } 54 | } 55 | Ok(host.invoke_transfer(host.state(), amount)?) 56 | } 57 | -------------------------------------------------------------------------------- /examples/transfer-policy-check/tests/tests.rs: -------------------------------------------------------------------------------- 1 | //! Tests for the transfer-policy-check contract. 2 | use concordium_smart_contract_testing::*; 3 | use concordium_std::{attributes, OwnedPolicy}; 4 | use concordium_std_derive::*; 5 | use transfer_policy_check::*; 6 | 7 | /// Constants. 8 | const ALICE: AccountAddress = 9 | account_address!("2xBpaHottqhwFZURMZW4uZduQvpxNDSy46iXMYs9kceNGaPpZX"); 10 | const BOB: AccountAddress = account_address!("2xdTv8awN1BjgYEw8W1BVXVtiEwG2b29U8KoZQqJrDuEqddseE"); 11 | const BOB_ADDR: Address = Address::Account(BOB); 12 | 13 | const SIGNER: Signer = Signer::with_one_key(); 14 | 15 | // Tests: 16 | 17 | /// Test that sending money via the contract works when the sender has the 18 | /// correct policy. Meaning that the sender has the country of residence in 19 | /// Denmark (`DK`). 20 | #[test] 21 | fn test_amount_forward_on_correct_policy() { 22 | let (mut chain, contract_address) = init(); 23 | 24 | // Construct a policy with the correct country code. 25 | let policy = policy_with_country(LOCAL_COUNTRY); 26 | // Create the account BOB, who is from Denmark. 27 | chain.create_account(Account::new_with_policy( 28 | BOB, 29 | AccountBalance::new(Amount::from_ccd(1000), Amount::zero(), Amount::zero()) 30 | .expect("Staked + locked < total."), 31 | policy, 32 | )); 33 | 34 | let amount_to_send = Amount::from_ccd(10); 35 | 36 | // Send money from Bob to Alice. 37 | let update = chain 38 | .contract_update(SIGNER, BOB, BOB_ADDR, Energy::from(50_000), UpdateContractPayload { 39 | amount: amount_to_send, 40 | address: contract_address, 41 | receive_name: OwnedReceiveName::new_unchecked( 42 | "transfer-policy-check.receive".to_string(), 43 | ), 44 | message: OwnedParameter::empty(), 45 | }) 46 | .expect("Contract update succeeds."); 47 | 48 | // Check that the money was forwarded. 49 | assert_eq!(update.account_transfers().collect::>(), [( 50 | contract_address, 51 | amount_to_send, 52 | ALICE 53 | )]); 54 | } 55 | 56 | // Helpers: 57 | 58 | /// Construct a policy with the provided country code. 59 | fn policy_with_country(country_code: [u8; 2]) -> OwnedPolicy { 60 | let policies = OwnedPolicy { 61 | identity_provider: 0, 62 | created_at: Timestamp::from_timestamp_millis(0), 63 | valid_to: Timestamp::from_timestamp_millis(1000), 64 | items: vec![(attributes::COUNTRY_OF_RESIDENCE, country_code.into())], 65 | }; 66 | 67 | policies 68 | } 69 | 70 | /// Initialize the chain and contract. 71 | /// 72 | /// Creates one account (ALICE), deploys the module, and initializes the 73 | /// contract. 74 | fn init() -> (Chain, ContractAddress) { 75 | let mut chain = Chain::new(); 76 | 77 | // Create an account. 78 | chain.create_account(Account::new(ALICE, Amount::from_ccd(1000))); 79 | 80 | // Load and deploy the module. 81 | let module = module_load_v1("concordium-out/module.wasm.v1").expect("Module exists."); 82 | let deployment = chain.module_deploy_v1(SIGNER, ALICE, module).expect("Module deploys."); 83 | 84 | // Initialize the transfer policy check contract. 85 | let init = chain 86 | .contract_init(SIGNER, ALICE, Energy::from(10_000), InitContractPayload { 87 | amount: Amount::zero(), 88 | mod_ref: deployment.module_reference, 89 | init_name: OwnedContractName::new_unchecked("init_transfer-policy-check".to_string()), 90 | param: OwnedParameter::from_serial(&ALICE).expect("Parameter has valid size."), 91 | }) 92 | .expect("Initialize transfer policy check contract"); 93 | 94 | (chain, init.contract_address) 95 | } 96 | -------------------------------------------------------------------------------- /examples/two-step-transfer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "two-step-transfer" 3 | version = "0.1.1" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | description = "Two-step transfer smart contract." 8 | homepage = "https://github.com/concordium/concordium-rust-smart-contracts" 9 | repository = "https://github.com/concordium/concordium-rust-smart-contracts" 10 | readme = "../README.md" 11 | 12 | [features] 13 | default = ["std", "bump_alloc"] 14 | 15 | std = ["concordium-std/std"] 16 | bump_alloc = ["concordium-std/bump_alloc"] 17 | 18 | [dependencies.concordium-std] 19 | version = "*" 20 | path = "../../concordium-std" 21 | default-features = false 22 | features = ["concordium-quickcheck"] 23 | 24 | [dev-dependencies] 25 | concordium-std = { version = "*", path = "../../concordium-std" } 26 | concordium-std-derive = { path = "../../concordium-std-derive" } 27 | 28 | [lib] 29 | crate-type = ["cdylib", "rlib"] 30 | 31 | [profile.release] 32 | opt-level = 3 33 | -------------------------------------------------------------------------------- /examples/voting/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "voting-contract" 3 | version = "0.1.0" 4 | authors = ["Concordium "] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | concordium-std = {path = "../../concordium-std", default-features = false} 12 | 13 | [dev-dependencies] 14 | concordium-smart-contract-testing = { path = "../../contract-testing" } 15 | concordium-std-derive = { path = "../../concordium-std-derive" } 16 | 17 | [features] 18 | default = ["std", "bump_alloc"] 19 | std = ["concordium-std/std"] 20 | bump_alloc = ["concordium-std/bump_alloc"] 21 | 22 | [lib] 23 | crate-type=["cdylib", "rlib"] 24 | 25 | [profile.release] 26 | opt-level = 3 27 | panic = "abort" 28 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | edition = "2021" 2 | combine_control_expr = false 3 | wrap_comments = true 4 | brace_style = "PreferSameLine" 5 | enum_discrim_align_threshold = 20 6 | fn_single_line = true 7 | format_strings = true 8 | format_macro_matchers = true 9 | format_macro_bodies = true 10 | imports_granularity = "Crate" 11 | normalize_comments = false 12 | reorder_impl_items = true 13 | reorder_imports = true 14 | struct_field_align_threshold = 20 15 | trailing_semicolon = true 16 | type_punctuation_density = "Wide" 17 | use_field_init_shorthand = true 18 | use_try_shorthand = true 19 | format_code_in_doc_comments = true 20 | overflow_delimited_expr = true 21 | normalize_doc_attributes = true 22 | use_small_heuristics = "Off" 23 | -------------------------------------------------------------------------------- /templates/cis2-nft/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "{{crate_name}}" 3 | version = "0.1.0" 4 | authors = [ "{{authors}}" ] 5 | edition = "2021" 6 | license = "MPL-2.0" 7 | description = "{{description}}" 8 | 9 | [features] 10 | default = ["std"] 11 | std = ["concordium-std/std", "concordium-cis2/std"] 12 | bump_alloc = ["concordium-std/bump_alloc"] 13 | 14 | [dependencies] 15 | concordium-std = {version = "10.1", default-features = false} 16 | concordium-cis2 = {version = "6.2", default-features = false} 17 | 18 | [dev-dependencies] 19 | concordium-smart-contract-testing = "4.3" 20 | concordium-std-derive = "6.0" 21 | 22 | [lib] 23 | crate-type=["cdylib", "rlib"] 24 | 25 | [profile.release] 26 | codegen-units = 1 27 | opt-level = "s" 28 | -------------------------------------------------------------------------------- /templates/cis2-nft/cargo-generate.toml: -------------------------------------------------------------------------------- 1 | [template] 2 | cargo_generate_version = ">= 0.17.0, < 0.24.0" 3 | 4 | [placeholders] 5 | description = { type="string", prompt="Description for the project?" } 6 | tokenMetadataBaseURL= { type="string", prompt="Token metadata base URL of the token?", default='https://some.example/token/' } 7 | -------------------------------------------------------------------------------- /templates/credential-registry/Cargo.toml: -------------------------------------------------------------------------------- 1 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 2 | 3 | [package] 4 | name = "{{crate_name}}" 5 | version = "0.1.0" 6 | edition = "2021" 7 | license = "MPL-2.0" 8 | authors = [ "{{authors}}" ] 9 | description = "{{description}}" 10 | 11 | [features] 12 | default = ["std", "crypto-primitives", "bump_alloc"] 13 | std = ["concordium-std/std", "concordium-cis2/std"] 14 | bump_alloc = ["concordium-std/bump_alloc"] 15 | crypto-primitives = ["concordium-std/crypto-primitives"] 16 | 17 | [dependencies] 18 | concordium-std = {version = "10.1", default-features = false, features = ["concordium-quickcheck"]} 19 | concordium-cis2 = {version = "6.2", default-features = false} 20 | quickcheck = {version = "1"} 21 | 22 | [dev-dependencies] 23 | concordium-smart-contract-testing = "4.3" 24 | concordium-std-derive = "6.0" 25 | 26 | [lib] 27 | crate-type=["cdylib", "rlib"] 28 | 29 | [profile.release] 30 | opt-level = "s" 31 | codegen-units = 1 32 | -------------------------------------------------------------------------------- /templates/credential-registry/README.md: -------------------------------------------------------------------------------- 1 | # Credential registry contract 2 | 3 | This smart contract implements an example on-chain registry for the public 4 | part of verifiable credentials (VCs). The contract follows CIS-4: Credential 5 | Registry Standard. 6 | 7 | The contract keeps track of credentials' public data, allows managing the 8 | VC life cycle, and querying VCs data and status. The intended users are 9 | issuers of VCs, holders of VCs, revocation authorities, and verifiers. 10 | 11 | When initializing a contract, the issuer provides a type and a schema 12 | reference for the credentials in the registry. The schema reference points 13 | to a JSON document describing the structure of verifiable credentials in the 14 | registry (attributes and their types). If the issuer wants to issue 15 | verifiable credentials of several types, they can deploy several instances 16 | of this contract with different credential types. 17 | 18 | ## Issuer's functionality 19 | 20 | {% if revocable_by_others %}- register/remove revocation authority keys;{% else %}{% endif %} 21 | - register a new credential; 22 | - revoke a credential; 23 | - update the issuer's metadata; 24 | - update the credential metadata; 25 | - update credential schema reference; 26 | {% if restorable %}- upgrade the contract, set implementors; 27 | - restore (cancel revocation of) a revoked credential.{% else %}- upgrade the contract, set implementors.{% endif %} 28 | 29 | ## Holder's functionality 30 | 31 | - revoke a credential by signing a revocation message. 32 | {% if revocable_by_others %} 33 | ## Revocation authority's functionality 34 | 35 | Revocation authorities are some entities chosen by the issuer that have 36 | revocation capabilities. Their public keys are registered by the issuer and 37 | a revocation authority signs a revocation message with the corresponding 38 | private key. 39 | 40 | - revoke a credential by signing a revocation message.{%endif%} 41 | 42 | ## Verifier's functionality 43 | 44 | - view credential status to verify VC validity; 45 | - view credential data to verify proofs (verifiable presentations) requested 46 | from holders. 47 | -------------------------------------------------------------------------------- /templates/credential-registry/cargo-generate.toml: -------------------------------------------------------------------------------- 1 | [template] 2 | cargo_generate_version = ">= 0.17.0, < 0.24.0" 3 | 4 | [hooks] 5 | pre = ["pre-script.rhai"] # a script for setting default values for the variables when `template_type = default` 6 | 7 | [placeholders] 8 | description = { type = "string", prompt = "Description for the project?" } 9 | template_type = { type = "string", prompt = "Select template type ('full' includes all features and is recommended for first-time users; 'custom' allows configuring who can revoke credentials and whether they can be restored)", choices = ["full", "custom"], default = "full"} 10 | 11 | [values] 12 | revocable_by_others = true 13 | restorable = true 14 | 15 | [conditional.'template_type == "custom"'.placeholders] 16 | revocable_by_others = { type = "bool", prompt = "Can credentials be revoked by someone other than the issuer or the holder?", default = false } 17 | restorable = { type = "bool", prompt = "Can revocation be reverted?", default = false } 18 | -------------------------------------------------------------------------------- /templates/credential-registry/pre-script.rhai: -------------------------------------------------------------------------------- 1 | let template_type = variable::get("template_type"); 2 | if template_type == "full" { 3 | variable::set("revocable_by_others", true); 4 | variable::set("restorable", true); 5 | } 6 | -------------------------------------------------------------------------------- /templates/default/Cargo.toml: -------------------------------------------------------------------------------- 1 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 2 | 3 | [package] 4 | name = "{{ crate_name }}" 5 | version = "0.1.0" 6 | edition = "2021" 7 | license = "MPL-2.0" 8 | authors = ["{{ authors }}"] 9 | 10 | [features] 11 | default = ["std"] 12 | std = ["concordium-std/std"] 13 | bump_alloc = ["concordium-std/bump_alloc"] 14 | 15 | [dependencies] 16 | concordium-std = { version = "10.1", default-features = false } 17 | 18 | [dev-dependencies] 19 | concordium-smart-contract-testing = "4.3" 20 | 21 | [lib] 22 | crate-type = ["cdylib", "rlib"] 23 | 24 | [profile.release] 25 | opt-level = "s" 26 | codegen-units = 1 27 | -------------------------------------------------------------------------------- /templates/default/cargo-generate.toml: -------------------------------------------------------------------------------- 1 | [template] 2 | cargo_generate_version = ">= 0.17.0, < 0.24.0" 3 | -------------------------------------------------------------------------------- /templates/default/deploy-scripts/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2021" 3 | name = "deploy_scripts" 4 | version = "1.0.0" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | anyhow = "1.0" 10 | chrono = "0.4.26" 11 | clap = { version = "4", features = ["derive", "env"]} 12 | concordium-rust-sdk="4.2" 13 | tokio = {version = "1.18", features = ["rt", "macros", "rt-multi-thread"] } 14 | tonic = {version = "0.10", features = ["tls", "tls-roots"]} # Use system trust roots. 15 | {{ crate_name }} = { path = "../" } 16 | -------------------------------------------------------------------------------- /templates/default/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! # Concordium V1 Smart Contract Template 2 | 3 | #![cfg_attr(not(feature = "std"), no_std)] 4 | 5 | use concordium_std::*; 6 | use core::fmt::Debug; 7 | 8 | /// The state of the smart contract. 9 | #[derive(Serialize, SchemaType)] 10 | pub struct State { 11 | // Add fields to this type to hold state in the smart contract. 12 | // This field is just an example. 13 | custom_state_field: i8, 14 | } 15 | 16 | /// Errors that may be emitted by this smart contract. 17 | #[derive(Debug, PartialEq, Eq, Reject, Serialize, SchemaType)] 18 | pub enum Error { 19 | /// Failed parsing the input parameter. 20 | #[from(ParseError)] 21 | ParseParams, 22 | /// Add variants to this enum to be able to return custom errors from the smart contract. 23 | CustomError, 24 | } 25 | 26 | /// Any type implementing Serialize and SchemaType can be 27 | /// used as an input parameter to a smart contract function. 28 | #[derive(Serialize, SchemaType)] 29 | pub struct CustomInputParameter { 30 | /// Just an example, you could have any fields here. 31 | pub num: i8, 32 | } 33 | 34 | /// Creates a new instance of the smart contract. 35 | #[init(contract = "{{ crate_name }}", parameter = "CustomInputParameter")] 36 | fn init(ctx: &InitContext, _state_builder: &mut StateBuilder) -> InitResult { 37 | let param: CustomInputParameter = ctx.parameter_cursor().get()?; 38 | 39 | // Create the initial state of the smart contract here. 40 | // This state can then be used in the other functions. 41 | Ok(State { 42 | custom_state_field: param.num, 43 | }) 44 | } 45 | 46 | /// Receive function. The input parameter in this function is the boolean variable `return_error`. 47 | /// If `return_error == true`, the receive function will return a custom error. 48 | /// If `return_error == false`, the receive function executes successfully. 49 | #[receive( 50 | contract = "{{ crate_name }}", 51 | name = "receive", 52 | // You can use any other type than bool here, bool is used here only as an example. 53 | parameter = "bool", 54 | error = "Error", 55 | mutable 56 | )] 57 | fn receive(ctx: &ReceiveContext, _host: &mut Host) -> Result<(), Error> { 58 | // Parse input and apply any other logic relevant for this function of the smart contract. 59 | // You can mutate the smart contract state here via host.state_mut(), since the receive attribute has the mutable flag. 60 | // You can return any of your custom error variants from above. 61 | 62 | // Returns ParseError on failure. 63 | let return_error = ctx.parameter_cursor().get()?; 64 | if return_error { 65 | Err(Error::CustomError) 66 | } else { 67 | Ok(()) 68 | } 69 | } 70 | 71 | /// Returns the state of the smart contract. 72 | #[receive(contract = "{{ crate_name }}", name = "view", return_value = "State")] 73 | fn view<'a>(_ctx: &ReceiveContext, host: &'a Host) -> ReceiveResult<&'a State> { 74 | Ok(host.state()) 75 | } 76 | -------------------------------------------------------------------------------- /templates/default/tests/tests.rs: -------------------------------------------------------------------------------- 1 | use concordium_smart_contract_testing::*; 2 | use {{crate_name}}::*; 3 | 4 | /// A test account. 5 | const ALICE: AccountAddress = AccountAddress([0u8; 32]); 6 | const ALICE_ADDR: Address = Address::Account(ALICE); 7 | 8 | /// The initial balance of the ALICE test account. 9 | const ACC_INITIAL_BALANCE: Amount = Amount::from_ccd(10_000); 10 | 11 | /// A [`Signer`] with one set of keys, used for signing transactions. 12 | const SIGNER: Signer = Signer::with_one_key(); 13 | 14 | /// Test that invoking the `receive` endpoint with the `false` parameter 15 | /// succeeds in updating the contract. 16 | #[test] 17 | fn test_throw_no_error() { 18 | let (mut chain, init) = initialize(); 19 | 20 | // Update the contract via the `receive` entrypoint with the parameter `false`. 21 | chain 22 | .contract_update(SIGNER, ALICE, ALICE_ADDR, Energy::from(10_000), UpdateContractPayload { 23 | address: init.contract_address, 24 | amount: Amount::zero(), 25 | receive_name: OwnedReceiveName::new_unchecked("{{crate_name}}.receive".to_string()), 26 | message: OwnedParameter::from_serial(&false) 27 | .expect("Parameter within size bounds"), 28 | }) 29 | .expect("Update succeeds with `false` as input."); 30 | } 31 | 32 | /// Test that invoking the `receive` endpoint with the `true` parameter 33 | /// results in the `CustomError` being thrown. 34 | #[test] 35 | fn test_throw_error() { 36 | let (mut chain, init) = initialize(); 37 | 38 | // Update the contract via the `receive` entrypoint with the parameter `true`. 39 | let update = chain 40 | .contract_update(SIGNER, ALICE, ALICE_ADDR, Energy::from(10_000), UpdateContractPayload { 41 | address: init.contract_address, 42 | amount: Amount::zero(), 43 | receive_name: OwnedReceiveName::new_unchecked("{{crate_name}}.receive".to_string()), 44 | message: OwnedParameter::from_serial(&true).expect("Parameter within size bounds"), 45 | }) 46 | .expect_err("Update fails with `true` as input."); 47 | 48 | // Check that the contract returned `CustomError`. 49 | let error: Error = update.parse_return_value().expect("Deserialize `Error`"); 50 | assert_eq!(error, Error::CustomError); 51 | } 52 | 53 | /// Helper method for initializing the contract. 54 | /// 55 | /// Does the following: 56 | /// - Creates the [`Chain`] 57 | /// - Creates one account, `Alice` with `10_000` CCD as the initial balance. 58 | /// - Initializes the contract. 59 | /// - Returns the [`Chain`] and the [`ContractInitSuccess`] 60 | fn initialize() -> (Chain, ContractInitSuccess) { 61 | // Initialize the test chain. 62 | let mut chain = Chain::new(); 63 | 64 | // Create the test account. 65 | chain.create_account(Account::new(ALICE, ACC_INITIAL_BALANCE)); 66 | 67 | // Load the module. 68 | let module = module_load_v1("./concordium-out/module.wasm.v1").expect("Module exists at path"); 69 | // Deploy the module. 70 | let deployment = chain.module_deploy_v1(SIGNER, ALICE, module).expect("Deploy valid module"); 71 | 72 | let parameter = CustomInputParameter { num: 0 }; 73 | 74 | // Initialize the contract. 75 | let init = chain 76 | .contract_init( 77 | SIGNER, 78 | ALICE, 79 | Energy::from(10_000), 80 | InitContractPayload { 81 | amount: Amount::zero(), 82 | mod_ref: deployment.module_reference, 83 | init_name: OwnedContractName::new_unchecked("init_{{crate_name}}".to_string()), 84 | param: OwnedParameter::from_serial(¶meter).expect("Parameter is valid."), 85 | }, 86 | ) 87 | .expect("Initializing contract"); 88 | 89 | (chain, init) 90 | } 91 | -------------------------------------------------------------------------------- /templates/issue-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Templates do not build with the latest cargo-concordium {{ env.VERSION }} 3 | labels: '[Type] Bug' 4 | --- 5 | 6 | An attempt to build with the cargo generate {{ env.VERSION }} failed. 7 | -------------------------------------------------------------------------------- /templates/resources/compile.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Concordium/concordium-rust-smart-contracts/8fdd1b480f7e0c8e82b7b1537d2ecdff923ead8d/templates/resources/compile.gif -------------------------------------------------------------------------------- /templates/resources/init.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Concordium/concordium-rust-smart-contracts/8fdd1b480f7e0c8e82b7b1537d2ecdff923ead8d/templates/resources/init.gif -------------------------------------------------------------------------------- /templates/resources/simulation_init.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Concordium/concordium-rust-smart-contracts/8fdd1b480f7e0c8e82b7b1537d2ecdff923ead8d/templates/resources/simulation_init.gif -------------------------------------------------------------------------------- /templates/resources/simulation_receive_throw_error_false.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Concordium/concordium-rust-smart-contracts/8fdd1b480f7e0c8e82b7b1537d2ecdff923ead8d/templates/resources/simulation_receive_throw_error_false.gif -------------------------------------------------------------------------------- /templates/resources/simulation_receive_throw_error_true.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Concordium/concordium-rust-smart-contracts/8fdd1b480f7e0c8e82b7b1537d2ecdff923ead8d/templates/resources/simulation_receive_throw_error_true.gif -------------------------------------------------------------------------------- /templates/resources/simulation_view.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Concordium/concordium-rust-smart-contracts/8fdd1b480f7e0c8e82b7b1537d2ecdff923ead8d/templates/resources/simulation_view.gif -------------------------------------------------------------------------------- /templates/resources/test.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Concordium/concordium-rust-smart-contracts/8fdd1b480f7e0c8e82b7b1537d2ecdff923ead8d/templates/resources/test.gif --------------------------------------------------------------------------------