├── .actrc
├── .cargo
└── config.toml
├── .circleci
└── config.yml
├── .dockerignore
├── .github
├── ISSUE_TEMPLATE
│ ├── backlog_item.md
│ ├── bug_issue.md
│ ├── config.yml
│ └── general_issue.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ ├── check-licence.yml
│ └── docs.yml
├── .gitignore
├── .gitmodules
├── Cargo.lock
├── Cargo.toml
├── HEADER-LICENSE
├── LICENSE
├── README.md
├── config.json
├── docker
├── launch.Dockerfile
└── release.Dockerfile
├── docs
├── .gitignore
├── 404.html
├── assets
│ ├── css
│ │ └── style.scss
│ ├── favicon.ico
│ ├── img
│ │ ├── nav-formula.png
│ │ ├── pint.png
│ │ └── set-custom-types.png
│ └── pint2.svg
├── getting-started
│ ├── installation.md
│ ├── overview
│ │ └── architecture.md
│ └── resources
│ │ ├── developer-resources.md
│ │ └── general-resources.md
├── index.md
└── usage
│ ├── command-line.md
│ └── configuration.md
├── js
├── .prettierrc
├── e2e
│ ├── README.md
│ ├── index.ts
│ ├── package.json
│ ├── src
│ │ ├── config.ts
│ │ ├── extrinsic.ts
│ │ ├── index.ts
│ │ ├── launch.ts
│ │ ├── runner.ts
│ │ └── util.ts
│ ├── tsconfig.json
│ └── tslint.json
├── finalize
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
├── package.json
├── pint-types-bundle
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── chainlink.json
│ ├── index.ts
│ ├── package.json
│ └── tsconfig.json
├── scripts
│ └── update_pint_types.ts
└── yarn.lock
├── mkdocs.yml
├── node
├── Cargo.toml
├── build.rs
└── src
│ ├── chain_spec
│ ├── dev.rs
│ ├── mod.rs
│ ├── pint.rs
│ └── shot.rs
│ ├── cli.rs
│ ├── client.rs
│ ├── command.rs
│ ├── instant_finalize.rs
│ ├── lib.rs
│ ├── main.rs
│ └── service.rs
├── package-lock.json
├── pallets
├── asset-index
│ ├── Cargo.toml
│ ├── README.md
│ ├── rpc
│ │ ├── Cargo.toml
│ │ ├── runtime-api
│ │ │ ├── Cargo.toml
│ │ │ └── src
│ │ │ │ └── lib.rs
│ │ └── src
│ │ │ └── lib.rs
│ └── src
│ │ ├── benchmarking.rs
│ │ ├── lib.rs
│ │ ├── mock.rs
│ │ ├── tests.rs
│ │ ├── traits.rs
│ │ └── types.rs
├── committee
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── benchmarking.rs
│ │ ├── lib.rs
│ │ ├── mock.rs
│ │ ├── tests.rs
│ │ ├── traits.rs
│ │ ├── types.rs
│ │ └── utils.rs
├── local-treasury
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── benchmarking.rs
│ │ ├── lib.rs
│ │ ├── mock.rs
│ │ └── tests.rs
├── price-feed
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── benchmarking.rs
│ │ ├── lib.rs
│ │ ├── mock.rs
│ │ ├── tests.rs
│ │ ├── traits.rs
│ │ └── types.rs
├── remote-asset-manager
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── lib.rs
│ │ ├── traits.rs
│ │ └── types.rs
├── remote-treasury
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ └── lib.rs
└── saft-registry
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ ├── benchmarking.rs
│ ├── lib.rs
│ ├── mock.rs
│ ├── tests.rs
│ └── traits.rs
├── primitives
├── derive
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── lib.rs
│ │ └── xcm
│ │ ├── mod.rs
│ │ └── result.rs
├── primitives
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ │ ├── fee.rs
│ │ ├── lib.rs
│ │ ├── traits.rs
│ │ └── types.rs
└── xcm-calls
│ ├── Cargo.toml
│ ├── README.md
│ └── src
│ ├── assets.rs
│ ├── encode_with.rs
│ ├── lib.rs
│ ├── proxy.rs
│ ├── staking.rs
│ └── utility.rs
├── resources
├── README.md
├── pint-dev-with-chainlink-feed.json
├── pint-dev.json
└── types.json
├── rpc
├── Cargo.toml
└── src
│ └── lib.rs
├── runtime
├── common
│ ├── Cargo.toml
│ └── src
│ │ ├── constants.rs
│ │ ├── lib.rs
│ │ ├── payment.rs
│ │ ├── traits.rs
│ │ ├── types.rs
│ │ └── weights
│ │ ├── mod.rs
│ │ ├── pallet_asset_index.rs
│ │ ├── pallet_chainlink_feed.rs
│ │ ├── pallet_committee.rs
│ │ ├── pallet_local_treasury.rs
│ │ ├── pallet_price_feed.rs
│ │ ├── pallet_remote_asset_manager.rs
│ │ └── pallet_saft_registry.rs
├── dev
│ ├── Cargo.toml
│ ├── build.rs
│ └── src
│ │ └── lib.rs
├── integration-tests
│ ├── Cargo.toml
│ └── src
│ │ ├── ext.rs
│ │ ├── lib.rs
│ │ ├── prelude.rs
│ │ ├── statemint.rs
│ │ ├── tests.rs
│ │ └── util.rs
├── pint
│ ├── Cargo.toml
│ ├── build.rs
│ └── src
│ │ └── lib.rs
└── shot
│ ├── Cargo.toml
│ ├── build.rs
│ └── src
│ └── lib.rs
├── rustfmt.toml
├── scripts
├── header.txt
└── init.sh
├── templates
├── pallet-weight-template.hbs
└── runtime-weight-template.hbs
└── test-utils
└── xcm-test-support
└── Cargo.toml
/.actrc:
--------------------------------------------------------------------------------
1 | # When using act to run github actions locally it must use a full image to be able to compile correctly
2 | -P ubuntu-20.04=nektos/act-environments-ubuntu:20.04
3 |
--------------------------------------------------------------------------------
/.cargo/config.toml:
--------------------------------------------------------------------------------
1 | [net]
2 | git-fetch-with-cli = true
3 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | # Generated by Cargo
2 | # will have compiled files and executables
3 | **/target/
4 | # These are backup files generated by rustfmt
5 | **/*.rs.bk
6 |
7 | # node deps for e2e
8 | node_modules
9 |
10 | # The directory caches for osx
11 | .DS_Store
12 |
13 | # typescript language server logs and logs
14 | *.log
15 |
16 | # rococo specs
17 | rococo*
18 |
19 | # The cache for docker container dependency
20 | .cargo
21 |
22 | # The cache for chain data in container
23 | .local
24 |
25 | # Binaries for launching PINT with polkadot
26 | bin
27 |
28 | # Libraries of js output
29 | js/**/*/lib
30 |
31 | # Unknown
32 | local-test
33 |
34 | # docker
35 | docker
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/backlog_item.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Backlog Item
3 | about: Issue that has enough reasoning, research and information to be implemented
4 | title: ''
5 | labels: 'needs triage'
6 | assignees: ''
7 |
8 | ---
9 |
10 |
11 |
12 | ## Implementation details
13 |
14 |
15 | ## Testing details
16 |
17 |
18 | ## Acceptance Criteria
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_issue.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: 'bug'
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## Describe the bug
11 |
12 |
13 | -
14 |
15 |
16 | ## Expected Behavior
17 |
18 |
25 |
26 | -
27 |
28 |
29 | ## Current Behavior
30 |
31 |
39 |
40 | -
41 |
42 |
43 | ## Possible Solution
44 |
45 |
53 |
54 | -
55 |
56 |
57 | ## To Reproduce
58 | Steps to reproduce the behavior:
59 |
60 | 1.
61 | 2.
62 | 3.
63 |
64 |
65 | ## Log output
66 |
67 |
68 | Log Output
69 |
70 | ```Paste log output here
71 | paste log output...
72 | ```
73 |
74 |
75 |
76 | ## Specification
77 |
78 |
91 |
92 | - rustc version:
93 | - pint version:
94 | - commit tag:
95 | - commit hash:
96 | - operating system:
97 | - additional links:
98 |
99 |
100 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 |
2 | blank_issues_enabled: true
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/general_issue.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: General issue
3 | about: General purpose issue template
4 | title: ''
5 | labels: 'needs triage'
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## Issue summary
11 |
12 | -
13 |
14 |
15 | ## Other information and links
16 |
17 | -
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Changes
2 |
3 |
9 |
10 | -
11 | -
12 | -
13 |
14 | ## Tests
15 |
16 |
21 |
22 | ```
23 |
24 | ```
25 |
26 | ## Issues
27 |
28 |
34 |
35 | -
--------------------------------------------------------------------------------
/.github/workflows/check-licence.yml:
--------------------------------------------------------------------------------
1 | name: Check Licence
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - main
7 | push:
8 | branches:
9 | - main
10 |
11 | jobs:
12 | check-licence:
13 | runs-on: ubuntu-18.04
14 |
15 | steps:
16 | - uses: actions/checkout@v2
17 | - name: Set up Golang
18 | uses: actions/setup-go@v2
19 | with:
20 | go-version: '^1.16'
21 | - name: Install addlicense
22 | run: |
23 | export PATH=${PATH}:`go env GOPATH`/bin
24 | go get -v -u github.com/google/addlicense
25 | - name: Check license
26 | run: |
27 | export PATH=${PATH}:`go env GOPATH`/bin
28 | addlicense -check -c "ChainSafe Systems" -f ./scripts/header.txt -y 2021 $(find $PWD -type f -name '*.rs')
29 |
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: Publish docs via GitHub Pages
2 | on:
3 | push:
4 | branches:
5 | - main
6 |
7 | jobs:
8 | build:
9 | name: Deploy docs
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Checkout main
13 | uses: actions/checkout@v2
14 |
15 | - uses: actions-rs/toolchain@v1
16 | with:
17 | toolchain: nightly
18 | target: wasm32-unknown-unknown
19 |
20 | - run: |
21 | cargo doc --all-features
22 | mv target/doc docs/api
23 |
24 | - name: Deploy docs
25 | uses: mhausenblas/mkdocs-deploy-gh-pages@master
26 | env:
27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28 | CONFIG_FILE: ./mkdocs.yml
29 | EXTRA_PACKAGES: build-base
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Generated by Cargo
2 | # will have compiled files and executables
3 | **/target/
4 | # These are backup files generated by rustfmt
5 | **/*.rs.bk
6 |
7 | # node deps for e2e
8 | node_modules
9 |
10 | # The directory caches for osx
11 | .DS_Store
12 |
13 | # typescript language server logs and logs
14 | *.log
15 |
16 | # rococo specs
17 | rococo*
18 |
19 | # The cache for docker container dependency
20 | .cargo
21 |
22 | # The cache for chain data in container
23 | .local
24 |
25 | # Binaries for launching PINT with polkadot
26 | bin
27 |
28 | # Libraries of js output
29 | js/**/*/lib
30 |
31 | # Unknown
32 | local-test
33 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "js/polkadot-launch"]
2 | path = js/polkadot-launch
3 | url = https://github.com/ChainSafe/polkadot-launch.git
4 |
--------------------------------------------------------------------------------
/HEADER-LICENSE:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Polkadot Index Network Token (PINT :beer:)
2 |
3 | [](http://www.gnu.org/licenses/lgpl-3.0)
4 | [](https://chainsafe.github.io/PINT/api/pint_runtime_dev/)
5 |
6 | A Polkadot ecosystem index for investors. A self sustaining auction treasury for parachains.
7 |
8 | Organized by the Stateless Money validator, governed by a community that includes Polychain Capital, Hypersphere
9 | Ventures, HashKey Capital, Acala, and built by ChainSafe as a StakerDAO product.
10 |
11 | For more information on the project please visit [Polkadot Index Network Token](https://docs.polkadotindex.com/)
12 | documentation.
13 |
14 | ❗**Current development should be considered a work in progress.**
15 |
16 | ## Upstream
17 |
18 | This project is a fork of the
19 | [Substrate Developer Hub Node Template](https://github.com/substrate-developer-hub/substrate-node-template).
20 |
21 | ## Build & Run
22 |
23 | Follow these steps to prepare a local Substrate development environment :hammer_and_wrench:
24 |
25 | ### Setup
26 |
27 | This project currently builds against Rust nightly-2021-08-01. Assuming you have rustup already insatlled set up your
28 | local environment:
29 |
30 | ```shell
31 | rustup install nightly-2021-08-01
32 | rustup target add wasm32-unknown-unknown --toolchain nightly-2021-08-01
33 | rustup override set nightly-2021-08-01
34 | ```
35 |
36 | ### Build
37 |
38 | Once the development environment is set up, build the node template. This command will build the
39 | [Wasm](https://substrate.dev/docs/en/knowledgebase/advanced/executor#wasm-execution) and
40 | [native](https://substrate.dev/docs/en/knowledgebase/advanced/executor#native-execution) code:
41 |
42 | ```bash
43 | cargo build --release
44 | ```
45 |
46 | Note: If the build fails with `(signal: 9, SIGKILL: kill)` it has probably run out of memory. Try freeing some memory or
47 | build on another machine.
48 |
49 | ## Run
50 |
51 | ### Development Chain
52 |
53 | You can start a standalone development chain with instant sealing:
54 |
55 | ```bash
56 | cargo run -- --tmp --dev --instant-sealing
57 | ```
58 |
59 | Use a chain spec file with pre funded Developer accounts
60 |
61 | ```bash
62 | cargo run -- --tmp --chain ./resources/pint-dev.json --instant-sealing
63 | ```
64 |
65 | __NOTE: the amount of PINT in all the endowed accounts (dev accounts) of the balances pallet (
66 | see [pint-dev.json](resources/pint-dev.json)) directly affects the NAV, since this is the total amount of PINT in
67 | curculation at genesis__
68 |
69 | Or if already built
70 |
71 | ```bash
72 | ./target/release/pint --tmp --dev --instant-sealing
73 | ```
74 |
75 | This will use the [`node/src/chain_spec/dev.rs`](node/src/chain_spec/dev.rs) chain spec.
76 |
77 | ### Local Testnet
78 |
79 | Polkadot (release-v0.9.x branch)
80 |
81 | ```bash
82 | cargo build --release
83 |
84 | ./target/release/polkadot build-spec --chain rococo-local --raw --disable-default-bootnode > rococo_local.json
85 |
86 | ./target/release/polkadot --chain ./rococo_local.json -d cumulus_relay0 --validator --alice --port 9844
87 |
88 | ./target/release/polkadot --chain ./rococo_local.json -d cumulus_relay1 --validator --bob --port 9955
89 | ```
90 |
91 | PINT Parachain:
92 |
93 | ```bash
94 | # this command assumes the chain spec is in a directory named polkadot that is a sibling of the pint directory
95 | ./target/release/pint --collator --alice --chain pint-dev --ws-port 9945 --parachain-id 200 --rpc-cors all -- --execution wasm --chain ../polkadot/rococo_local.json --ws-port 9977 --rpc-cors all
96 | ```
97 |
98 | ### Registering on Local Relay Chain
99 |
100 | In order to produce blocks you will need to register the parachain as detailed in
101 | the [Substrate Cumulus Workshop](https://substrate.dev/cumulus-workshop/#/en/3-parachains/2-register) by going to
102 |
103 | Developer -> sudo -> paraSudoWrapper -> sudoScheduleParaInitialize(id, genesis)
104 |
105 | Ensure you set the `ParaId` to `200` and the `parachain: Bool` to `Yes`.
106 |
107 | ```bash
108 | cargo build --release
109 | # Build the Chain spec
110 | ./target/release/pint build-spec --disable-default-bootnode > ./pint-local-plain.json
111 | # Build the raw file
112 | ./target/release/pint build-spec --chain=./pint-local-plain.json --raw --disable-default-bootnode > ./pint-local.json
113 |
114 |
115 | # export genesis state and wasm
116 | ./target/release/pint export-genesis-state --parachain-id 200 > ./resources/para-200-genesis
117 | ./target/release/pint export-genesis-wasm > ./para-200.wasm
118 | ```
119 |
120 | * [polkadot-launch](https://github.com/paritytech/polkadot-launch) can be run by dropping the proper polkadot binary in
121 | the `./bin` folder and
122 | * Run globally
123 | * `polkadot-launch config.json`
124 | * Run locally, navigate into polkadot-launch,
125 | * ``` yarn ```
126 | * ``` yarn start ```
127 |
128 | ### Documentation
129 |
130 | ## Commands
131 |
132 | * `mkdocs serve` - Start the live-reloading docs server.
133 | * `mkdocs build` - Build the documentation site.
134 | * `mkdocs -h` - Print help message and exit.
135 |
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "relaychain": {
3 | "bin": "./bin/polkadot",
4 | "chain": "rococo-local",
5 | "nodes": [
6 | {
7 | "name": "alice",
8 | "wsPort": 9944,
9 | "port": 30444
10 | },
11 | {
12 | "name": "bob",
13 | "wsPort": 9955,
14 | "port": 30555
15 | },
16 | {
17 | "name": "charlie",
18 | "wsPort": 9966,
19 | "port": 30666
20 | }
21 | ]
22 | },
23 | "parachains": [
24 | {
25 | "bin": "./bin/pint",
26 | "chain": "dev-local",
27 | "balance": "1000000000000000000000",
28 | "nodes": [
29 | {
30 | "wsPort": 9988,
31 | "port": 31200,
32 | "name": "alice",
33 | "flags": [
34 | "--unsafe-ws-external",
35 | "--force-authoring",
36 | "--",
37 | "--execution=wasm"
38 | ]
39 | }
40 | ]
41 | }
42 | ],
43 | "simpleParachains": [],
44 | "types": {},
45 | "finalization": true
46 | }
47 |
--------------------------------------------------------------------------------
/docker/launch.Dockerfile:
--------------------------------------------------------------------------------
1 | # syntax=docker/dockerfile:experimental
2 | #
3 | # Copyright 2021 ChainSafe Systems
4 | # SPDX-License-Identifier: LGPL-3.0-only
5 | #
6 | # This Dockerfile builds the environment of e2e tests
7 | FROM debian:buster-slim
8 | COPY config.json config.json
9 | COPY js/polkadot-launch polkadot-launch
10 | COPY --from=chainsafe/pint /usr/local/bin/pint bin/
11 | COPY --from=parity/polkadot:v0.9.12 /usr/bin/polkadot bin/
12 | ENV CARGO_TERM_COLOR=always
13 | RUN apt-get update -y \
14 | && apt-get install openssl curl git -y \
15 | && curl -sL https://deb.nodesource.com/setup_15.x | bash - \
16 | && apt-get -qqy --no-install-recommends install nodejs -y \
17 | && rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb \
18 | && rm -f /var/cache/apt/*.bin \
19 | && cd polkadot-launch \
20 | && npm install \
21 | && npm run build
22 | EXPOSE 9988
23 | ENTRYPOINT [ "node", "polkadot-launch/dist/cli.js", "config.json" ]
24 |
--------------------------------------------------------------------------------
/docker/release.Dockerfile:
--------------------------------------------------------------------------------
1 | # syntax=docker/dockerfile:experimental
2 | #
3 | # Copyright 2021 ChainSafe Systems
4 | # SPDX-License-Identifier: LGPL-3.0-only
5 | #
6 | # Building layer
7 | FROM paritytech/ci-linux:production as builder
8 | COPY . .
9 | ENV CARGO_TERM_COLOR=always
10 | RUN --mount=type=cache,target=/usr/local/cargo/git \
11 | --mount=type=cache,target=/usr/local/cargo/registry \
12 | --mount=type=cache,sharing=private,target=target \
13 | cargo build --release \
14 | && mv target/release/pint /pint
15 |
16 | # Release
17 | FROM debian:buster-slim
18 | LABEL description="The docker image of PINT"
19 | COPY --from=builder /pint /usr/local/bin/
20 | RUN useradd -m -u 1000 -U -s /bin/sh -d /pint pint && \
21 | mkdir -p /pint/.local/share && \
22 | mkdir /data && \
23 | chown -R pint:pint /data && \
24 | ln -s /data /pint/.local/share/pint && \
25 | rm -rf /usr/bin /usr/sbin
26 | USER pint
27 | # 30333 for p2p traffic
28 | # 9933 for RPC call
29 | # 9944 for Websocket
30 | # 9615 for Prometheus (metrics)
31 | EXPOSE 30333 9933 9944 9615
32 | VOLUME [ "/data" ]
33 | ENTRYPOINT [ "/usr/local/bin/pint" ]
34 |
--------------------------------------------------------------------------------
/docs/.gitignore:
--------------------------------------------------------------------------------
1 | _site
2 |
--------------------------------------------------------------------------------
/docs/404.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | permalink: /404.html
4 | ---
5 |
6 |
19 |
20 |
21 |
404
22 |
23 |
Page not found :(
24 |
The requested page could not be found.
25 |
26 |
--------------------------------------------------------------------------------
/docs/assets/css/style.scss:
--------------------------------------------------------------------------------
1 | body {
2 | color: #BBB !important;
3 | font-family: "ubuntu", sans-serif;
4 | line-height: 1.75 !important;
5 | }
6 |
7 | header, footer {
8 | border: 0 !important;
9 | padding: 2% 0 !important;
10 | }
11 |
12 | h1, h2, h3, h4, h5 {
13 | color: #CCC;
14 | font-weight: 500;
15 | padding-top: 2%;
16 | }
17 |
18 | h1.title {
19 | font-size: 110%;
20 | }
21 |
22 | b, strong {
23 | color: #CCC;
24 | }
25 |
26 | a {
27 | color: #e6087b !important;
28 | }
29 |
30 | a:hover {
31 | color: #EEE !important;
32 | text-decoration: none;
33 | transition: 0.1s;
34 | }
35 |
36 | ul, li {
37 | padding: 0.5% 0;
38 | }
39 |
40 | code {
41 | padding: 4px;
42 | }
43 |
44 | pre {
45 | font-size: 17px;
46 | padding: 10px 16px;
47 | }
48 |
--------------------------------------------------------------------------------
/docs/assets/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChainSafe/PINT/acb2900a8bf45044aa15c0dd22d2d947f168bf2f/docs/assets/favicon.ico
--------------------------------------------------------------------------------
/docs/assets/img/nav-formula.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChainSafe/PINT/acb2900a8bf45044aa15c0dd22d2d947f168bf2f/docs/assets/img/nav-formula.png
--------------------------------------------------------------------------------
/docs/assets/img/pint.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChainSafe/PINT/acb2900a8bf45044aa15c0dd22d2d947f168bf2f/docs/assets/img/pint.png
--------------------------------------------------------------------------------
/docs/assets/img/set-custom-types.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChainSafe/PINT/acb2900a8bf45044aa15c0dd22d2d947f168bf2f/docs/assets/img/set-custom-types.png
--------------------------------------------------------------------------------
/docs/getting-started/installation.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Installation
4 | permalink: /getting-started/installation
5 | ---
6 |
7 | # Get Started
8 |
9 | ## Prerequisites
10 |
11 | This project currently builds against Rust nightly-2021-08-01. Assuming you have rustup already insatlled set up your local environment:
12 |
13 | ```shell
14 | rustup install nightly-2021-08-01
15 | rustup target add wasm32-unknown-unknown --toolchain nightly-2021-08-01
16 | rustup override set nightly-2021-08-01
17 | ```
18 |
19 | ## Build
20 |
21 | Once the development environment is set up, build the node template. This command will build the
22 | [Wasm](https://substrate.dev/docs/en/knowledgebase/advanced/executor#wasm-execution) and
23 | [native](https://substrate.dev/docs/en/knowledgebase/advanced/executor#native-execution) code:
24 |
25 | ```bash
26 | cargo build --release
27 | ```
28 |
29 | Note: If the build fails with `(signal: 9, SIGKILL: kill)` it has probably run out of memory. Try freeing some memory or build on another machine.
30 |
31 | ## Run
32 |
33 | ### Development Chain
34 |
35 | You can start a standalone development chain with:
36 |
37 | ```bash
38 | cargo run -- --dev --instant-sealing
39 | ```
40 |
41 | Or if already built:
42 |
43 | ```bash
44 | ./target/release/pint --dev --instant-sealing
45 | ```
46 |
47 | For [docker](https://github.com/ChainSafe/PINT/blob/main/docker/release.Dockerfile):
48 |
49 | ```
50 | docker run chainsafe/pint --dev --instant-sealing
51 | ```
52 |
53 | This will use the [`node/src/chain_spec/dev.rs`](../../node/src/chain_spec/dev.rs) chain spec.
54 |
55 | ### Local Testnet
56 |
57 | Polkadot (release-v0.9.x branch)
58 |
59 | ```
60 | cargo build --release
61 |
62 | ./target/release/polkadot build-spec --chain rococo-local --raw --disable-default-bootnode > rococo_local.json
63 |
64 | ./target/release/polkadot --chain ./rococo_local.json -d cumulus_relay0 --validator --alice --port 9844
65 |
66 | ./target/release/polkadot --chain ./rococo_local.json -d cumulus_relay1 --validator --bob --port 9955
67 | ```
68 |
69 | ##### PINT Parachain:
70 |
71 | ```
72 | # this command assumes the chain spec is in a directory named polkadot that is a sibling of the pint directory
73 | ./target/release/pint --collator --alice --chain pint-dev --ws-port 9945 --parachain-id 200 --rpc-cors all -- --execution wasm --chain ../polkadot/rococo_local.json --ws-port 9977 --rpc-cors all
74 | ```
75 |
76 | ### Registering on Local Relay Chain
77 |
78 | In order to produce blocks you will need to register the parachain as detailed in the [Substrate Cumulus Workshop](https://substrate.dev/cumulus-workshop/#/en/3-parachains/2-register) by going to
79 |
80 | Developer -> sudo -> paraSudoWrapper -> sudoScheduleParaInitialize(id, genesis)
81 |
82 | Ensure you set the `ParaId` to `200` and the `parachain: Bool` to `Yes`.
83 |
84 | ```
85 | cargo build --release
86 | # Build the Chain spec
87 | ./target/release/pint build-spec --chain=pint-dev --disable-default-bootnode > ./pint-local-plain.json
88 | # Build the raw file
89 | ./target/release/pint build-spec --chain=./pint-local-plain.json --raw --disable-default-bootnode > ./pint-local.json
90 |
91 |
92 | # export genesis state and wasm
93 | ./target/release/pint export-genesis-state --chain=pint-dev --parachain-id 200 > para-200-genesis
94 | ./target/release/pint export-genesis-wasm --chain=pint-dev > ./para-200.wasm
95 | ```
96 |
97 |
98 | ### Start a Parachain Node (Collator)
99 |
100 | From the parachain template working directory:
101 |
102 | ```bash
103 | # This assumes a ParaId of 200. Change as needed.
104 | ./target/release/pint \
105 | -d /tmp/parachain/alice \
106 | --collator \
107 | --alice \
108 | --force-authoring \
109 | --ws-port 9945 \
110 | --parachain-id 200 \
111 | -- \
112 | --execution wasm \
113 | --chain pint_local.json
114 | ```
115 |
116 |
117 |
118 | * [polkadot-launch](https://github.com/paritytech/polkadot-launch) can be run by dropping the proper polkadot binary in the `./bin` folder and
119 | * Run globally
120 | * `polkadot-launch config.json`
121 | * Run locally, navigate into polkadot-launch,
122 | * ``` yarn ```
123 | * ``` yarn start ```
124 |
125 |
126 | ## Test
127 |
128 | ### Testing PINT with cargo
129 |
130 | ```
131 | cargo test --all-features
132 | ```
133 |
134 | Will run the tests of PINT with cargo.
135 |
136 | ### Testing PINT with polkadot.js
137 |
138 | ```
139 | # the e2e tests require `polkadot-launch` as a git submodule
140 | git submodule update --recursive
141 |
142 | # install dependencies and run e2e tests
143 | cd js && yarn && yarn e2e
144 | ```
145 |
146 | Will bootstrap `PINT` with `polkadot-launch` and run all calls of PINT with `polkadot.js`
147 | to test both `PINT` can connect to `rococo` and PINT calls are workable with `polkadot.js`.
148 |
149 |
150 | ## Learn More
151 |
152 | - More detailed instructions to use Cumulus parachains are found in the
153 | [Cumulus Workshop](https://substrate.dev/cumulus-workshop/#/en/3-parachains/2-register).
154 | - Refer to the upstream [Substrate Node Template](https://github.com/substrate-developer-hub/substrate-node-template)
155 | to learn more about the structure of this project, the capabilities it encapsulates and the way in
156 | which those capabilities are implemented.
157 | - Learn more about how a parachain block is added to a finalized chain [here](https://polkadot.network/the-path-of-a-parachain-block/).
158 |
--------------------------------------------------------------------------------
/docs/getting-started/resources/developer-resources.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Developer Resources
4 | permalink: /developer-resources/
5 | ---
6 |
7 | ### Cryptography
8 |
9 | - blake2s used for hashing
10 | - ed25519 (signing)
11 | - ed25519 (curve)
12 |
13 | ### WASM
14 |
15 | - WASM Specification
16 | - Wasm on the Blockchain: The Lesser Evil [blog post]
17 |
18 | ### Polkadot
19 |
20 | - Polkadot Wiki
21 | - Polkadot Consensus Wiki
22 | - Polkadot Runtime Environment Specification (Section 8.2)
23 | - Rust Docs: finality_grandpa
24 | - paritytech/finality_grandpa
25 | - The State of Crypto Interoperability Explained in Pictures
26 |
27 | #### Parachains
28 |
29 | - The Parachain (Blog Post)
30 | - Parachains on Polkadot Wiki
31 | - Parathreads (Blog Post)
32 | - Parathreads on Polkadot Wiki
33 | - The Path of a Parachain Block
34 | - The Path of a Parachain Block (Video)
35 |
36 | ### Substrate
37 |
38 | - Official Substrate Documentation
39 |
40 |
41 |
--------------------------------------------------------------------------------
/docs/getting-started/resources/general-resources.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: General Resources
4 | permalink: /getting-started/resources/general-resources
5 | ---
6 |
7 | ## Welcome
8 |
9 | Here you will find resources to help facilitate your learning about _Polkadot_. Don't worry if you are unfamiliar with these terms, the resources listed here assume no prior knowledge about them.
10 |
11 | ## Polkadot
12 |
13 | To start, it would be extremely beneficial to have an understanding of the Polkadot Network. For a high-level introduction to Polkadot, check out the lightpaper. To understand the motivation behind Polkadot's creation and what makes it unique, check out this great blog post A brief summary of everything Substrate and Polkadot. While reading, it would be helpful to note that Substrate.
14 |
15 | ### Additional Resources
16 |
17 | #### Docs
18 |
19 | - Polkadot Wiki
20 |
21 | - Polkadot Paper
22 |
23 | #### Articles
24 |
25 | - How Polkadot tackles the biggest problems facing blockchain innovators - June 7th 2018
26 |
27 | #### Block explorers
28 |
29 | - Polkadot Explorer
30 |
31 | - Polkascan - Polkadot block explorer
32 |
33 | - Polkadot Telemetry Service
34 |
35 | ### Additional Resources
36 |
37 | ## Substrate
38 |
39 | #### Docs
40 |
41 | - Substrate Documentation
42 |
43 | #### Videos
44 |
45 | - Gavin Wood on Substrate at Event Horizon 2018
46 |
47 | - Rob Habermeier presents Parity Substrate
48 |
49 | #### Articles
50 |
51 | - What is Substrate? - July 9th 2018
52 |
53 | - A brief summary of everything Substrate and Polkadot - March 18th 2019
54 |
55 | ## Web3 Foundation
56 |
57 | #### Docs
58 |
59 | - Web3 Foundation's General Grants Program
60 |
61 | #### Articles
62 |
63 | - Why Wy Need Web 3.0 - September 12th 2018
64 |
--------------------------------------------------------------------------------
/docs/usage/command-line.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Command-Line
4 | permalink: /usage/command-line/
5 | ---
6 |
7 | ## Commands
8 |
9 | ### Build
10 |
11 | This will build the
12 | [Wasm Runtime](https://substrate.dev/docs/en/knowledgebase/advanced/executor#wasm-execution) and
13 | [native](https://substrate.dev/docs/en/knowledgebase/advanced/executor#native-execution) of PINT:
14 |
15 | ```
16 | cargo build --release
17 | ```
18 |
19 | ### Test
20 |
21 | Run all tests
22 | ```
23 | cargo test
24 | ```
25 |
26 | Run all tests, including benchmarks
27 | ```
28 | cargo test --all-features
29 | ```
30 |
31 |
32 | ### Start the PINT chain
33 |
34 | ```
35 | ./target/release/pint --dev --instant-sealing
36 | ```
37 |
38 | This will seal blocks instantly. The node will never produce blocks
39 |
40 | Use the docker image:
41 |
42 | ```
43 | docker run -it -p 9944:9944 chainsafe/pint --tmp --dev --instant-sealing --rpc-external --ws-external --rpc-cors all --rpc-methods Unsafe
44 | ```
45 |
46 | If the [polkadot.js UI](https://polkadot.js.org/apps/#/explorer) fails to connect try adding `--rpc-cors all`.
47 |
--------------------------------------------------------------------------------
/docs/usage/configuration.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default title: Configuration permalink: /usage/configuration/
3 | ---
4 |
5 | # Configuration
6 |
7 | ## Polkadot JS UI
8 |
9 | In order to use [polkadot.js UI](https://polkadot.js.org/apps/#/explorer) to interact with the chain you need to specify
10 | the custom PINT is using by copying the [types.json](../../resources/types.json) object into the input
11 | at `Settings > Devoloper` in the polkadot js UI menu.
12 |
13 | 
14 |
15 | ## Chain Spec
16 |
17 | By default, PINT uses the [dev chain spec](../../node/src/chain_spec/dev.rs).
18 |
19 | The `GenesisConfig` configures the initial chain state at genesis.
20 |
21 | Excerpt:
22 |
23 | ```rust
24 | GenesisConfig {
25 | system: SystemConfig {
26 | code: WASM_BINARY.expect("WASM binary was not build, please build it!").to_vec(),
27 | changes_trie_config: Default::default (),
28 | },
29 | // This ensures the `endowed_accounts` have funds in their accounts
30 | balances: BalancesConfig { balances: endowed_accounts.iter().cloned().map( | k| (k, 1 < < 12)).collect() },
31 | // This configures the comittee
32 | committee: CommitteeConfig { council_members: council_members.clone(), ..Default::default () },
33 | // all council members can create feeds and no feeds in genesis
34 | chainlink_feed: ChainlinkFeedConfig { feeds: Default::default(), pallet_admin: Some(root_key.clone()), feed_creators: council_members },
35 | sudo: SudoConfig { key: root_key },
36 | parachain_info: ParachainInfoConfig { parachain_id: id },
37 | }
38 | ```
39 |
40 | To run the chain with a custom chainspec we need to provide the path to your chainspec json file:
41 |
42 | *NOTE:* the id of your custom chain spec should contain `dev` in order to run it as standalone chain.
43 |
44 | ```
45 | ./target/release/pint --tmp --chain=
46 | ```
47 |
48 | Read more about substrate's [Chain Specification](https://substrate.dev/docs/en/knowledgebase/integrate/chain-spec)
49 | and [creating private networks](https://substrate.dev/docs/en/tutorials/start-a-private-network)
50 |
51 | #### Build the chainspec
52 |
53 | ```
54 | ./target/release/pint build-spec \
55 | --disable-default-bootnode > pint-local-plain.json
56 | ```
57 |
58 | #### Build the raw chainspec file
59 | ```
60 | ./target/release/pint build-spec \
61 | --chain=./pint-local-plain.json \
62 | --raw --disable-default-bootnode > pint-local-raw.json
63 | ```
64 |
--------------------------------------------------------------------------------
/js/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 4,
3 | "overrides": [
4 | {
5 | "files": "*.json",
6 | "options": {
7 | "tabWidth": 2
8 | }
9 | },
10 | {
11 | "files": ".prettierrc",
12 | "options": {
13 | "tabWidth": 2
14 | }
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/js/e2e/README.md:
--------------------------------------------------------------------------------
1 | # E2E
2 |
3 | E2E tests for PINT
4 |
5 | This package will traverse all APIs provided written in the config
6 |
7 |
8 | ## LICENSE
9 |
10 | GNU-v3
11 |
--------------------------------------------------------------------------------
/js/e2e/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@pint/e2e",
3 | "version": "1.0.0",
4 | "description": "E2E tests for PINT",
5 | "main": "index.js",
6 | "repository": "https://github.com/ChainSafe/PINT",
7 | "author": "ChainSafe",
8 | "license": "GNU-v3",
9 | "private": true,
10 | "devDependencies": {
11 | "@types/bn.js": "^5.1.0",
12 | "@types/node": "^15.3.1",
13 | "ts-node": "^10.0.0",
14 | "tslint": "^6.1.3",
15 | "typescript": "^4.2.4"
16 | },
17 | "dependencies": {
18 | "@open-web3/orml-types": "^0.9.3",
19 | "@pint/types": "^1.0.0",
20 | "@polkadot/api": "^6.8.1",
21 | "@polkadot/keyring": "^7.8.2",
22 | "@polkadot/types": "^6.8.1",
23 | "@polkadot/util-crypto": "^7.8.2",
24 | "bn.js": "^5.2.0",
25 | "find-up": "^5.0.0"
26 | },
27 | "scripts": {
28 | "start": "ts-node index.ts",
29 | "build": "tsc --strict",
30 | "lint": "tsc --noEmit --strict && tslint --project ./tsconfig.json"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/js/e2e/src/config.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Config of E2E tests
3 | */
4 | import { ApiPromise } from "@polkadot/api";
5 | import { KeyringPair } from "@polkadot/keyring/types";
6 | import { Extrinsic } from "./extrinsic";
7 |
8 | /**
9 | * The config of e2e tests
10 | */
11 | export interface Config {
12 | api: ApiPromise;
13 | pair: KeyringPair;
14 | exs: Extrinsic[];
15 | config: ExtrinsicConfig;
16 | }
17 |
18 | /**
19 | * The config of extrinsics
20 | */
21 | export interface ExtrinsicConfig {
22 | alice: KeyringPair;
23 | bob: KeyringPair;
24 | charlie: KeyringPair;
25 | dave: KeyringPair;
26 | ziggy: KeyringPair;
27 | }
28 |
29 | /**
30 | * Extrinsic interface
31 | */
32 | export interface IExtrinsic {
33 | // extrinsic id
34 | id?: string;
35 | // use signed origin
36 | signed?: KeyringPair;
37 | pallet: string;
38 | call: string;
39 | args: any[];
40 | shared?: () => Promise;
41 | verify?: (shared?: any) => Promise;
42 | proposal?: boolean;
43 | /// Required calls or functions before this extrinsic
44 | required?: string[];
45 | /// Calls or functions with this extrinsic
46 | with?: IExtrinsic[];
47 | }
48 |
--------------------------------------------------------------------------------
/js/e2e/src/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * E2E tests for PINT
3 | */
4 | import Runner from "./runner";
5 | export { Config, ExtrinsicConfig, IExtrinsic } from "./config";
6 | export * as Launch from "./launch";
7 | export { Extrinsic } from "./extrinsic";
8 | export { assert, expandId, waitBlock } from "./util";
9 | export { Runner };
10 |
--------------------------------------------------------------------------------
/js/e2e/src/launch.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * pint-launch
3 | */
4 | import fs from "fs";
5 | import findUp from "find-up";
6 | import path from "path";
7 | import { fork, ChildProcess, StdioOptions, spawn } from "child_process";
8 |
9 | /**
10 | * Launch PINT locally
11 | *
12 | * @param stdio {StdioOptions}
13 | * @returns {Promise}
14 | */
15 | export async function local(stdio?: StdioOptions): Promise {
16 | return fork("js/polkadot-launch/src/cli.ts", ["config.json"], {
17 | cwd: path.resolve(String(await findUp("Cargo.toml")), ".."),
18 | killSignal: "SIGINT",
19 | stdio,
20 | } as any);
21 | }
22 |
23 | /**
24 | * Launch PINT via docker (CI)
25 | *
26 | * @param stdio {StdioOptions}
27 | * @returns {Promise}
28 | */
29 | export async function docker(stdio?: StdioOptions): Promise {
30 | return spawn(
31 | "sudo",
32 | [
33 | "docker",
34 | "run",
35 | "--name",
36 | "launch",
37 | "-p",
38 | "9988:9988",
39 | "-p",
40 | "9966:9966",
41 | "-p",
42 | "9999:9999",
43 | "--ip",
44 | "0.0.0.0",
45 | "launch",
46 | ],
47 | {
48 | stdio,
49 | }
50 | );
51 | }
52 |
53 | /**
54 | * Launch PINT via local or docker
55 | *
56 | * @param stdio {StdioOptions}
57 | * @returns {Promise}
58 | */
59 | export async function launch(stdio?: StdioOptions): Promise {
60 | const root = await findUp("Cargo.toml");
61 | if (fs.existsSync(path.resolve(String(root), "../bin/pint"))) {
62 | return local(stdio);
63 | } else {
64 | return docker(stdio);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/js/e2e/src/util.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Utils
3 | */
4 | import { IExtrinsic } from "./config";
5 |
6 | export function assert(r: boolean, msg: string): string | void {
7 | if (!r) {
8 | return msg;
9 | }
10 | }
11 |
12 | /**
13 | * Expand Id of extrinsic
14 | */
15 | export function expandId(e: IExtrinsic): IExtrinsic {
16 | if (!e.id) e.id = `${e.pallet}.${e.call}`;
17 |
18 | if (e.with) {
19 | for (const r of e.with) {
20 | if (typeof r !== "function") {
21 | expandId(r);
22 | }
23 | }
24 | }
25 |
26 | return e;
27 | }
28 |
29 | /**
30 | * Wait for n blocks
31 | *
32 | * The current gap of producing a block is 4s,
33 | * we use 5s here.
34 | *
35 | * @param {number} block
36 | * @returns {Promise}
37 | */
38 | export async function waitBlock(block: number): Promise {
39 | return new Promise((resolve) => setTimeout(resolve, block * 12000));
40 | }
41 |
--------------------------------------------------------------------------------
/js/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "indent": [true, "spaces", 2],
3 | "compilerOptions": {
4 | "allowSyntheticDefaultImports": true,
5 | "baseUrl": ".",
6 | "declaration": true,
7 | "esModuleInterop": true,
8 | "outDir": "lib",
9 | "module": "commonjs",
10 | "moduleResolution": "node",
11 | "noImplicitAny": true,
12 | "resolveJsonModule": true,
13 | "sourceMap": true,
14 | "skipLibCheck": true,
15 | "target": "es6"
16 | },
17 | "include": ["index.ts", "src/**/*"],
18 | "exclude": ["node_modules"]
19 | }
20 |
--------------------------------------------------------------------------------
/js/e2e/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tslint:recommended",
3 | "rules": {
4 | "curly": [true, "ignore-same-line"],
5 | "max-classes-per-file": false,
6 | "max-line-length": {
7 | "options": [120]
8 | },
9 | "new-parens": true,
10 | "no-arg": true,
11 | "no-bitwise": true,
12 | "no-conditional-assignment": true,
13 | "no-consecutive-blank-lines": false,
14 | "no-console": false
15 | },
16 | "linterOptions": {
17 | "exclude": []
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/js/finalize/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Test the finalization of parachain intergration
3 | */
4 | import fs from "fs";
5 | import path from "path";
6 | import { Launch } from "@pint/e2e/src";
7 | import findUp from "find-up";
8 | import { ChildProcess, spawn } from "child_process";
9 |
10 | // Message of launching complete
11 | const LAUNCH_COMPLETE: string = "POLKADOT LAUNCH COMPLETE";
12 |
13 | // PINT finalization regex
14 | export const PINT_FINALIZE: RegExp = /\[Parachain\].*finalized #(\d)/;
15 |
16 | // Kill subprocesses
17 | function killAll(ps: ChildProcess, exitCode: number) {
18 | try {
19 | ps.send && !ps.killed && ps.send("exit");
20 | ps.kill("SIGINT");
21 | } catch (e) {
22 | if (e.code !== "EPERM") {
23 | process.stdout.write(e);
24 | process.exit(2);
25 | }
26 | }
27 |
28 | process.exit(exitCode);
29 | }
30 |
31 | /**
32 | * Tail file and done when got expected message
33 | */
34 | async function tail(
35 | file: string,
36 | match: (s: string) => boolean
37 | ): Promise {
38 | const root = await findUp("Cargo.toml");
39 |
40 | return new Promise(async (resolve) => {
41 | const ps = fs.existsSync(path.resolve(String(root), "../bin/pint"))
42 | ? spawn("tail", ["-f", file], {
43 | cwd: path.resolve(String(root), ".."),
44 | stdio: "pipe",
45 | })
46 | : spawn("docker", ["exec", "launch", "tail", "-f", `${file}`], {
47 | stdio: "pipe",
48 | });
49 |
50 | ps.stdout.on("data", (chunk: Buffer) => {
51 | chunk && match(chunk.toString()) && resolve(null);
52 | });
53 |
54 | ps.stderr.on("data", (chunk: Buffer) => {
55 | process.stderr.write(chunk);
56 | process.exit(1);
57 | });
58 | });
59 | }
60 |
61 | /**
62 | * Entrypoint
63 | */
64 | async function main() {
65 | const ps = await Launch.launch("pipe");
66 | ps.stdout.on("data", async (chunk: Buffer) => {
67 | process.stdout.write(chunk.toString());
68 | if (chunk.includes(LAUNCH_COMPLETE)) {
69 | await tail("9988.log", (chunk: string): boolean => {
70 | process.stdout.write(chunk);
71 | const match = chunk.match(PINT_FINALIZE);
72 | return (
73 | match && match.length == 2 && Number.parseInt(match[1]) > 0
74 | );
75 | });
76 |
77 | console.log("FINALIZE SUCCEED!");
78 | process.exit(0);
79 | }
80 | });
81 |
82 | // Kill all processes when exiting.
83 | process.on("exit", () => {
84 | console.log("-> exit polkadot-launch...");
85 | killAll(ps, process.exitCode);
86 | });
87 |
88 | // Log errors
89 | ps.stderr.on("data", (chunk: Buffer) =>
90 | process.stderr.write(chunk.toString())
91 | );
92 | }
93 |
94 | (() => {
95 | main();
96 | })();
97 |
--------------------------------------------------------------------------------
/js/finalize/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@pint/finalization",
3 | "version": "1.0.0",
4 | "description": "Test the finalization in parachain intergration",
5 | "main": "index.js",
6 | "license": "MIT",
7 | "private": true,
8 | "devDependencies": {
9 | "@types/node": "^15.3.1",
10 | "ts-node": "^10.0.0",
11 | "tslint": "^6.1.3",
12 | "typescript": "^4.2.4"
13 | },
14 | "dependencies": {
15 | "@pint/e2e": "^1.0.0",
16 | "find-up": "^5.0.0"
17 | },
18 | "scripts": {
19 | "start": "ts-node index.ts",
20 | "build": "tsc --strict",
21 | "lint": "tsc --noEmit --strict && tslint --project ./tsconfig.json"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/js/finalize/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "indent": [true, "spaces", 2],
3 | "compilerOptions": {
4 | "allowSyntheticDefaultImports": true,
5 | "baseUrl": ".",
6 | "declaration": true,
7 | "esModuleInterop": true,
8 | "outDir": "lib",
9 | "module": "commonjs",
10 | "moduleResolution": "node",
11 | "noImplicitAny": true,
12 | "resolveJsonModule": true,
13 | "sourceMap": true,
14 | "skipLibCheck": true,
15 | "target": "es6"
16 | },
17 | "include": ["index.ts", "src/**/*"],
18 | "exclude": ["node_modules"]
19 | }
20 |
--------------------------------------------------------------------------------
/js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "workspaces": [
4 | "e2e",
5 | "pint-types-bundle",
6 | "finalize"
7 | ],
8 | "scripts": {
9 | "e2e": "ts-node e2e/index.ts",
10 | "update-pint-types": "ts-node scripts/update_pint_types.ts"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/js/pint-types-bundle/.gitignore:
--------------------------------------------------------------------------------
1 | # ignore files generated by typescript
2 | dist/
3 | node_modules/
4 |
--------------------------------------------------------------------------------
/js/pint-types-bundle/README.md:
--------------------------------------------------------------------------------
1 | # PINT Types
2 |
3 | Substrate types used in PINT parachain.
4 |
5 |
6 | ## Usage
7 |
8 | Import the types in your JS or TS app.
9 |
10 | ```ts
11 | import definitions from "@pint/types";
12 | ```
--------------------------------------------------------------------------------
/js/pint-types-bundle/chainlink.json:
--------------------------------------------------------------------------------
1 | {
2 | "Address": "MultiAddress",
3 | "LookupSource": "MultiAddress",
4 | "FeedId": "u32",
5 | "RoundId": "u32",
6 | "Value": "u128",
7 | "FeedConfig": {
8 | "owner": "AccountId",
9 | "pending_owner": "Option",
10 | "submission_value_bounds": "(Value, Value)",
11 | "submission_count_bounds": "(u32, u32)",
12 | "payment": "Balance",
13 | "timeout": "BlockNumber",
14 | "decimals": "u8",
15 | "description": "Vec",
16 | "restart_delay": "RoundId",
17 | "reporting_round": "RoundId",
18 | "latest_round": "RoundId",
19 | "first_valid_round": "Option",
20 | "oracle_count": "u32",
21 | "pruning_window": "RoundId",
22 | "next_round_to_prune": "RoundId",
23 | "debt": "Balance",
24 | "max_debt": "Option"
25 | },
26 | "FeedConfigOf": "FeedConfig",
27 | "Round": {
28 | "started_at": "BlockNumber",
29 | "answer": "Option",
30 | "updated_at": "Option",
31 | "answered_in_round": "Option"
32 | },
33 | "RoundOf": "Round",
34 | "RoundDetails": {
35 | "submissions": "Vec",
36 | "submission_count_bounds": "(u32, u32)",
37 | "payment": "Balance",
38 | "timeout": "BlockNumber"
39 | },
40 | "RoundDetailsOf": "RoundDetails",
41 | "OracleMeta": {
42 | "withdrawable": "Balance",
43 | "admin": "AccountId",
44 | "pending_admin": "Option"
45 | },
46 | "OracleMetaOf": "OracleMeta",
47 | "OracleStatus": {
48 | "starting_round": "RoundId",
49 | "ending_round": "Option",
50 | "last_reported_round": "Option",
51 | "last_started_round": "Option",
52 | "latest_submission": "Option"
53 | },
54 | "OracleStatusOf": "OracleStatus",
55 | "Requester": {
56 | "delay": "RoundId",
57 | "last_started_round": "Option"
58 | },
59 | "RoundData": {
60 | "started_at": "BlockNumber",
61 | "answer": "Value",
62 | "updated_at": "BlockNumber",
63 | "answered_in_round": "RoundId"
64 | },
65 | "RoundDataOf": "RoundData",
66 | "SubmissionBounds": "(u32, u32)"
67 | }
68 |
--------------------------------------------------------------------------------
/js/pint-types-bundle/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@pint/types",
3 | "version": "1.0.0",
4 | "description": "Bundled types to instantiate the Polkadot JS api with PINT",
5 | "main": "dist/index.js",
6 | "types": "dist/index.d.ts",
7 | "prepublish": "tsc",
8 | "scripts": {
9 | "build": "tsc"
10 | },
11 | "keywords": ["pint", "types", "polkadot", "api"],
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/ChainSafe/PINT.git"
15 | },
16 | "author": "ChainSafe Systems",
17 | "license": "GPL-3.0-only",
18 | "dependencies": {
19 | "@polkadot/keyring": "^7.8.2",
20 | "@polkadot/types": "^6.8.1"
21 | },
22 | "devDependencies": {
23 | "typescript": "^4.2.4"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/js/pint-types-bundle/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "indent": [true, "spaces", 2],
3 | "compilerOptions": {
4 | "target": "es5",
5 | "module": "commonjs",
6 | "lib": ["es2017", "es7", "es6", "dom"],
7 | "declaration": true,
8 | "outDir": "dist",
9 | "strict": true,
10 | "esModuleInterop": true,
11 | "resolveJsonModule": true
12 | },
13 | "exclude": ["node_modules", "dist"]
14 | }
15 |
--------------------------------------------------------------------------------
/js/scripts/update_pint_types.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Exports `pint-types-bundle` to `/resources/types.json`
3 | */
4 |
5 | import fs from "fs";
6 | import path from "path";
7 | import { definitions } from "../pint-types-bundle/index";
8 |
9 | (async () => {
10 | const types = (definitions.types as any)[0].types;
11 | if (types.length === 0) {
12 | throw "No PINT types provided";
13 | }
14 |
15 | const target = path.resolve(__dirname, "../../resources/types.json");
16 | fs.writeFileSync(target, JSON.stringify(types, null, 2));
17 | console.log("Updated \x1b[36m/resources/types.json\x1b[0m !");
18 | })();
19 |
--------------------------------------------------------------------------------
/mkdocs.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 ChainSafe Systems
2 | # SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | site_name: PINT Docs
5 | site_description: The Official Documentation for PINT | A Polkadot ecosystem index for investors
6 |
7 | repo_name: chainsafe/pint
8 | repo_url: https://github.com/ChainSafe/pint
9 | edit_uri: edit/development/docs/
10 |
11 | # Configuration
12 | markdown_extensions:
13 | - meta
14 | - admonition
15 | - codehilite
16 | - toc:
17 | permalink: true
18 |
19 | theme:
20 | name: material
21 | palette:
22 | primary: brown
23 | accent: yellow
24 | theme:
25 | # Light mode
26 | - media: "(prefers-color-scheme: light)"
27 | scheme: default
28 | primary: brown
29 | accent: yellow
30 | toggle:
31 | icon: material/toggle-switch-off-outline
32 | name: Switch to dark mode
33 | # Dark mode
34 | - media: "(prefers-color-scheme: dark)"
35 | scheme: slate
36 | primary: brown
37 | accent: yellow
38 | toggle:
39 | icon: material/toggle-switch
40 | name: Switch to light mode
41 | favicon: ./assets/favicon.ico
42 | features:
43 | # - navigation.instant
44 | - navigation.tracking
45 | - navigation.sections
46 | - navigation.tabs
47 | - navigation.tabs.sticky
48 | nav:
49 | - Getting Started:
50 | - Overview: ./index.md
51 | - Architecture: ./getting-started/overview/architecture.md
52 | - Installation: ./getting-started/installation.md
53 | - General Resources: ./getting-started/resources/general-resources.md
54 | - Developer Resources: ./getting-started/resources/developer-resources.md
55 | - Usage:
56 | - Command Line: ./usage/command-line.md
57 | - Configuration: ./usage/configuration.md
58 | - API Docs: ./api/pint_runtime_dev/index.html
59 | # - Testing and Debugging:
60 | # - Test Suite: ./testing-and-debugging/test-suite.md
61 | # - Debugging: ./testing-and-debugging/debugging.md
62 | # - Contributing:
63 | # - Overview: ./contributing.md
64 | extra:
65 | social:
66 | - icon: fontawesome/brands/github-alt
67 | link: https://github.com/ChainSafe/pint
68 | - icon: fontawesome/brands/twitter
69 | link: https://twitter.com/ChainSafeth
70 |
--------------------------------------------------------------------------------
/node/build.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed};
5 |
6 | fn main() {
7 | generate_cargo_keys();
8 | rerun_if_git_head_changed();
9 | }
10 |
--------------------------------------------------------------------------------
/node/src/chain_spec/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 | use primitives::{AccountId, AccountPublic};
4 | use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};
5 | use serde::{Deserialize, Serialize};
6 | use sp_consensus_aura::sr25519::AuthorityId as AuraId;
7 | use sp_core::{Pair, Public};
8 | use sp_runtime::traits::IdentifyAccount;
9 |
10 | pub mod dev;
11 | #[cfg(feature = "pint")]
12 | pub mod pint;
13 | #[cfg(feature = "shot")]
14 | pub mod shot;
15 |
16 | /// The extensions for the [`DevChainSpec`].
17 | #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)]
18 | #[serde(deny_unknown_fields)]
19 | pub struct Extensions {
20 | /// The relay chain of the Parachain.
21 | pub relay_chain: String,
22 | /// The id of the Parachain.
23 | pub para_id: u32,
24 | }
25 |
26 | impl Extensions {
27 | /// Try to get the extension from the given `ChainSpec`.
28 | pub fn try_get(chain_spec: &dyn sc_service::ChainSpec) -> Option<&Self> {
29 | sc_chain_spec::get_extension(chain_spec.extensions())
30 | }
31 | }
32 |
33 | /// Helper function to generate a crypto pair from seed
34 | pub fn get_from_seed(seed: &str) -> ::Public {
35 | TPublic::Pair::from_string(&format!("//{}", seed), None).expect("static values are valid; qed").public()
36 | }
37 |
38 | /// Helper function to generate an account ID from seed
39 | pub fn get_account_id_from_seed(seed: &str) -> AccountId
40 | where
41 | AccountPublic: From<::Public>,
42 | {
43 | AccountPublic::from(get_from_seed::(seed)).into_account()
44 | }
45 |
46 | /// Generate collator keys from seed.
47 | ///
48 | /// This function's return type must always match the session keys of the chain
49 | /// in tuple format.
50 | pub fn get_collator_keys_from_seed(seed: &str) -> AuraId {
51 | get_from_seed::(seed)
52 | }
53 |
--------------------------------------------------------------------------------
/node/src/cli.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | use crate::chain_spec;
5 | use cumulus_client_cli;
6 | use sc_cli;
7 | use std::path::PathBuf;
8 | use structopt::StructOpt;
9 |
10 | /// Sub-commands supported by the collator.
11 | #[derive(Debug, StructOpt)]
12 | pub enum Subcommand {
13 | /// Export the genesis state of the parachain.
14 | #[structopt(name = "export-genesis-state")]
15 | ExportGenesisState(ExportGenesisStateCommand),
16 |
17 | /// Export the genesis wasm of the parachain.
18 | #[structopt(name = "export-genesis-wasm")]
19 | ExportGenesisWasm(ExportGenesisWasmCommand),
20 |
21 | /// Build a chain specification.
22 | BuildSpec(sc_cli::BuildSpecCmd),
23 |
24 | /// Validate blocks.
25 | CheckBlock(sc_cli::CheckBlockCmd),
26 |
27 | /// Export blocks.
28 | ExportBlocks(sc_cli::ExportBlocksCmd),
29 |
30 | /// Export the state of a given block into a chain spec.
31 | ExportState(sc_cli::ExportStateCmd),
32 |
33 | /// Import blocks.
34 | ImportBlocks(sc_cli::ImportBlocksCmd),
35 |
36 | /// Remove the whole chain.
37 | PurgeChain(cumulus_client_cli::PurgeChainCmd),
38 |
39 | /// Revert the chain to a previous state.
40 | Revert(sc_cli::RevertCmd),
41 |
42 | /// The custom benchmark subcommmand benchmarking runtime pallets.
43 | #[structopt(name = "benchmark", about = "Benchmark runtime pallets.")]
44 | Benchmark(frame_benchmarking_cli::BenchmarkCmd),
45 | }
46 |
47 | /// Command for exporting the genesis state of the parachain
48 | #[derive(Debug, StructOpt)]
49 | pub struct ExportGenesisStateCommand {
50 | /// Output file name or stdout if unspecified.
51 | #[structopt(parse(from_os_str))]
52 | pub output: Option,
53 |
54 | /// Id of the parachain this state is for.
55 | ///
56 | /// Default: 100
57 | #[structopt(long)]
58 | pub parachain_id: Option,
59 |
60 | /// Write output in binary. Default is to write in hex.
61 | #[structopt(short, long)]
62 | pub raw: bool,
63 |
64 | /// The name of the chain for that the genesis state should be exported.
65 | #[structopt(short, long)]
66 | pub chain: Option,
67 | }
68 |
69 | /// Command for exporting the genesis wasm file.
70 | #[derive(Debug, StructOpt)]
71 | pub struct ExportGenesisWasmCommand {
72 | /// Output file name or stdout if unspecified.
73 | #[structopt(parse(from_os_str))]
74 | pub output: Option,
75 |
76 | /// Write output in binary. Default is to write in hex.
77 | #[structopt(short, long)]
78 | pub raw: bool,
79 |
80 | /// The name of the chain for that the genesis wasm file should be exported.
81 | #[structopt(long)]
82 | pub chain: Option,
83 | }
84 |
85 | #[derive(Debug, StructOpt)]
86 | #[structopt(settings = &[
87 | structopt::clap::AppSettings::GlobalVersion,
88 | structopt::clap::AppSettings::ArgsNegateSubcommands,
89 | structopt::clap::AppSettings::SubcommandsNegateReqs,
90 | ])]
91 | pub struct Cli {
92 | #[structopt(subcommand)]
93 | pub subcommand: Option,
94 |
95 | #[structopt(flatten)]
96 | pub run: cumulus_client_cli::RunCmd,
97 |
98 | /// Relaychain arguments
99 | #[structopt(raw = true)]
100 | pub relaychain_args: Vec,
101 |
102 | /// Instant block sealing
103 | ///
104 | /// Can only be used with `--dev`
105 | #[structopt(long = "instant-sealing")]
106 | pub instant_sealing: bool,
107 | }
108 |
109 | #[derive(Debug)]
110 | pub struct RelayChainCli {
111 | /// The actual relay chain cli object.
112 | pub base: polkadot_cli::RunCmd,
113 |
114 | /// Optional chain id that should be passed to the relay chain.
115 | pub chain_id: Option,
116 |
117 | /// The base path that should be used by the relay chain.
118 | pub base_path: Option,
119 | }
120 |
121 | impl RelayChainCli {
122 | /// Parse the relay chain CLI parameters using the para chain
123 | /// `Configuration`.
124 | pub fn new<'a>(
125 | para_config: &sc_service::Configuration,
126 | relay_chain_args: impl Iterator- ,
127 | ) -> Self {
128 | let extension = chain_spec::Extensions::try_get(&*para_config.chain_spec);
129 | let chain_id = extension.map(|e| e.relay_chain.clone());
130 | let base_path = para_config.base_path.as_ref().map(|x| x.path().join("polkadot"));
131 | Self { base_path, chain_id, base: polkadot_cli::RunCmd::from_iter(relay_chain_args) }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/node/src/instant_finalize.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | use sc_consensus::BlockImport;
5 | use sp_runtime::traits::Block as BlockT;
6 |
7 | pub struct InstantFinalizeBlockImport(I);
8 |
9 | impl InstantFinalizeBlockImport {
10 | /// Create a new instance.
11 | pub fn new(inner: I) -> Self {
12 | Self(inner)
13 | }
14 | }
15 |
16 | #[async_trait::async_trait]
17 | impl BlockImport for InstantFinalizeBlockImport
18 | where
19 | Block: BlockT,
20 | I: BlockImport + Send,
21 | {
22 | type Error = I::Error;
23 | type Transaction = I::Transaction;
24 |
25 | async fn check_block(
26 | &mut self,
27 | block: sc_consensus::BlockCheckParams,
28 | ) -> Result {
29 | self.0.check_block(block).await
30 | }
31 |
32 | async fn import_block(
33 | &mut self,
34 | mut block_import_params: sc_consensus::BlockImportParams,
35 | cache: std::collections::HashMap>,
36 | ) -> Result {
37 | block_import_params.finalized = true;
38 | self.0.import_block(block_import_params, cache).await
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/node/src/lib.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | pub mod chain_spec;
5 | pub mod client;
6 | pub mod instant_finalize;
7 | pub mod service;
8 |
--------------------------------------------------------------------------------
/node/src/main.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | //! Substrate Parachain Node Template CLI
5 |
6 | #![warn(missing_docs)]
7 |
8 | mod chain_spec;
9 | #[macro_use]
10 | mod service;
11 | mod cli;
12 | mod client;
13 | mod command;
14 | mod instant_finalize;
15 |
16 | fn main() -> sc_cli::Result<()> {
17 | command::run()
18 | }
19 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "PINT",
3 | "lockfileVersion": 2,
4 | "requires": true,
5 | "packages": {}
6 | }
7 |
--------------------------------------------------------------------------------
/pallets/asset-index/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ['ChainSafe Systems']
3 | description = 'FRAME pallet to implement PINT asset index.'
4 | edition = '2018'
5 | license = 'LGPL-3.0-only'
6 | name = 'pallet-asset-index'
7 | readme = 'README.md'
8 | repository = 'https://github.com/ChainSafe/PINT/'
9 | version = '0.0.1'
10 |
11 | [dependencies]
12 | serde = { version = "1.0.130", features = ["derive"], optional = true }
13 | codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false }
14 | scale-info = { version = "1.0", default-features = false, features = ["derive"] }
15 |
16 | # Substrate Dependencies
17 | sp-core = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
18 | frame-support = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
19 | frame-system = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
20 | frame-benchmarking = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false, optional = true }
21 |
22 | # Polkadot Dependencies
23 | polkadot-parachain = { git = 'https://github.com/paritytech/polkadot', branch = 'release-v0.9.13', default-features = false }
24 | xcm = { git = 'https://github.com/paritytech/polkadot', branch = 'release-v0.9.13', default-features = false }
25 | xcm-executor = { git = 'https://github.com/paritytech/polkadot', branch = 'release-v0.9.13', default-features = false }
26 |
27 | # PINT dependencies
28 | pallet-chainlink-feed = { git = 'https://github.com/smartcontractkit/chainlink-polkadot', branch = 'polkadot-v0.9.13', default-features = false }
29 | pallet-price-feed = { path = "../price-feed", default-features = false }
30 | primitives = { path = "../../primitives/primitives", default-features = false }
31 |
32 | # ORML Dependencies
33 | orml-traits = { git = 'https://github.com/open-web3-stack/open-runtime-module-library', branch = 'master', default-features = false }
34 |
35 | [dev-dependencies]
36 | serde = "1.0.130"
37 |
38 | sp-io = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
39 | sp-runtime = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
40 | sp-std = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
41 |
42 | pallet-balances = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
43 |
44 | pallet-saft-registry = { path = "../saft-registry" }
45 |
46 | orml-tokens = { git = 'https://github.com/open-web3-stack/open-runtime-module-library', branch = 'master' }
47 | rand = "0.8.4"
48 |
49 | [features]
50 | default = ['std']
51 | std = [
52 | 'serde',
53 | 'codec/std',
54 | 'sp-core/std',
55 | 'frame-support/std',
56 | 'frame-system/std',
57 | 'pallet-price-feed/std',
58 | 'primitives/std',
59 |
60 | 'polkadot-parachain/std',
61 | 'xcm/std',
62 | 'xcm-executor/std',
63 |
64 | 'orml-traits/std',
65 | ]
66 | runtime-benchmarks = [
67 | 'frame-benchmarking',
68 | 'frame-support/runtime-benchmarks',
69 | 'pallet-price-feed/runtime-benchmarks',
70 | # 'pallet-chainlink-feed/runtime-benchmarks',
71 | 'primitives/runtime-benchmarks',
72 | ]
73 |
74 | [package.metadata.docs.rs]
75 | targets = ['x86_64-unknown-linux-gnu']
76 |
--------------------------------------------------------------------------------
/pallets/asset-index/README.md:
--------------------------------------------------------------------------------
1 | License: LGPL-3.0-only
--------------------------------------------------------------------------------
/pallets/asset-index/rpc/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ['ChainSafe Systems']
3 | description = 'RPC for the asset-index pallet.'
4 | edition = '2018'
5 | license = 'LGPL-3.0-only'
6 | name = 'pallet-asset-index-rpc'
7 | readme = 'README.md'
8 | repository = 'https://github.com/ChainSafe/PINT/'
9 | version = '0.0.1'
10 |
11 | [dependencies]
12 | serde = { version = "1.0.130", features = ["derive"] }
13 | codec = { package = "parity-scale-codec", version = "2.3.1" }
14 | jsonrpc-core = "18.0.0"
15 | jsonrpc-core-client = "18.0.0"
16 | jsonrpc-derive = "18.0.0"
17 | sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" }
18 | sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" }
19 | sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" }
20 |
21 | # PINT RPC
22 | pallet-asset-index-rpc-runtime-api = { path = "runtime-api" }
23 |
24 | # PINT dependencies
25 | primitives = { path = "../../../primitives/primitives", default-features = false }
26 |
27 | [dev-dependencies]
28 | serde_json = "1.0.69"
29 |
30 | [package.metadata.docs.rs]
31 | targets = ['x86_64-unknown-linux-gnu']
32 |
--------------------------------------------------------------------------------
/pallets/asset-index/rpc/runtime-api/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ['ChainSafe Systems']
3 | description = 'RPC runtime API for the asset-index pallet.'
4 | edition = '2018'
5 | license = 'LGPL-3.0-only'
6 | name = 'pallet-asset-index-rpc-runtime-api'
7 | readme = 'README.md'
8 | repository = 'https://github.com/ChainSafe/PINT/'
9 | version = '0.0.1'
10 |
11 | [dependencies]
12 | serde = { version = "1.0.130", optional = true, features = ["derive"] }
13 | codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false }
14 | scale-info = { version = "1.0", default-features = false, features = ["derive"] }
15 | sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false }
16 | sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false }
17 | sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13", default-features = false }
18 |
19 | # PINT dependencies
20 | primitives = { path = "../../../../primitives/primitives", default-features = false }
21 |
22 | [features]
23 | default = ["std"]
24 | std = [
25 | "serde",
26 | "codec/std",
27 | "sp-api/std",
28 | "sp-runtime/std",
29 | "sp-std/std",
30 | "primitives/std",
31 | ]
32 |
33 | [package.metadata.docs.rs]
34 | targets = ['x86_64-unknown-linux-gnu']
35 |
--------------------------------------------------------------------------------
/pallets/asset-index/rpc/runtime-api/src/lib.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | //! Runtime API definition for the asset-index pallet.
5 |
6 | #![cfg_attr(not(feature = "std"), no_std)]
7 | // The `too_many_arguments` warning originates from `decl_runtime_apis` macro.
8 | #![allow(clippy::too_many_arguments)]
9 | #![allow(clippy::unnecessary_mut_passed)]
10 |
11 | use codec::Codec;
12 | use sp_std::prelude::*;
13 |
14 | use primitives::Ratio;
15 |
16 | sp_api::decl_runtime_apis! {
17 | pub trait AssetIndexApi where
18 | AccountId: Codec,
19 | AssetId: Codec,
20 | Balance: Codec,
21 | {
22 | fn get_nav() -> Ratio;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pallets/asset-index/rpc/src/lib.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | //! RPC interface for the asset-index pallet.
5 |
6 | use codec::Codec;
7 | use jsonrpc_core::{Error as RpcError, ErrorCode, Result};
8 | use jsonrpc_derive::rpc;
9 | use primitives::Ratio;
10 | use sp_api::ProvideRuntimeApi;
11 | use sp_blockchain::HeaderBackend;
12 | use sp_runtime::{generic::BlockId, traits::Block as BlockT};
13 | use std::sync::Arc;
14 |
15 | pub use self::gen_client::Client as AssetIndexClient;
16 | pub use pallet_asset_index_rpc_runtime_api::AssetIndexApi as AssetIndexRuntimeApi;
17 |
18 | /// Asset index state API
19 | #[rpc]
20 | pub trait AssetIndexApi {
21 | #[rpc(name = "assetIndex_getNav")]
22 | fn get_nav(&self, at: Option) -> Result;
23 | }
24 |
25 | /// A struct that implements the [`AssetIndexApi`].
26 | pub struct AssetIndexBackend {
27 | client: Arc,
28 | _marker: std::marker::PhantomData,
29 | }
30 |
31 | impl AssetIndexBackend {
32 | /// Create new `AssetIndex` with the given reference to the client.
33 | pub fn new(client: Arc) -> Self {
34 | AssetIndexBackend { client, _marker: Default::default() }
35 | }
36 | }
37 |
38 | pub enum Error {
39 | RuntimeError,
40 | }
41 |
42 | impl From for i64 {
43 | fn from(e: Error) -> i64 {
44 | match e {
45 | Error::RuntimeError => 1,
46 | }
47 | }
48 | }
49 |
50 | impl AssetIndexApi<::Hash, AccountId, AssetId, Balance>
51 | for AssetIndexBackend
52 | where
53 | Block: BlockT,
54 | C: Send + Sync + 'static + ProvideRuntimeApi + HeaderBackend,
55 | C::Api: AssetIndexRuntimeApi,
56 | AccountId: Codec,
57 | AssetId: Codec,
58 | Balance: Codec,
59 | {
60 | fn get_nav(&self, at: Option<::Hash>) -> Result {
61 | let api = self.client.runtime_api();
62 | let at = BlockId::hash(at.unwrap_or(
63 | // If the block hash is not supplied assume the best block.
64 | self.client.info().best_hash,
65 | ));
66 | api.get_nav(&at).map_err(|e| RpcError {
67 | code: ErrorCode::ServerError(Error::RuntimeError.into()),
68 | message: "Unable to get current NAV.".into(),
69 | data: Some(format!("{:?}", e).into()),
70 | })
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/pallets/asset-index/src/traits.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | /// A type to abstract the range of lockup period
5 | pub trait LockupPeriodRange {
6 | /// The minimum value of the lockup period range
7 | fn min() -> BlockNumber;
8 |
9 | /// The maximum value of the lockup period range
10 | fn max() -> BlockNumber;
11 | }
12 |
--------------------------------------------------------------------------------
/pallets/asset-index/src/types.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | use codec::{Decode, Encode};
5 | use frame_support::{
6 | sp_runtime::{
7 | traits::{AtLeast32BitUnsigned, Zero},
8 | RuntimeDebug,
9 | },
10 | sp_std::vec::Vec,
11 | };
12 |
13 | /// Abstraction over the lock of minted index token that are locked up for
14 | /// `LockupPeriod`
15 | #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)]
16 | pub struct IndexTokenLock {
17 | /// Locked amount of index token.
18 | pub locked: Balance,
19 | /// The block when the locked index token can be unlocked.
20 | pub end_block: BlockNumber,
21 | }
22 |
23 | /// Metadata for an asset
24 | #[derive(PartialEq, Eq, Clone, Default, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)]
25 | pub struct AssetMetadata {
26 | pub name: BoundedString,
27 | pub symbol: BoundedString,
28 | pub decimals: u8,
29 | }
30 |
31 | /// Represents a single asset being withdrawn
32 | #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)]
33 | pub struct AssetWithdrawal {
34 | /// The identifier of the asset
35 | pub asset: AssetId,
36 | /// The amount of asset units about to be transferred to the LP.
37 | pub units: Balance,
38 | /// The amount still reserved for this withdrawal.
39 | pub reserved: Balance,
40 | /// Whether this withdrawal was already been closed.
41 | pub withdrawn: bool,
42 | }
43 |
44 | #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)]
45 | /// Describes an in progress withdrawal of a collection of assets from the index
46 | pub struct PendingRedemption {
47 | /// The block after which the redemption process is over.
48 | pub end_block: BlockNumber,
49 | /// All the withdrawals resulted from the redemption.
50 | pub assets: Vec>,
51 | }
52 |
53 | /// Represents the redemption of a given pint amount based on the
54 | /// `AssetDistribution`.
55 | #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)]
56 | pub struct AssetRedemption {
57 | /// All the assets together with their redeemed amount
58 | pub asset_amounts: Vec<(AssetId, Balance)>,
59 | /// The total amount of redeemed pint
60 | pub redeemed_index_tokens: Balance,
61 | }
62 |
63 | impl Default for AssetRedemption {
64 | fn default() -> Self {
65 | Self { asset_amounts: Vec::new(), redeemed_index_tokens: Balance::zero() }
66 | }
67 | }
68 |
69 | /// Limits the amount of deposits
70 | #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)]
71 | #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
72 | pub struct DepositRange {
73 | /// Minimum amount of index tokens a deposit must be worth
74 | pub minimum: Balance,
75 | /// Maximum amount of index tokens a deposit must be worth
76 | pub maximum: Balance,
77 | }
78 |
79 | // Default implementation for bounds [0, MAX]
80 | impl Default for DepositRange {
81 | fn default() -> Self {
82 | Self { minimum: Balance::one(), maximum: Balance::max_value() }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/pallets/committee/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ['ChainSafe Systems']
3 | description = 'FRAME pallet to implement PINT committee.'
4 | edition = '2018'
5 | license = 'LGPL-3.0-only'
6 | name = 'pallet-committee'
7 | readme = 'README.md'
8 | repository = 'https://github.com/ChainSafe/PINT/'
9 | version = '0.0.1'
10 |
11 | [dependencies]
12 | log = { version = "0.4.14", default-features = false }
13 | codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false }
14 | scale-info = { version = "1.0", default-features = false, features = ["derive"] }
15 |
16 | # Substrate Dependencies
17 | frame-support = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
18 | frame-system = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
19 | frame-benchmarking = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false, optional = true }
20 |
21 | [dev-dependencies]
22 | sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" }
23 | sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" }
24 | sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" }
25 | frame-benchmarking = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
26 |
27 | [features]
28 | default = ['std']
29 | std = [
30 | 'log/std',
31 | 'codec/std',
32 | 'frame-support/std',
33 | 'frame-system/std',
34 | ]
35 | runtime-benchmarks = [
36 | 'frame-benchmarking',
37 | 'frame-support/runtime-benchmarks',
38 | 'frame-system/runtime-benchmarks',
39 | ]
40 |
41 | [package.metadata.docs.rs]
42 | targets = ['x86_64-unknown-linux-gnu']
43 |
--------------------------------------------------------------------------------
/pallets/committee/README.md:
--------------------------------------------------------------------------------
1 | License: LGPL-3.0-only
2 |
--------------------------------------------------------------------------------
/pallets/committee/src/benchmarking.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 | use super::*;
4 | use frame_benchmarking::{account, benchmarks, vec, Box};
5 | use frame_support::{
6 | assert_noop, assert_ok,
7 | traits::{EnsureOrigin, Get, Hooks, UnfilteredDispatchable},
8 | };
9 | use frame_system::{ensure_signed, Call as SystemCall, Pallet as System, RawOrigin as SystemOrigin};
10 |
11 | fn submit_proposal(origin: ::Origin) -> pallet::Proposal {
12 | let action: T::Action = SystemCall::::remark { remark: vec![0; 0] }.into();
13 | let expected_nonce = pallet::ProposalCount::::get();
14 |
15 | let account_id = ensure_signed(origin.clone()).unwrap();
16 | assert_ok!(>::add_constituent(SystemOrigin::Root.into(), account_id.clone()));
17 | >::set_block_number(
18 | >::block_number() +
19 | ::VotingPeriod::get() +
20 | ::ProposalSubmissionPeriod::get() +
21 | 1_u32.into(),
22 | );
23 |
24 | let call = Call::::propose { action: Box::new(action.clone()) };
25 | assert_ok!(call.dispatch_bypass_filter(origin));
26 |
27 | pallet::Proposal::::new(action, account_id, expected_nonce, ProposalStatus::Active)
28 | }
29 |
30 | fn run_to_block(n: T::BlockNumber) {
31 | while System::::block_number() < n {
32 | System::::set_block_number(System::::block_number() + 1u32.into());
33 | Pallet::::on_initialize(System::::block_number());
34 | }
35 | }
36 |
37 | benchmarks! {
38 | propose {
39 | let origin = T::ProposalSubmissionOrigin::successful_origin();
40 | let proposal = submit_proposal::(origin.clone());
41 | let call = Call::::propose{action: Box::new(SystemCall::::remark{remark:vec![0; 0]}.into())};
42 | }: {
43 | call.dispatch_bypass_filter(origin)?
44 | } verify {
45 | assert!(>::get_proposal(&proposal.hash()) == Some(proposal));
46 | }
47 |
48 | vote {
49 | let origin = T::ProposalSubmissionOrigin::successful_origin();
50 | let proposal = submit_proposal::(origin.clone());
51 |
52 | // run to voting period
53 | >::set_block_number(
54 | >::block_number()
55 | + ::VotingPeriod::get()
56 | + ::ProposalSubmissionPeriod::get() + 1_u32.into(),
57 | );
58 |
59 | // construct call
60 | let call = Call::::vote{ proposal_hash: proposal.hash(), vote: VoteKind::Abstain};
61 | }: {
62 | call.dispatch_bypass_filter(origin)?
63 | } verify {
64 | assert_eq!(
65 | >::get_votes_for(&proposal.hash()).unwrap().votes.len(),
66 | 1,
67 | );
68 | }
69 |
70 | close {
71 | let proposal: pallet::Proposal = submit_proposal::(T::ProposalSubmissionOrigin::successful_origin());
72 |
73 | // vote
74 | for i in 0..5 {
75 | let voter: T::AccountId = account("voter", i, 0);
76 | assert_ok!(Votes::::try_mutate(&proposal.hash(), |votes| {
77 | if let Some(votes) = votes {
78 | votes.cast_vote(
79 | MemberVote::new(CommitteeMember::new(voter, MemberType::Council), VoteKind::Aye),
80 | );
81 | Ok(())
82 | } else {
83 | Err(Error::::NoProposalWithHash)
84 | }
85 | }));
86 | }
87 |
88 | // run out of voting period
89 | >::set_block_number(
90 | >::block_number()
91 | + ::VotingPeriod::get() * 2_u32.into()
92 | + ::ProposalSubmissionPeriod::get()
93 | + 1_u32.into()
94 | );
95 |
96 | // construct call
97 | let call = Call::::close{proposal_hash: proposal.hash()};
98 | }: {
99 | call.dispatch_bypass_filter(T::ProposalExecutionOrigin::successful_origin())?
100 | } verify {
101 | assert_noop!(
102 | >::close(T::ProposalExecutionOrigin::successful_origin(), proposal.hash()),
103 | >::ProposalAlreadyExecuted
104 | );
105 | }
106 |
107 | add_constituent {
108 | let constituent: T::AccountId = account("constituent", 0, 0);
109 | }: _(
110 | SystemOrigin::Root,
111 | constituent.clone()
112 | ) verify {
113 | assert!(>::contains_key(constituent));
114 | }
115 |
116 | remove_member {
117 | let constituent: T::AccountId = account("constituent", 0, 0);
118 | assert_ok!(>::add_constituent(SystemOrigin::Root.into(), constituent.clone()));
119 | }: _(
120 | SystemOrigin::Root,
121 | constituent.clone()
122 | ) verify {
123 | assert!(!>::contains_key(constituent));
124 | }
125 |
126 | set_voting_period {
127 | let two_weeks: T::BlockNumber = (10u32 * 60 * 24 * 7 * 2).into();
128 | }: _(
129 | SystemOrigin::Root,
130 | two_weeks
131 | ) verify {
132 | run_to_block::(::VotingPeriod::get());
133 | assert_eq!(pallet::VotingPeriod::::get(), two_weeks);
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/pallets/committee/src/traits.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | /// A type to abstract the range of voting period
5 | pub trait VotingPeriodRange {
6 | /// The minimum value of the voting period range
7 | fn min() -> BlockNumber;
8 |
9 | /// The maximum value of the voting period range
10 | fn max() -> BlockNumber;
11 | }
12 |
--------------------------------------------------------------------------------
/pallets/committee/src/utils.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | use frame_support::sp_runtime::traits::{CheckedAdd, CheckedDiv, CheckedMul, One};
5 |
6 | // Proposal submissions and voting follow set cycles e.g.
7 | //
8 | // ---v0--||-----s1----|--v1--||-----s2----|--v2--|...
9 | //
10 | // Proposals submitted in s1 are voted upon in v1 and after that
11 | // they may or may not be executed and then are dropped from the ActiveProposals
12 | // set.
13 | //
14 | // Proposals submitted during v0 fall into the next submission period and
15 | // should be voted on in v1. To simplify implementation we assume the cycle
16 | // begins with an initial dummy voting period.
17 | //
18 | // Will return an None if any of the arithmetic operations fail due to
19 | // overflow/underflow
20 | //
21 | pub fn get_vote_end(
22 | current_block: &T,
23 | voting_period: &T,
24 | proposal_period: &T,
25 | ) -> Option {
26 | let epoch_period = voting_period.checked_add(proposal_period)?;
27 |
28 | // [(current_block // period) + 1] * period + voting_period
29 | // return the block at the end of the next voting period after the current one
30 | current_block
31 | .checked_div(&epoch_period)?
32 | .checked_add(&T::one())?
33 | .checked_mul(&epoch_period)?
34 | .checked_add(voting_period)
35 | }
36 |
37 | #[cfg(test)]
38 | mod tests {
39 | use super::*;
40 | use std::iter;
41 |
42 | const VOTE_P: i32 = 2;
43 | const PROPOSAL_P: i32 = 3;
44 |
45 | #[test]
46 | // A proposal made during the start dummpy period must have votes submitted
47 | // before the end of v1
48 | fn test_proposal_in_v0() {
49 | assert_eq!(get_vote_end(&0, &VOTE_P, &PROPOSAL_P), Some(VOTE_P + PROPOSAL_P + VOTE_P))
50 | }
51 |
52 | #[test]
53 | // A proposal made during s1 must have votes submitted before
54 | // the end of v1
55 | fn test_proposal_in_s1() {
56 | assert_eq!(get_vote_end(&4, &VOTE_P, &PROPOSAL_P), Some(VOTE_P + PROPOSAL_P + VOTE_P))
57 | }
58 |
59 | #[test]
60 | // A proposal made during v1 must have votes submitted before
61 | // the end of v2
62 | fn test_proposal_in_v1() {
63 | assert_eq!(get_vote_end(&9, &VOTE_P, &PROPOSAL_P), Some(VOTE_P + 2 * (PROPOSAL_P + VOTE_P)))
64 | }
65 |
66 | #[test]
67 | // Check a range of blocks are as expected
68 | fn test_proposal_range() {
69 | let result: Vec = (0..15).map(|i| get_vote_end(&i, &VOTE_P, &PROPOSAL_P).unwrap()).collect();
70 |
71 | let expected: Vec = iter::empty()
72 | .chain(iter::repeat(VOTE_P + PROPOSAL_P + VOTE_P).take(5))
73 | .chain(iter::repeat(VOTE_P + 2 * (PROPOSAL_P + VOTE_P)).take(5))
74 | .chain(iter::repeat(VOTE_P + 3 * (PROPOSAL_P + VOTE_P)).take(5))
75 | .collect();
76 |
77 | assert_eq!(result, expected)
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/pallets/local-treasury/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ['ChainSafe Systems']
3 | description = 'FRAME pallet to implement PINT local treasury.'
4 | edition = '2018'
5 | license = 'LGPL-3.0-only'
6 | name = 'pallet-local-treasury'
7 | readme = 'README.md'
8 | repository = 'https://github.com/ChainSafe/PINT/'
9 | version = '0.0.1'
10 |
11 | [dependencies]
12 | codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false }
13 | scale-info = { version = "1.0", default-features = false, features = ["derive"] }
14 |
15 | # Substrate Dependencies
16 | frame-support = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
17 | frame-system = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
18 | frame-benchmarking = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false, optional = true }
19 |
20 | [dev-dependencies]
21 | serde = "1.0.130"
22 | sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" }
23 | sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" }
24 | sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" }
25 | frame-system = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
26 | frame-benchmarking = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
27 | sp-runtime = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
28 |
29 | pallet-balances = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
30 |
31 | [features]
32 | default = ['std']
33 | std = [
34 | 'codec/std',
35 | 'frame-support/std',
36 | 'frame-system/std',
37 | ]
38 | runtime-benchmarks = [
39 | 'frame-benchmarking',
40 | 'frame-system/runtime-benchmarks',
41 | 'frame-support/runtime-benchmarks',
42 | ]
43 |
44 | [package.metadata.docs.rs]
45 | targets = ['x86_64-unknown-linux-gnu']
46 |
--------------------------------------------------------------------------------
/pallets/local-treasury/README.md:
--------------------------------------------------------------------------------
1 | License: LGPL-3.0-only
--------------------------------------------------------------------------------
/pallets/local-treasury/src/benchmarking.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 | use super::*;
4 | use frame_benchmarking::{account, benchmarks};
5 | use frame_support::{sp_runtime::traits::AccountIdConversion, traits::Currency, PalletId};
6 | use frame_system::Origin;
7 |
8 | benchmarks! {
9 | withdraw {
10 | let local_treasury: ::AccountId = PalletId(*b"Treasury").into_account();
11 | T::Currency::deposit_creating(&local_treasury, 10_000_000_u32.into());
12 | let admin: ::AccountId = account("admin", 0, 0);
13 | }: _(
14 | >::Root,
15 | 5_000_000_u32.into(),
16 | admin.clone()
17 | ) verify {
18 | assert_eq!(
19 | T::Currency::free_balance(&admin),
20 | 5_000_000_u32.into(),
21 | );
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/pallets/local-treasury/src/lib.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | //! # Local Treasury Pallet
5 | //!
6 | //! Manages PINT exclusively. The treasury is a single account which is derived from the configured
7 | //! `PalletId`. It maintains ownership of various assets and is controlled by the Governance
8 | //! Committee. Deposits to the Treasury can be done by simply transferring funds to its AccountId.
9 | //! The committee can execute proposals to withdraw funds from the Treasury.
10 |
11 | #![cfg_attr(not(feature = "std"), no_std)]
12 |
13 | pub use pallet::*;
14 |
15 | #[cfg(test)]
16 | mod mock;
17 |
18 | #[cfg(feature = "runtime-benchmarks")]
19 | mod benchmarking;
20 | #[cfg(test)]
21 | mod tests;
22 |
23 | // this is requires as the #[pallet::event] proc macro generates code that violates this lint
24 | #[allow(clippy::unused_unit)]
25 | #[frame_support::pallet]
26 | pub mod pallet {
27 | use frame_support::{
28 | dispatch::DispatchResult,
29 | pallet_prelude::*,
30 | sp_runtime::traits::AccountIdConversion,
31 | traits::{Currency, ExistenceRequirement::AllowDeath, Get},
32 | PalletId,
33 | };
34 | use frame_system::pallet_prelude::*;
35 |
36 | type AccountIdFor = ::AccountId;
37 | type BalanceFor = <::Currency as Currency>>::Balance;
38 |
39 | #[pallet::config]
40 | pub trait Config: frame_system::Config {
41 | /// Origin that is allowed to manage the treasury balance and initiate
42 | /// withdrawals
43 | type AdminOrigin: EnsureOrigin;
44 | /// PalletId used to generate the `AccountId` which holds the balance of the
45 | /// treasury.
46 | #[pallet::constant]
47 | type PalletId: Get;
48 | /// The pallet to use as the base currency for this treasury
49 | type Currency: Currency;
50 | type Event: From> + IsType<::Event>;
51 |
52 | /// The weight for this pallet's extrinsics.
53 | type WeightInfo: WeightInfo;
54 | }
55 |
56 | #[pallet::pallet]
57 | #[pallet::generate_store(pub(super) trait Store)]
58 | pub struct Pallet(_);
59 |
60 | #[pallet::event]
61 | #[pallet::generate_deposit(pub(super) fn deposit_event)]
62 | pub enum Event {
63 | /// Admin successfully transferred some funds from the treasury to
64 | /// another account parameters. \[recipient, amount\]
65 | Withdrawn(AccountIdFor, BalanceFor),
66 | }
67 |
68 | #[pallet::hooks]
69 | impl Hooks> for Pallet {}
70 |
71 | #[pallet::extra_constants]
72 | impl Pallet {
73 | /// Returns the `AccountId` of the treasury account.
74 | pub fn treasury_account() -> T::AccountId {
75 | T::PalletId::get().into_account()
76 | }
77 | }
78 |
79 | #[pallet::call]
80 | impl Pallet {
81 | /// Transfer balance from the treasury to another account.
82 | ///
83 | /// Only callable by the AdminOrigin.
84 | #[pallet::weight(T::WeightInfo::withdraw())]
85 | pub fn withdraw(origin: OriginFor, amount: BalanceFor, recipient: AccountIdFor) -> DispatchResult {
86 | T::AdminOrigin::ensure_origin(origin)?;
87 |
88 | T::Currency::transfer(&Self::treasury_account(), &recipient, amount, AllowDeath)?;
89 |
90 | Self::deposit_event(Event::Withdrawn(recipient, amount));
91 |
92 | Ok(())
93 | }
94 | }
95 |
96 | /// Trait for the treasury pallet extrinsic weights.
97 | pub trait WeightInfo {
98 | fn withdraw() -> Weight;
99 | }
100 |
101 | /// For backwards compatibility and tests
102 | impl WeightInfo for () {
103 | fn withdraw() -> Weight {
104 | Default::default()
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/pallets/local-treasury/src/mock.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | // Required as construct_runtime! produces code that violates this lint
5 | #![allow(clippy::from_over_into)]
6 |
7 | use crate as pallet_local_treasury;
8 | use frame_support::{ord_parameter_types, parameter_types, traits::StorageMapShim, PalletId};
9 | use frame_system as system;
10 |
11 | use frame_support::traits::Everything;
12 | use sp_core::H256;
13 | use sp_runtime::{
14 | testing::Header,
15 | traits::{AccountIdConversion, BlakeTwo256, IdentityLookup},
16 | };
17 |
18 | type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic;
19 | type Block = frame_system::mocking::MockBlock;
20 |
21 | // Configure a mock runtime to test the pallet.
22 | frame_support::construct_runtime!(
23 | pub enum Test where
24 | Block = Block,
25 | NodeBlock = Block,
26 | UncheckedExtrinsic = UncheckedExtrinsic,
27 | {
28 | System: frame_system::{Pallet, Call, Config, Storage, Event},
29 | Balances: pallet_balances::{Pallet, Call, Storage, Config, Event},
30 | LocalTreasury: pallet_local_treasury::{Pallet, Call, Storage, Event},
31 | }
32 | );
33 |
34 | parameter_types! {
35 | pub const BlockHashCount: u64 = 250;
36 | pub const SS58Prefix: u8 = 42;
37 | }
38 |
39 | pub(crate) type Balance = u64;
40 | pub(crate) type AccountId = u64;
41 |
42 | impl system::Config for Test {
43 | type BaseCallFilter = Everything;
44 | type BlockWeights = ();
45 | type BlockLength = ();
46 | type DbWeight = ();
47 | type Origin = Origin;
48 | type Call = Call;
49 | type Index = u64;
50 | type BlockNumber = u64;
51 | type Hash = H256;
52 | type Hashing = BlakeTwo256;
53 | type AccountId = AccountId;
54 | type Lookup = IdentityLookup;
55 | type Header = Header;
56 | type Event = Event;
57 | type BlockHashCount = BlockHashCount;
58 | type Version = ();
59 | type PalletInfo = PalletInfo;
60 | type AccountData = ();
61 | type OnNewAccount = ();
62 | type OnKilledAccount = ();
63 | type SystemWeightInfo = ();
64 | type SS58Prefix = SS58Prefix;
65 | type OnSetCode = ();
66 | }
67 |
68 | // param types for balances
69 | parameter_types! {
70 | pub const MaxLocks: u32 = 1024;
71 | pub static ExistentialDeposit: Balance = 0;
72 | }
73 |
74 | impl pallet_balances::Config for Test {
75 | type Balance = Balance;
76 | type DustRemoval = ();
77 | type Event = Event;
78 | type ExistentialDeposit = ExistentialDeposit;
79 | type AccountStore = StorageMapShim<
80 | pallet_balances::Account,
81 | system::Provider,
82 | Balance,
83 | pallet_balances::AccountData,
84 | >;
85 | type MaxLocks = MaxLocks;
86 | type MaxReserves = ();
87 | type ReserveIdentifier = [u8; 8];
88 | type WeightInfo = ();
89 | }
90 |
91 | pub(crate) const LOCAL_TREASURE_PALLET_ID: PalletId = PalletId(*b"12345678");
92 | pub(crate) const ADMIN_ACCOUNT_ID: AccountId = 88;
93 |
94 | parameter_types! {
95 | pub const TestPalletId: PalletId = LOCAL_TREASURE_PALLET_ID;
96 | }
97 | ord_parameter_types! {
98 | pub const AdminAccountId: AccountId = ADMIN_ACCOUNT_ID;
99 | }
100 |
101 | impl pallet_local_treasury::Config for Test {
102 | type AdminOrigin = frame_system::EnsureSignedBy;
103 | type PalletId = TestPalletId;
104 | type Currency = Balances;
105 | type Event = Event;
106 | type WeightInfo = ();
107 | }
108 |
109 | pub fn local_treasury_account_id() -> AccountId {
110 | LOCAL_TREASURE_PALLET_ID.into_account()
111 | }
112 |
113 | // Build genesis storage according to the mock runtime.
114 | pub fn new_test_ext(balances: Vec<(AccountId, Balance)>) -> sp_io::TestExternalities {
115 | let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap();
116 | pallet_balances::GenesisConfig:: {
117 | // Assign initial balances to accounts
118 | balances,
119 | }
120 | .assimilate_storage(&mut t)
121 | .unwrap();
122 | t.into()
123 | }
124 |
--------------------------------------------------------------------------------
/pallets/local-treasury/src/tests.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | use crate::mock::*;
5 | use frame_support::{assert_noop, assert_ok};
6 | use pallet_balances::Error as BalancesError;
7 | use sp_runtime::traits::BadOrigin;
8 |
9 | const ASHLEY: AccountId = 0;
10 |
11 | fn assert_balances(balances: &[(AccountId, Balance)]) {
12 | for (account, balance) in balances {
13 | assert_eq!(&Balances::free_balance(account), balance)
14 | }
15 | }
16 |
17 | #[test]
18 | fn unprivileged_account_can_deposit() {
19 | const INITIAL_BALANCE: Balance = 100;
20 | const AMOUNT: Balance = 10;
21 |
22 | let initial_balances: Vec<(u64, u64)> = vec![(local_treasury_account_id(), 0), (ASHLEY, INITIAL_BALANCE)];
23 |
24 | let final_balances: Vec<(u64, u64)> =
25 | vec![(local_treasury_account_id(), AMOUNT), (ASHLEY, INITIAL_BALANCE - AMOUNT)];
26 |
27 | new_test_ext(initial_balances).execute_with(|| {
28 | assert_ok!(Balances::transfer(Origin::signed(ASHLEY), local_treasury_account_id(), AMOUNT));
29 | assert_balances(&final_balances);
30 | });
31 | }
32 |
33 | #[test]
34 | fn unprivileged_account_cannot_withdraw() {
35 | const INITIAL_BALANCE: Balance = 100;
36 | const AMOUNT: Balance = 10;
37 |
38 | let initial_balances: Vec<(u64, u64)> = vec![(local_treasury_account_id(), 0), (ASHLEY, INITIAL_BALANCE)];
39 |
40 | new_test_ext(initial_balances.clone()).execute_with(|| {
41 | assert_noop!(LocalTreasury::withdraw(Origin::signed(ASHLEY), AMOUNT, ASHLEY), BadOrigin);
42 | assert_balances(&initial_balances);
43 | });
44 | }
45 |
46 | #[test]
47 | fn admin_account_can_withdraw() {
48 | const INITIAL_BALANCE: Balance = 100;
49 | const AMOUNT: Balance = 1;
50 |
51 | let initial_balances: Vec<(u64, u64)> = vec![(local_treasury_account_id(), INITIAL_BALANCE), (ADMIN_ACCOUNT_ID, 0)];
52 |
53 | let final_balances: Vec<(u64, u64)> =
54 | vec![(local_treasury_account_id(), INITIAL_BALANCE - AMOUNT), (ADMIN_ACCOUNT_ID, AMOUNT)];
55 |
56 | new_test_ext(initial_balances).execute_with(|| {
57 | assert_ok!(LocalTreasury::withdraw(Origin::signed(ADMIN_ACCOUNT_ID), AMOUNT, ADMIN_ACCOUNT_ID));
58 | assert_balances(&final_balances);
59 | });
60 | }
61 |
62 | #[test]
63 | fn admin_account_can_withdraw_to_zero() {
64 | const INITIAL_BALANCE: Balance = 100;
65 | const AMOUNT: Balance = 100;
66 |
67 | let initial_balances: Vec<(u64, u64)> = vec![(local_treasury_account_id(), INITIAL_BALANCE), (ADMIN_ACCOUNT_ID, 0)];
68 |
69 | let final_balances: Vec<(u64, u64)> = vec![(local_treasury_account_id(), 0), (ADMIN_ACCOUNT_ID, AMOUNT)];
70 |
71 | new_test_ext(initial_balances).execute_with(|| {
72 | assert_ok!(LocalTreasury::withdraw(Origin::signed(ADMIN_ACCOUNT_ID), AMOUNT, ADMIN_ACCOUNT_ID));
73 | assert_balances(&final_balances);
74 | });
75 | }
76 |
77 | #[test]
78 | fn admin_account_overdraw_fails() {
79 | const INITIAL_BALANCE: Balance = 100;
80 | const AMOUNT: Balance = 101;
81 |
82 | let initial_balances: Vec<(u64, u64)> = vec![(local_treasury_account_id(), INITIAL_BALANCE), (ADMIN_ACCOUNT_ID, 0)];
83 |
84 | new_test_ext(initial_balances.clone()).execute_with(|| {
85 | assert_noop!(
86 | LocalTreasury::withdraw(Origin::signed(ADMIN_ACCOUNT_ID), AMOUNT, ADMIN_ACCOUNT_ID),
87 | BalancesError::::InsufficientBalance
88 | );
89 | assert_balances(&initial_balances);
90 | });
91 | }
92 |
--------------------------------------------------------------------------------
/pallets/price-feed/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ['ChainSafe Systems']
3 | description = 'FRAME pallet to implement PINT price feeds.'
4 | edition = '2018'
5 | license = 'LGPL-3.0-only'
6 | name = 'pallet-price-feed'
7 | readme = 'README.md'
8 | repository = 'https://github.com/ChainSafe/PINT/'
9 | version = '0.0.1'
10 |
11 | [dependencies]
12 | serde = { version = "1.0.130", optional = true }
13 | codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false }
14 | scale-info = { version = "1.0", default-features = false, features = ["derive"] }
15 |
16 | # Substrate Dependencies
17 | frame-support = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
18 | frame-system = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
19 | frame-benchmarking = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false, optional = true }
20 |
21 | # PINT dependencies
22 | pallet-chainlink-feed = { git = 'https://github.com/smartcontractkit/chainlink-polkadot', branch = 'polkadot-v0.9.13', default-features = false }
23 | primitives = { path = "../../primitives/primitives", default-features = false }
24 |
25 | [dev-dependencies]
26 | serde = "1.0.130"
27 | sp-core = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
28 | sp-io = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
29 | sp-runtime = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
30 |
31 | pallet-balances = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
32 | pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = 'polkadot-v0.9.13' }
33 |
34 | [features]
35 | default = ['std']
36 | std = [
37 | 'serde',
38 | 'codec/std',
39 | 'frame-support/std',
40 | 'frame-system/std',
41 | 'pallet-chainlink-feed/std',
42 | 'primitives/std',
43 | ]
44 | runtime-benchmarks = [
45 | 'frame-benchmarking',
46 | 'frame-support/runtime-benchmarks',
47 | 'pallet-chainlink-feed/runtime-benchmarks',
48 | 'primitives/runtime-benchmarks',
49 | ]
50 |
51 | [package.metadata.docs.rs]
52 | targets = ['x86_64-unknown-linux-gnu']
53 |
--------------------------------------------------------------------------------
/pallets/price-feed/README.md:
--------------------------------------------------------------------------------
1 | License: LGPL-3.0-only
--------------------------------------------------------------------------------
/pallets/price-feed/src/benchmarking.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | #![cfg(feature = "runtime-benchmarks")]
5 |
6 | use super::*;
7 | use frame_benchmarking::benchmarks;
8 | use frame_support::{assert_ok, dispatch::UnfilteredDispatchable, sp_std::convert::TryInto, traits::EnsureOrigin};
9 |
10 | use crate::Pallet as PriceFeed;
11 |
12 | benchmarks! {
13 | map_asset_price_feed {
14 | let asset_id :T::AssetId = T::try_convert(2u8).unwrap();
15 | let origin = T::AdminOrigin::successful_origin();
16 | let feed_id = 0u32.try_into().ok().unwrap();
17 | let call = Call::::map_asset_price_feed {
18 | asset_id: asset_id.clone(),
19 | feed_id: feed_id
20 | };
21 | }: { call.dispatch_bypass_filter(origin)? } verify {
22 | assert_eq!(
23 | PriceFeed::::asset_feed(asset_id),
24 | Some(feed_id)
25 | );
26 | }
27 |
28 | unmap_asset_price_feed {
29 | let asset_id :T::AssetId = T::try_convert(2u8).unwrap();
30 | let origin = T::AdminOrigin::successful_origin();
31 | let feed_id = 0u32.try_into().ok().unwrap();
32 | assert_ok!(PriceFeed::::map_asset_price_feed(origin.clone(), asset_id.clone(), feed_id));
33 | let call = Call::::unmap_asset_price_feed {
34 | asset_id: asset_id.clone(),
35 | };
36 | }: { call.dispatch_bypass_filter(origin)? } verify {
37 | assert_eq!(
38 | PriceFeed::::asset_feed(asset_id),
39 | None
40 | );
41 | }
42 | }
43 |
44 | #[cfg(test)]
45 | mod tests {
46 | use frame_support::assert_ok;
47 |
48 | use crate::mock::{new_test_ext, FeedBuilder, Test};
49 |
50 | use super::*;
51 |
52 | #[test]
53 | fn map_asset_price_feed() {
54 | new_test_ext().execute_with(|| {
55 | assert_ok!(FeedBuilder::new().description(b"X".to_vec()).build_and_store());
56 | assert_ok!(Pallet::::test_benchmark_map_asset_price_feed());
57 | });
58 | }
59 |
60 | #[test]
61 | fn unmap_asset_price_feed() {
62 | new_test_ext().execute_with(|| {
63 | assert_ok!(FeedBuilder::new().description(b"X".to_vec()).build_and_store());
64 | assert_ok!(Pallet::::test_benchmark_unmap_asset_price_feed());
65 | });
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/pallets/price-feed/src/tests.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | use crate as pallet;
5 | use crate::{mock::*, Error};
6 | use frame_support::{assert_noop, assert_ok};
7 | use pallet::PriceFeed as _;
8 | use primitives::Price;
9 | use sp_runtime::{traits::BadOrigin, FixedPointNumber};
10 |
11 | const ASSET_X_ID: AssetId = 2;
12 | const ASSET_Y_ID: AssetId = 3;
13 |
14 | #[test]
15 | fn feed_creation_and_mapping_should_work() {
16 | new_test_ext().execute_with(|| {
17 | // insert two feeds
18 | assert_ok!(FeedBuilder::new().description(b"X".to_vec()).build_and_store());
19 | assert_ok!(FeedBuilder::new().description(b"Y".to_vec()).build_and_store());
20 |
21 | // PINT asset id is not tracked yet
22 | assert_noop!(PriceFeed::get_price(ASSET_X_ID), Error::::AssetPriceFeedNotFound);
23 |
24 | // map feed 0 to PINT
25 | assert_ok!(PriceFeed::map_asset_price_feed(Origin::signed(ADMIN_ACCOUNT_ID), ASSET_X_ID, 0));
26 |
27 | // map feed 1 to assetId 2
28 | assert_ok!(PriceFeed::map_asset_price_feed(Origin::signed(ADMIN_ACCOUNT_ID), ASSET_Y_ID, 1));
29 |
30 | assert_ok!(PriceFeed::unmap_asset_price_feed(Origin::signed(ADMIN_ACCOUNT_ID), ASSET_Y_ID));
31 | });
32 | }
33 |
34 | #[test]
35 | fn non_admin_cannot_map_feeds() {
36 | new_test_ext().execute_with(|| {
37 | assert_ok!(FeedBuilder::new().description(b"PINT".to_vec()).build_and_store());
38 |
39 | assert_noop!(PriceFeed::map_asset_price_feed(Origin::signed(1), PINTAssetId::get(), 0), BadOrigin);
40 | })
41 | }
42 |
43 | #[test]
44 | fn cannot_get_price_pair_for_feed_without_valid_round() {
45 | new_test_ext().execute_with(|| {
46 | // insert two feeds
47 | assert_ok!(FeedBuilder::new().description(b"PINT".to_vec()).build_and_store());
48 | assert_ok!(FeedBuilder::new().description(b"X".to_vec()).build_and_store());
49 |
50 | assert_ok!(PriceFeed::map_asset_price_feed(Origin::signed(ADMIN_ACCOUNT_ID), PINTAssetId::get(), 0));
51 | assert_ok!(PriceFeed::map_asset_price_feed(Origin::signed(ADMIN_ACCOUNT_ID), ASSET_X_ID, 1));
52 | assert_noop!(PriceFeed::get_price(ASSET_X_ID), Error::::InvalidFeedValue);
53 | })
54 | }
55 |
56 | #[test]
57 | fn price_pair_should_be_available() {
58 | new_test_ext().execute_with(|| {
59 | // insert two feeds
60 | let decimals = 6;
61 | assert_ok!(FeedBuilder::new()
62 | .description(b"X".to_vec())
63 | .min_submissions(1)
64 | .decimals(decimals as u8)
65 | .value_bounds(0, 1_000_000_000_000)
66 | .build_and_store());
67 | assert_ok!(FeedBuilder::new().description(b"Y".to_vec()).min_submissions(1).decimals(0).build_and_store());
68 |
69 | assert_ok!(PriceFeed::map_asset_price_feed(Origin::signed(ADMIN_ACCOUNT_ID), ASSET_X_ID, 0));
70 | assert_ok!(PriceFeed::map_asset_price_feed(Origin::signed(ADMIN_ACCOUNT_ID), ASSET_Y_ID, 1));
71 |
72 | // insert round feed 1
73 | let feed_id = 0;
74 | let round_id = 1;
75 | let oracle = 2;
76 | let base_submission = 1_000_000_000;
77 | let precision = 10u128.pow(decimals);
78 | assert_ok!(ChainlinkFeed::submit(Origin::signed(oracle), feed_id, round_id, base_submission));
79 |
80 | // insert round feed 2
81 | let feed_id = 1;
82 | let round_id = 1;
83 | let oracle = 2;
84 | let quote_submission = 200;
85 | assert_ok!(ChainlinkFeed::submit(Origin::signed(oracle), feed_id, round_id, quote_submission));
86 |
87 | let base_price = PriceFeed::get_price(ASSET_X_ID).expect("price pair should be available");
88 | assert_eq!(base_price, Price::saturating_from_integer((base_submission as u128) / precision));
89 |
90 | let quote_price = PriceFeed::get_price(ASSET_Y_ID).expect("price pair should be available");
91 | assert_eq!(quote_price, Price::saturating_from_integer(quote_submission as u128));
92 |
93 | let pair = PriceFeed::get_relative_price_pair(ASSET_X_ID, ASSET_Y_ID).expect("relative price available");
94 |
95 | assert_eq!(
96 | pair.price,
97 | Price::saturating_from_rational((base_submission as u128) / precision, quote_submission)
98 | );
99 | })
100 | }
101 |
--------------------------------------------------------------------------------
/pallets/price-feed/src/traits.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | #[cfg(feature = "runtime-benchmarks")]
5 | use frame_support::dispatch::DispatchResultWithPostInfo;
6 |
7 | use frame_support::dispatch::DispatchError;
8 | use primitives::{AssetPricePair, Price};
9 |
10 | /// An interface to access price data
11 | pub trait PriceFeed {
12 | /// Returns the current price for the given asset measured in the constant denominating asset
13 | /// which is used as the quote currency, whereas the price of the `base` Asset will be the base
14 | /// currency for the price pair. *Note*: this returns the price for 1 basic unit
15 | fn get_price(base: AssetId) -> Result;
16 |
17 | /// Returns the current price pair for the prices of the base and quote asset in the form of
18 | /// `base/quote`
19 | fn get_relative_price_pair(base: AssetId, quote: AssetId) -> Result, DispatchError>;
20 | }
21 |
22 | #[cfg(feature = "runtime-benchmarks")]
23 | pub trait PriceFeedBenchmarks {
24 | fn create_feed(caller: AccountId, asset_id: AssetId) -> DispatchResultWithPostInfo;
25 | }
26 |
--------------------------------------------------------------------------------
/pallets/price-feed/src/types.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | use frame_support::pallet_prelude::*;
5 |
6 | /// Represents an answer of a feed at a certain point of time
7 | #[derive(PartialEq, Eq, Clone, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)]
8 | pub struct TimestampedValue {
9 | /// The timestamped value
10 | pub value: Value,
11 | /// Timestamp when the answer was first received
12 | pub moment: Moment,
13 | }
14 |
--------------------------------------------------------------------------------
/pallets/remote-asset-manager/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ['ChainSafe Systems']
3 | description = 'FRAME pallet to bond/unbond and transfer assets on other chains.'
4 | edition = '2018'
5 | license = 'LGPL-3.0-only'
6 | name = 'pallet-remote-asset-manager'
7 | readme = 'README.md'
8 | repository = 'https://github.com/ChainSafe/PINT/'
9 | version = '0.0.1'
10 |
11 | [dependencies]
12 | log = { version = "0.4.14", default-features = false }
13 | serde = { version = "1.0.130", features = ["derive"], optional = true }
14 | codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false }
15 | scale-info = { version = "1.0", default-features = false, features = ["derive"] }
16 |
17 | # Substrate Dependencies
18 | frame-support = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
19 | frame-system = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
20 | frame-benchmarking = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false, optional = true }
21 | pallet-staking = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
22 |
23 | # Polkadot Dependencies
24 | xcm = { git = 'https://github.com/paritytech/polkadot', branch = 'release-v0.9.13', default-features = false }
25 | xcm-executor = { git = 'https://github.com/paritytech/polkadot', branch = 'release-v0.9.13', default-features = false }
26 |
27 | # Cumulus dependencies
28 | cumulus-pallet-xcm = { git = 'https://github.com/paritytech/cumulus', branch = 'polkadot-v0.9.13', default-features = false }
29 | cumulus-primitives-core = { git = 'https://github.com/paritytech/cumulus', branch = 'polkadot-v0.9.13', default-features = false }
30 |
31 | # PINT dependencies
32 | xcm-calls = {path = "../../primitives/xcm-calls", default-features = false }
33 | primitives = { path = "../../primitives/primitives", default-features = false }
34 |
35 | # orml Dependencies
36 | orml-traits = { git = 'https://github.com/open-web3-stack/open-runtime-module-library', branch = 'master', default-features = false }
37 | orml-xtokens = { git = 'https://github.com/open-web3-stack/open-runtime-module-library', branch = 'master', default-features = false }
38 |
39 |
40 | [features]
41 | default = ['std']
42 | std = [
43 | 'serde',
44 | 'codec/std',
45 | 'log/std',
46 | 'frame-support/std',
47 | 'frame-system/std',
48 | 'pallet-staking/std',
49 | 'xcm/std',
50 |
51 | 'xcm-calls/std',
52 | 'primitives/std',
53 |
54 | 'xcm-executor/std',
55 | 'cumulus-pallet-xcm/std',
56 | 'cumulus-primitives-core/std',
57 |
58 | 'orml-traits/std',
59 | 'orml-xtokens/std',
60 | ]
61 | # this feature is only for compilation now
62 | runtime-benchmarks = [
63 | 'frame-benchmarking',
64 | 'frame-support/runtime-benchmarks',
65 | 'frame-system/runtime-benchmarks',
66 | 'primitives/runtime-benchmarks',
67 | ]
68 |
69 | [package.metadata.docs.rs]
70 | targets = ['x86_64-unknown-linux-gnu']
71 |
--------------------------------------------------------------------------------
/pallets/remote-asset-manager/README.md:
--------------------------------------------------------------------------------
1 | License: LGPL-3.0-only
--------------------------------------------------------------------------------
/pallets/remote-asset-manager/src/traits.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | use frame_support::dispatch::DispatchResult;
5 | use orml_traits::GetByKey;
6 |
7 | /// The trait that provides balances related info about the parachain's various
8 | /// sovereign accounts.
9 | ///
10 | /// Definitions:
11 | /// - *Sovereign Account* is an account controlled by a particular Consensus System, within some
12 | /// other Consensus System: The account on the relay chain controlled by the PINT parachain.
13 | /// - *Stash Account* holds funds bonded for staking. If a remote asset (DOT) supports staking then
14 | /// PINT can bond funds that it holds in the sovereign account on the remote chain.
15 | /// Meaning as soon as remote assets are bonded from PINT's sovereign account
16 | /// on a target chain this sovereign account becomes a *stash account*. Both
17 | /// terms now describe one and the same account and are therefore used in the
18 | /// following interchangeably for the same account, even if the remote asset
19 | /// does not support staking.
20 | ///
21 | /// Staking rewards are not tracked since it is intended that the generated
22 | /// staking rewards are routinely exchanged via an AMM for PINT. Some of the
23 | /// resulting PINT will be allocated to the Treasury, with the
24 | /// remainder being burned. This does not affect the staked funds itself, so we
25 | /// only consider two states the funds can have: either free (not bonded), or
26 | /// not free (bonded or unbonded but not withdrawn yet.)
27 | pub trait BalanceMeter {
28 | /// The assumed balance of the PINT's parachain sovereign account on the
29 | /// asset's native chain that is currently not bonded or otherwise locked.
30 | fn free_stash_balance(asset: AssetId) -> Balance;
31 |
32 | /// Ensures that the given amount can be removed from the parachain's
33 | /// sovereign account without falling below the configured
34 | /// `minimum_stash_balance`
35 | fn ensure_free_stash(asset: AssetId, amount: Balance) -> DispatchResult;
36 |
37 | /// Returns the configured minimum stash balance below which the parachain's
38 | /// sovereign account balance must not fall.
39 | fn minimum_free_stash_balance(asset: &AssetId) -> Balance;
40 | }
41 |
42 | /// A type to abstract several staking related thresholds
43 | pub trait StakingCap {
44 | /// The minimum amount that should be held in stash (must remain
45 | /// unbonded).
46 | /// Withdrawals are only authorized if the updated stash balance does
47 | /// exceeds this.
48 | ///
49 | /// This must be at least the `ExistentialDeposit` as configured on the
50 | /// asset's native chain (e.g. DOT/Polkadot)
51 | fn minimum_reserve_balance(asset: AssetId) -> Balance;
52 |
53 | /// The minimum required amount to justify an additional `bond_extra` XCM call to stake
54 | /// additional funds.
55 | fn minimum_bond_extra(asset: AssetId) -> Balance;
56 | }
57 |
58 | // Convenience impl for orml `parameter_type_with_key!` impls
59 | impl StakingCap for (ReserveMinimum, BondExtra)
60 | where
61 | ReserveMinimum: GetByKey,
62 | BondExtra: GetByKey,
63 | {
64 | fn minimum_reserve_balance(asset: AssetId) -> Balance {
65 | ReserveMinimum::get(&asset)
66 | }
67 |
68 | fn minimum_bond_extra(asset: AssetId) -> Balance {
69 | BondExtra::get(&asset)
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/pallets/remote-asset-manager/src/types.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | use codec::{Decode, Encode};
5 | use frame_support::{sp_runtime::traits::AtLeast32BitUnsigned, RuntimeDebug};
6 | use xcm::v1::{AssetId, Fungibility, Junction, Junctions, MultiAsset, MultiLocation};
7 |
8 | /// Represents all XCM calls of the `pallet_staking` pallet transacted on a parachain
9 | #[derive(Default, Encode, Decode, Clone, PartialEq, RuntimeDebug, scale_info::TypeInfo)]
10 | pub struct XcmStakingMessageCount {
11 | /// Total number of all `pallet_staking::Pallet::bond_extra` calls transacted
12 | pub bond_extra: u32,
13 | /// Total number of all `pallet_staking::Pallet::unbond` calls transacted
14 | pub unbond: u32,
15 | /// Total number of all `pallet_staking::Pallet::withdraw_unbonded` calls transacted
16 | pub withdraw_unbonded: u32,
17 | }
18 |
19 | /// Represents the different balances of an asset
20 | #[derive(Default, Encode, Decode, Clone, PartialEq, RuntimeDebug, scale_info::TypeInfo)]
21 | pub struct AssetLedger {
22 | /// The real deposits contributed to the index
23 | pub deposited: Balance,
24 | /// the amount of the asset about to be withdrawn
25 | pub pending_redemption: Balance,
26 | }
27 |
28 | impl AssetLedger
29 | where
30 | Balance: AtLeast32BitUnsigned + Copy,
31 | {
32 | /// Cancel each balance out, after which at least 1 balance is zero.
33 | pub fn consolidate(&mut self) {
34 | let deposited = self.deposited;
35 | self.deposited = self.deposited.saturating_sub(self.pending_redemption);
36 | self.pending_redemption = self.pending_redemption.saturating_sub(deposited);
37 | }
38 | }
39 |
40 | /// Represents the config for the statemint parachain
41 | #[derive(Encode, Decode, Clone, PartialEq, RuntimeDebug, scale_info::TypeInfo)]
42 | #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
43 | pub struct StatemintConfig {
44 | /// The id of the `statemint` parachain
45 | ///
46 | /// *NOTE* using `u32` here instead of location, since `MultiLocation` has
47 | /// no serde support
48 | pub parachain_id: u32,
49 | /// Whether interacting with the parachain is currently active
50 | pub enabled: bool,
51 | }
52 |
53 | impl StatemintConfig {
54 | /// The path to the `statemint` parachain
55 | ///
56 | /// *NOTE:* this is not the full path to the asset on the statemint chain
57 | pub fn parahain_location(&self) -> MultiLocation {
58 | MultiLocation::new(1, Junctions::X1(Junction::Parachain(self.parachain_id)))
59 | }
60 | }
61 | impl StatemintConfig {
62 | /// The XCM `MultiAsset` the statemint parachain expects in order to convert it correctly to the
63 | /// pint asset
64 | pub fn multi_asset(&self, amount: u128) -> MultiAsset {
65 | // TODO simplify when on polkadot-v0.9.9 (xcm-latest) with the correct asset id converter:
66 | // AsPrefixedGeneralIndex::reverse_ref(&self.pint_asset_id.into())
67 | // where Local is MultiLocation = Junctions::Here.into()
68 | MultiAsset { id: AssetId::Concrete(MultiLocation::here()), fun: Fungibility::Fungible(amount) }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/pallets/remote-treasury/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ['ChainSafe Systems']
3 | description = 'FRAME pallet to implement PINT remote treasury.'
4 | edition = '2018'
5 | license = 'LGPL-3.0-only'
6 | name = 'pallet-remote-treasury'
7 | readme = 'README.md'
8 | repository = 'https://github.com/ChainSafe/PINT/'
9 | version = '0.0.1'
10 |
11 | [dependencies]
12 | log = { version = "0.4.14", default-features = false }
13 | serde = { version = "1.0.130", features = ["derive"], optional = true }
14 | codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false }
15 | scale-info = { version = "1.0", default-features = false, features = ["derive"] }
16 |
17 | # Substrate Dependencies
18 | frame-support = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
19 | frame-system = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
20 | frame-benchmarking = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false, optional = true }
21 |
22 | # Polkadot Dependencies
23 | xcm = { git = 'https://github.com/paritytech/polkadot', branch = 'release-v0.9.13', default-features = false }
24 | xcm-executor = { git = 'https://github.com/paritytech/polkadot', branch = 'release-v0.9.13', default-features = false }
25 |
26 | # PINT dependencies
27 | primitives = { path = "../../primitives/primitives", default-features = false }
28 |
29 | # orml Dependencies
30 | orml-traits = { git = 'https://github.com/open-web3-stack/open-runtime-module-library', branch = 'master', default-features = false }
31 | orml-xtokens = { git = 'https://github.com/open-web3-stack/open-runtime-module-library', branch = 'master', default-features = false }
32 |
33 | [dev-dependencies]
34 | serde = "1.0.130"
35 | sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" }
36 | sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" }
37 | sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.13" }
38 | frame-system = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
39 | frame-benchmarking = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
40 |
41 | pallet-balances = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
42 |
43 | [features]
44 | default = ['std']
45 | std = [
46 | 'serde',
47 | 'codec/std',
48 | 'log/std',
49 | 'frame-support/std',
50 | 'frame-system/std',
51 |
52 | 'xcm/std',
53 | 'xcm-executor/std',
54 |
55 | 'primitives/std',
56 |
57 | 'orml-traits/std',
58 | 'orml-xtokens/std',
59 | ]
60 | runtime-benchmarks = [
61 | 'frame-benchmarking',
62 | 'frame-support/runtime-benchmarks',
63 | 'primitives/runtime-benchmarks',
64 | ]
65 |
66 | [package.metadata.docs.rs]
67 | targets = ['x86_64-unknown-linux-gnu']
68 |
--------------------------------------------------------------------------------
/pallets/remote-treasury/README.md:
--------------------------------------------------------------------------------
1 | License: LGPL-3.0-only
--------------------------------------------------------------------------------
/pallets/saft-registry/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ['ChainSafe Systems']
3 | description = 'FRAME pallet to implement PINT SAFT registry.'
4 | edition = '2018'
5 | license = 'LGPL-3.0-only'
6 | name = 'pallet-saft-registry'
7 | readme = 'README.md'
8 | repository = 'https://github.com/ChainSafe/PINT/'
9 | version = '0.0.1'
10 |
11 | [dependencies]
12 | codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false }
13 | scale-info = { version = "1.0", default-features = false, features = ["derive"] }
14 |
15 | # Substrate Dependencies
16 | frame-support = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
17 | frame-system = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
18 | frame-benchmarking = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false, optional = true }
19 |
20 | # polkadot
21 | xcm = { git = 'https://github.com/paritytech/polkadot', branch = 'release-v0.9.13', default-features = false }
22 |
23 | # PINT dependencies
24 | pallet-asset-index = {path = "../asset-index", default-features = false }
25 | primitives = { path = "../../primitives/primitives", default-features = false }
26 |
27 | [dev-dependencies]
28 | serde = "1.0.130"
29 |
30 | # substrate
31 | sp-core = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
32 | sp-io = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
33 | sp-runtime = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
34 |
35 | pallet-balances = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
36 |
37 | pallet-asset-index= { path = "../asset-index" }
38 | pallet-remote-asset-manager = { path = "../remote-asset-manager" }
39 | pallet-price-feed = { path = "../price-feed" }
40 |
41 | # ORML Dependencies
42 | orml-traits = { git = 'https://github.com/open-web3-stack/open-runtime-module-library', branch = 'master' }
43 | orml-tokens = { git = 'https://github.com/open-web3-stack/open-runtime-module-library', branch = 'master' }
44 |
45 | [package.metadata.docs.rs]
46 | targets = ['x86_64-unknown-linux-gnu']
47 |
48 | [features]
49 | default = ['std']
50 | std = [
51 | 'codec/std',
52 | 'frame-support/std',
53 | 'frame-system/std',
54 |
55 | 'xcm/std',
56 |
57 | 'primitives/std'
58 | ]
59 | runtime-benchmarks = [
60 | 'frame-benchmarking',
61 | 'frame-support/runtime-benchmarks',
62 | 'pallet-asset-index/runtime-benchmarks',
63 | 'primitives/runtime-benchmarks',
64 | ]
65 |
--------------------------------------------------------------------------------
/pallets/saft-registry/README.md:
--------------------------------------------------------------------------------
1 | License: LGPL-3.0-only
--------------------------------------------------------------------------------
/pallets/saft-registry/src/benchmarking.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | #![cfg(feature = "runtime-benchmarks")]
5 |
6 | use frame_benchmarking::benchmarks;
7 | use frame_support::{assert_ok, dispatch::UnfilteredDispatchable, sp_runtime::traits::Zero, traits::EnsureOrigin};
8 | use primitives::traits::AssetRecorderBenchmarks;
9 | use xcm::v1::{Junction, MultiLocation};
10 |
11 | use crate::Pallet as SaftRegistry;
12 |
13 | use super::*;
14 |
15 | const MAX_SAFT_RECORDS: u32 = 100;
16 |
17 | benchmarks! {
18 | add_saft {
19 | let asset: T::AssetId = T::try_convert(2u8).unwrap();
20 | let origin = T::AdminOrigin::successful_origin();
21 |
22 | assert_ok!(T::AssetRecorderBenchmarks::add_asset(
23 | T::try_convert(3u8).unwrap(),
24 | 100u32.into(),
25 | MultiLocation::default(),
26 | 1000u32.into()
27 | ));
28 |
29 | let call = Call::::add_saft {
30 | asset_id: asset,
31 | nav: 100u32.into(),
32 | units: 20u32.into()
33 | };
34 | }: { call.dispatch_bypass_filter(origin)? }
35 | verify {
36 | let id = SaftRegistry::::saft_counter(asset) - 1;
37 | assert_eq!(
38 | SaftRegistry::::active_safts(asset, id),
39 | Some(SAFTRecord::new(100_u32.into(), 20_u32.into()))
40 | );
41 | }
42 |
43 | remove_saft {
44 | let asset: T::AssetId = T::try_convert(2u8).unwrap();
45 | let origin = T::AdminOrigin::successful_origin();
46 | let nav = 100u32.into();
47 | let units = 20u32.into();
48 |
49 | assert_ok!(T::AssetRecorderBenchmarks::add_asset(
50 | T::try_convert(3u8).unwrap(),
51 | 100u32.into(),
52 | MultiLocation::default(),
53 | 1000u32.into()
54 | ));
55 |
56 | assert_ok!(T::AssetRecorderBenchmarks::deposit_saft_equivalent(nav));
57 | assert_ok!(SaftRegistry::::add_saft(origin.clone(), asset, nav, units));
58 |
59 | let call = Call::::remove_saft {
60 | asset_id: asset,
61 | saft_id: 0u32
62 | } ;
63 | }: { call.dispatch_bypass_filter(origin)? }
64 | verify {
65 | assert!(
66 | SaftRegistry::::active_safts(asset, 0).is_none()
67 | )
68 | }
69 |
70 | report_nav {
71 | let asset: T::AssetId = T::try_convert(2u8).unwrap();
72 | let origin = T::AdminOrigin::successful_origin();
73 |
74 | assert_ok!(T::AssetRecorderBenchmarks::add_asset(
75 | T::try_convert(3u8).unwrap(),
76 | 100u32.into(),
77 | MultiLocation::default(),
78 | 1000u32.into()
79 | ));
80 |
81 | assert_ok!(SaftRegistry::::add_saft(
82 | origin.clone(),
83 | asset,
84 | 100_u32.into(),
85 | 20_u32.into(),
86 | ));
87 |
88 | let call = Call::::report_nav {
89 | asset_id: asset,
90 | saft_id: 0,
91 | latest_nav: 1000_u32.into()
92 | };
93 | }: { call.dispatch_bypass_filter(origin)? }
94 | verify {
95 | assert_eq!(
96 | SaftRegistry::::active_safts(asset, 0u32),
97 | Some(SAFTRecord::new(1000_u32.into(), 20_u32.into()))
98 | );
99 | }
100 |
101 | convert_to_liquid {
102 | let o in 1 .. MAX_SAFT_RECORDS;
103 |
104 | let nav = 1337u32;
105 | let units = 1234u32;
106 | let asset:T::AssetId = T::try_convert(5u8).unwrap();
107 | let origin = T::AdminOrigin::successful_origin();
108 |
109 | assert_ok!(T::AssetRecorderBenchmarks::add_asset(
110 | T::try_convert(3u8).unwrap(),
111 | 100u32.into(),
112 | MultiLocation::default(),
113 | 1000u32.into()
114 | ));
115 |
116 | assert_ok!(SaftRegistry::::add_saft(
117 | origin.clone(),
118 | asset,
119 | nav.into(),
120 | units.into(),
121 | ));
122 |
123 | assert_ok!(>::try_mutate(asset, |counter: &mut u32| -> Result<(), ()> {
124 | *counter = o;
125 | Ok(())
126 | }));
127 |
128 | let call = Call::::convert_to_liquid {
129 | asset_id: asset,
130 | location: (Junction::Parachain(100)).into()
131 | };
132 | }: { call.dispatch_bypass_filter(origin)? } verify {
133 | assert_eq!(
134 | SaftRegistry::::saft_counter(asset),
135 | 0
136 | );
137 | assert!(
138 | SaftRegistry::::saft_nav(asset).is_zero()
139 | );
140 | }
141 | }
142 |
143 | #[cfg(test)]
144 | mod tests {
145 | use frame_support::assert_ok;
146 |
147 | use crate::mock::{new_test_ext, Test};
148 |
149 | use super::*;
150 |
151 | #[test]
152 | fn add_saft() {
153 | new_test_ext().execute_with(|| {
154 | assert_ok!(Pallet::::test_benchmark_add_saft());
155 | });
156 | }
157 |
158 | #[test]
159 | fn remove_saft() {
160 | new_test_ext().execute_with(|| {
161 | assert_ok!(Pallet::::test_benchmark_remove_saft());
162 | });
163 | }
164 |
165 | #[test]
166 | fn report_nav() {
167 | new_test_ext().execute_with(|| {
168 | assert_ok!(Pallet::::test_benchmark_report_nav());
169 | });
170 | }
171 |
172 | #[test]
173 | fn convert_to_liquid() {
174 | new_test_ext().execute_with(|| {
175 | assert_ok!(Pallet::::test_benchmark_convert_to_liquid());
176 | });
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/pallets/saft-registry/src/traits.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | // TODO: This will be moved into the AssetIndex pallet when that is implemented
5 | // Required here for mock and testing the SAFT registry
6 | #![allow(dead_code)]
7 |
8 | use frame_support::sp_runtime::DispatchError;
9 |
10 | pub enum AssetAvailability {
11 | Liquid,
12 | SAFT,
13 | }
14 |
15 | pub trait AssetRecorder {
16 | /// Add an asset to the recorder. If an asset with the given AssetId already exists
17 | /// then the added asset units will be combined.
18 | /// The provided NAV parameter is the Net Asset Value of the total units provided
19 | /// given in units of some stable asset. In the case of an AssetId that already exists the
20 | /// newly provided NAV will be used to re-value the existing units and compute a total NAV
21 | fn add_asset(
22 | id: &AssetId,
23 | units: &Balance,
24 | availability: &AssetAvailability,
25 | nav: &Balance,
26 | ) -> Result<(), DispatchError>;
27 |
28 | fn remove_asset(id: &AssetId) -> Result<(), DispatchError>;
29 |
30 | fn update_nav(id: &AssetId, nav: &Balance) -> Result<(), DispatchError>;
31 | }
32 |
--------------------------------------------------------------------------------
/primitives/derive/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ['ChainSafe Systems']
3 | description = 'PINT proc-macros'
4 | edition = "2018"
5 | license = 'LGPL-3.0-only'
6 | name = "derive"
7 | repository = 'https://github.com/ChainSafe/PINT/'
8 | version = "0.0.1"
9 |
10 | [lib]
11 | proc-macro = true
12 |
13 | [dependencies]
14 | proc-macro2 = "1.0.32"
15 | quote = "1.0.10"
16 | syn = { version = "1.0.81", features = ["full"] }
17 |
--------------------------------------------------------------------------------
/primitives/derive/README.md:
--------------------------------------------------------------------------------
1 | # derive
2 |
3 | This module contains `proc-macro`s for developing and testing.
4 |
5 | ## #[xcm_error]
6 |
7 | Provides a `From` implementation, could be used for `pallet::Error`.
8 |
9 | For example:
10 |
11 | ```rust
12 | #[pallet:error]
13 | #[xcm_error]
14 | pub enum Error {
15 | // ...
16 | }
17 | ```
18 |
--------------------------------------------------------------------------------
/primitives/derive/src/lib.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 | //! PINT proc-macros
4 | extern crate proc_macro;
5 |
6 | // mod derive;
7 | mod xcm;
8 |
9 | use proc_macro::TokenStream;
10 |
11 | /// `#[xcm_error]`
12 | ///
13 | /// This macro is used for expand errors of xcm::v0::Error
14 | #[proc_macro_attribute]
15 | pub fn xcm_error(_attr: TokenStream, item: TokenStream) -> TokenStream {
16 | xcm::error(item)
17 | }
18 |
--------------------------------------------------------------------------------
/primitives/derive/src/xcm/mod.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 | //! XCM macros
4 | mod result;
5 |
6 | pub use result::error;
7 |
--------------------------------------------------------------------------------
/primitives/derive/src/xcm/result.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 | //! XCM errors
4 | use proc_macro::TokenStream;
5 | use proc_macro2::Span;
6 | use quote::quote;
7 | use syn::{
8 | parse_macro_input, punctuated::Punctuated, token::Comma, Arm, DeriveInput, Expr, ExprMatch, Ident, Pat, PatTuple,
9 | PatTupleStruct, Path, PathArguments, PathSegment,
10 | };
11 |
12 | const XCM_ERRORS: [&str; 27] = [
13 | "Undefined",
14 | "Unimplemented",
15 | "Overflow",
16 | "UnhandledXcmVersion",
17 | "UnhandledXcmMessage",
18 | "UnhandledEffect",
19 | "EscalationOfPrivilege",
20 | "UntrustedReserveLocation",
21 | "UntrustedTeleportLocation",
22 | "DestinationBufferOverflow",
23 | "SendFailed(_)",
24 | "CannotReachDestination(_, _)",
25 | "MultiLocationFull",
26 | "FailedToDecode",
27 | "BadOrigin",
28 | "ExceedsMaxMessageSize",
29 | "FailedToTransactAsset(_)",
30 | "WeightLimitReached(_)",
31 | "Wildcard",
32 | "TooMuchWeightRequired",
33 | "NotHoldingFees",
34 | "WeightNotComputable",
35 | "Barrier",
36 | "NotWithdrawable",
37 | "LocationCannotHold",
38 | "TooExpensive",
39 | "AssetNotFound",
40 | ];
41 |
42 | /// Expand xcm errors
43 | pub fn expand_errors() -> Vec {
44 | XCM_ERRORS
45 | .iter()
46 | .map(|i| {
47 | let ident = Ident::new(if let Some(idx) = i.find('(') { &i[0..idx] } else { i }, Span::call_site());
48 | let (body, pat) = (ident.clone(), {
49 | let count = i.matches('_').count();
50 | if count == 0 {
51 | Pat::Verbatim(quote! { XcmError::#ident })
52 | } else {
53 | let mut elems = Punctuated::new();
54 | for _ in 0..count {
55 | elems.push(Pat::Verbatim(quote! { _ }));
56 | }
57 |
58 | let mut segments = Punctuated::new();
59 | segments.push(PathSegment { ident, arguments: PathArguments::None });
60 |
61 | let ts = Pat::TupleStruct(PatTupleStruct {
62 | attrs: Default::default(),
63 | path: Path { leading_colon: None, segments },
64 | pat: PatTuple { attrs: Default::default(), paren_token: Default::default(), elems },
65 | });
66 |
67 | Pat::Verbatim(quote! { XcmError::#ts })
68 | }
69 | });
70 |
71 | Arm {
72 | attrs: Default::default(),
73 | pat,
74 | guard: None,
75 | fat_arrow_token: Default::default(),
76 | body: Box::new(Expr::Verbatim(quote! { Self::#body })),
77 | comma: Some(Comma::default()),
78 | }
79 | })
80 | .collect()
81 | }
82 |
83 | fn expand_match(arms: Vec) -> ExprMatch {
84 | ExprMatch {
85 | attrs: Default::default(),
86 | match_token: Default::default(),
87 | expr: Box::new(Expr::Verbatim(quote! {e})),
88 | brace_token: Default::default(),
89 | arms,
90 | }
91 | }
92 |
93 | /// Extends xcm errors
94 | pub fn error(input: TokenStream) -> TokenStream {
95 | let input = parse_macro_input!(input as DeriveInput);
96 |
97 | // construct expr match
98 | let xcm_match = expand_match(expand_errors());
99 |
100 | // get generics
101 | let ident = &input.ident;
102 | let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
103 |
104 | let expanded = quote! {
105 | use xcm::v0::Error as XcmError;
106 |
107 | #input
108 |
109 | impl #impl_generics From for #ident #ty_generics #where_clause {
110 | fn from(e: XcmError) -> Self {
111 | #xcm_match
112 | }
113 | }
114 | };
115 |
116 | TokenStream::from(expanded)
117 | }
118 |
--------------------------------------------------------------------------------
/primitives/primitives/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ['ChainSafe Systems']
3 | description = 'Primitive types and traits for PINT.'
4 | edition = '2018'
5 | license = 'LGPL-3.0-only'
6 | name = 'primitives'
7 | readme = 'README.md'
8 | repository = 'https://github.com/ChainSafe/PINT/'
9 | version = '0.0.1'
10 |
11 | [dependencies]
12 | serde = { version = "1.0.130", features = ["derive"], optional = true }
13 | codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false, features = ['derive'] }
14 | scale-info = { version = "1.0", default-features = false, features = ["derive"] }
15 | frame-support = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
16 | frame-system = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
17 |
18 | # Polkadot Dependencies
19 | xcm = { git = 'https://github.com/paritytech/polkadot', branch = 'release-v0.9.13', default-features = false }
20 |
21 | [features]
22 | default = ['std']
23 | std = [
24 | 'serde',
25 | 'codec/std',
26 | 'frame-support/std',
27 | 'frame-system/std',
28 | 'xcm/std',
29 | ]
30 | runtime-benchmarks = []
31 |
32 | [package.metadata.docs.rs]
33 | targets = ['x86_64-unknown-linux-gnu']
34 |
--------------------------------------------------------------------------------
/primitives/primitives/README.md:
--------------------------------------------------------------------------------
1 | License: LGPL-3.0-only
--------------------------------------------------------------------------------
/primitives/primitives/src/fee.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | //! Fee types used in PINT pallets
5 |
6 | use codec::{Decode, Encode};
7 | use frame_support::sp_runtime::traits::AtLeast32Bit;
8 |
9 | /// Represents the fee rate where fee_rate = numerator / denominator
10 | #[derive(Debug, Encode, Decode, Copy, Clone, PartialEq, Eq, scale_info::TypeInfo)]
11 | #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
12 | pub struct FeeRate {
13 | pub numerator: u32,
14 | pub denominator: u32,
15 | }
16 |
17 | impl Default for FeeRate {
18 | fn default() -> Self {
19 | // 0.3%
20 | Self { numerator: 3, denominator: 1_000 }
21 | }
22 | }
23 |
24 | pub trait BaseFee
25 | where
26 | Self: Sized,
27 | {
28 | /// Returns the given amount after applying the fee rate: `self - fee`
29 | fn without_fee(&self, rate: FeeRate) -> Option;
30 |
31 | /// Returns the fees only.
32 | fn fee(&self, rate: FeeRate) -> Option;
33 | }
34 |
35 | impl BaseFee for u128 {
36 | fn without_fee(&self, rate: FeeRate) -> Option {
37 | self.checked_mul(rate.denominator as Self)?.checked_div(rate.denominator as Self + rate.numerator as Self)
38 | }
39 |
40 | fn fee(&self, rate: FeeRate) -> Option {
41 | self.checked_mul(rate.numerator as Self)?.checked_div(rate.denominator as Self)
42 | }
43 | }
44 |
45 | /// Determines the fee upon index token redemptions from range
46 | #[derive(Clone, Decode, Debug, Default, Encode, PartialEq, Eq, scale_info::TypeInfo)]
47 | pub struct RedemptionFeeRange {
48 | pub range: [(BlockNumber, FeeRate); 2],
49 | pub default_fee: FeeRate,
50 | }
51 |
52 | impl RedemptionFeeRange {
53 | /// get fee rate by spent time
54 | fn get_rate(&self, spent_time: BlockNumber) -> FeeRate {
55 | if spent_time < self.range[0].0 {
56 | self.range[0].1
57 | } else if spent_time <= self.range[1].0 {
58 | self.range[1].1
59 | } else {
60 | self.default_fee
61 | }
62 | }
63 |
64 | /// Determines the redemption fee based on how long the given amount were held in the index
65 | ///
66 | /// Parameters:
67 | /// - `time_spent`: The number of blocks the amount were held in the index. This is `current
68 | /// block - deposit`.
69 | /// - `amount`: The amount of index tokens withdrawn
70 | pub fn redemption_fee(&self, time_spent: BlockNumber, amount: Balance) -> Option {
71 | amount.fee(self.get_rate(time_spent))
72 | }
73 | }
74 |
75 | #[cfg(test)]
76 | mod tests {
77 | use super::*;
78 |
79 | #[test]
80 | fn test_fee_calculations() {
81 | let rate = FeeRate { numerator: 3, denominator: 1_000 };
82 |
83 | assert_eq!(1_003.without_fee(rate), Some(1_000));
84 | assert_eq!(1_003.fee(rate), Some(3));
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/primitives/primitives/src/lib.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | //! Primitive types used within PINT
5 | #![cfg_attr(not(feature = "std"), no_std)]
6 |
7 | pub mod fee;
8 | pub mod traits;
9 | pub mod types;
10 |
11 | pub use types::*;
12 |
--------------------------------------------------------------------------------
/primitives/xcm-calls/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ['ChainSafe Systems']
3 | description = 'FRAME pallet with XCM bindings to FRAME pallets.'
4 | edition = '2018'
5 | license = 'LGPL-3.0-only'
6 | name = 'xcm-calls'
7 | readme = 'README.md'
8 | repository = 'https://github.com/ChainSafe/PINT/'
9 | version = '0.0.1'
10 |
11 | [dependencies]
12 | serde = { version = "1.0.130", features = ["derive"], optional = true }
13 | codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false, features = ['derive'] }
14 | scale-info = { version = "1.0", default-features = false, features = ["derive"] }
15 | frame-support = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
16 | frame-system = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13', default-features = false }
17 |
18 | [dev-dependencies]
19 | sp-core = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
20 | sp-runtime = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
21 | sp-staking = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
22 | frame-election-provider-support = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
23 |
24 |
25 | ## Substrate Pallet Dependencies
26 | pallet-assets = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
27 | pallet-staking = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
28 | pallet-proxy = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
29 | pallet-utility = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
30 | pallet-balances = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13'}
31 | pallet-staking-reward-curve = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
32 | pallet-timestamp = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
33 | pallet-session = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
34 | pallet-bags-list = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
35 | sp-npos-elections = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.13' }
36 |
37 | # Polkadot Dependencies
38 | xcm = { git = 'https://github.com/paritytech/polkadot', branch = 'release-v0.9.13' }
39 |
40 | [features]
41 | default = ['std']
42 | std = [
43 | 'serde',
44 | 'codec/std',
45 | 'frame-support/std',
46 | 'frame-system/std'
47 | ]
48 | # this feature is only for compilation now
49 | runtime-benchmarks = []
50 |
51 | [package.metadata.docs.rs]
52 | targets = ['x86_64-unknown-linux-gnu']
53 |
--------------------------------------------------------------------------------
/primitives/xcm-calls/README.md:
--------------------------------------------------------------------------------
1 | # Primitives for cross chain Messages
2 |
3 | This module contains bindings for calls of various FRAME pallets:
4 |
5 | * [Assets Pallet](https://crates.parity.io/pallet_assets/pallet/index.html)
6 | * [Proxy Pallet](https://crates.parity.io/pallet_proxy/pallet/index.html)
7 | * [Staking Pallet](https://crates.parity.io/pallet_staking/index.html)
8 |
9 | Since the generic datatypes of a pallet are dependent on their runtime configuration of a parachains, the encoding to use when sending a [`Xcm::Transact`](https://github.com/paritytech/xcm-format#transact) is depending on the destination of a cross chain message.
10 |
11 | In order for the call to be decodable on the target chain (see Polkadot's [`XcmExecutor`](https://github.com/paritytech/polkadot/tree/master/xcm/xcm-executor)), it must be encoded with the corresponding index of the pallet, which also depends on the runtime configuration of the parachain.
12 |
13 | This provides module provides an excerpt from each pallet's call variants that are used for PINT's cross chain operations.
14 | Each Pallet includes their own encoder type that expects encoders for every generic datatype of the pallet.
--------------------------------------------------------------------------------
/primitives/xcm-calls/src/encode_with.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | //! Additional types for the remote asset manager pallet
5 |
6 | use codec::{Encode, EncodeAsRef, HasCompact, Output};
7 | use frame_support::{sp_runtime::MultiAddress, sp_std::marker::PhantomData};
8 |
9 | /// A helper to encode an item using the provided context
10 | pub trait EncodeWith {
11 | /// Same as `Encode::encode_to` but with additional context
12 | fn encode_to_with(input: &Input, ctx: &Context, dest: &mut T);
13 | }
14 |
15 | /// Encodes the type as it is
16 | pub struct PassthroughEncoder(PhantomData<(I, T)>);
17 |
18 | impl EncodeWith for PassthroughEncoder {
19 | fn encode_to_with(input: &I, _: &Context, dest: &mut T) {
20 | input.encode_to(dest)
21 | }
22 | }
23 |
24 | /// Encodes the type as it is but compact
25 | pub struct PassthroughCompactEncoder(PhantomData<(I, T)>);
26 |
27 | impl EncodeWith for PassthroughCompactEncoder {
28 | fn encode_to_with(input: &I, _: &Context, dest: &mut T) {
29 | <::Type as EncodeAsRef<'_, I>>::RefType::from(input).encode_to(dest)
30 | }
31 | }
32 |
33 | /// Encodes an `AccountId` as `Multiaddress` regardless of the asset id
34 | pub struct MultiAddressLookupSourceEncoder(
35 | PhantomData<(AccountId, AccountIndex, Context)>,
36 | );
37 |
38 | impl EncodeWith
39 | for MultiAddressLookupSourceEncoder
40 | where
41 | AccountId: Encode + Clone,
42 | AccountIndex: HasCompact,
43 | {
44 | fn encode_to_with(account: &AccountId, _: &Context, dest: &mut T) {
45 | MultiAddress::::from(account.clone()).encode_to(dest)
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/primitives/xcm-calls/src/proxy.rs:
--------------------------------------------------------------------------------
1 | // Copyright 2021 ChainSafe Systems
2 | // SPDX-License-Identifier: LGPL-3.0-only
3 |
4 | //! Xcm support for dispatching `pallet_proxy` pallet calls
5 |
6 | use codec::{Decode, Encode, MaxEncodedLen, Output};
7 | use frame_support::{sp_std::vec::Vec, weights::Weight, RuntimeDebug};
8 | #[cfg(feature = "std")]
9 | use serde::{Deserialize, Serialize};
10 |
11 | use crate::{CallEncoder, EncodeWith, PalletCall, PalletCallEncoder};
12 |
13 | /// The index of `pallet_proxy` in the polkadot runtime
14 | pub const POLKADOT_PALLET_PROXY_INDEX: u8 = 29u8;
15 |
16 | /// The identifier the `ProxyType::Staking` variant encodes to
17 | pub const POLKADOT_PALLET_PROXY_TYPE_STAKING_INDEX: u8 = 3u8;
18 |
19 | /// Denotes an enum based (identified by an `u8`) proxy type
20 | #[derive(
21 | Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, MaxEncodedLen, scale_info::TypeInfo,
22 | )]
23 | pub struct ProxyType(pub u8);
24 |
25 | impl From