diff --git a/.github/workflows/pull-request-feature-proposal.yml b/.github/workflows/pull-request-feature-proposal.yml
deleted file mode 100644
index b88fbcb7a30..00000000000
--- a/.github/workflows/pull-request-feature-proposal.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-name: Feature Proposal Pull Request
-
-on:
- pull_request:
- paths:
- - 'feature-proposal/**'
- - 'token/**'
- - 'ci/*-version.sh'
- - '!token/js/**'
- push:
- branches: [master]
- paths:
- - 'feature-proposal/**'
- - 'token/**'
- - 'ci/*-version.sh'
- - '!token/js/**'
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
- cancel-in-progress: true
-
-jobs:
- cargo-test-sbf:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE}}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/bin/rustfilt
- key: cargo-sbf-bins-${{ runner.os }}
-
- - uses: actions/cache@v4
- with:
- path: ~/.cache/solana
- key: solana-${{ env.SOLANA_VERSION }}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
- ./ci/install-program-deps.sh
- echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
-
- - name: Build and test
- run: ./ci/cargo-test-sbf.sh feature-proposal
diff --git a/.github/workflows/pull-request-instruction-padding.yml b/.github/workflows/pull-request-instruction-padding.yml
deleted file mode 100644
index 17756f7c679..00000000000
--- a/.github/workflows/pull-request-instruction-padding.yml
+++ /dev/null
@@ -1,62 +0,0 @@
-name: Instruction Pad Pull Request
-
-on:
- pull_request:
- paths:
- - 'instruction-padding/**'
- - 'ci/*-version.sh'
- - '.github/workflows/pull-request-instruction-padding.yml'
- push:
- branches: [master]
- paths:
- - 'instruction-padding/**'
- - 'ci/*-version.sh'
- - '.github/workflows/pull-request-instruction-padding.yml'
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
- cancel-in-progress: true
-
-jobs:
- cargo-test-sbf:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE}}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/bin/rustfilt
- key: cargo-sbf-bins-${{ runner.os }}
-
- - uses: actions/cache@v4
- with:
- path: ~/.cache/solana
- key: solana-${{ env.SOLANA_VERSION }}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
- ./ci/install-program-deps.sh
- echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
-
- - name: Build and test
- run: ./ci/cargo-test-sbf.sh instruction-padding
diff --git a/.github/workflows/pull-request-js.yml b/.github/workflows/pull-request-js.yml
index f75ef69e438..225874ebade 100644
--- a/.github/workflows/pull-request-js.yml
+++ b/.github/workflows/pull-request-js.yml
@@ -4,14 +4,8 @@ on:
pull_request:
paths:
- 'account-compression/sdk/**'
- - 'libraries/type-length-value/js/**'
- 'name-service/js/**'
- - 'single-pool/js/**'
- - 'stake-pool/js/**'
- - 'token/js/**'
- - 'token-group/js/**'
- 'token-lending/js/**'
- - 'token-metadata/js/**'
- 'token-swap/js/**'
- 'pnpm-lock.yaml'
- '.github/workflows/pull-request-js.yml'
@@ -19,13 +13,7 @@ on:
branches: [master]
paths:
- 'account-compression/sdk/**'
- - 'libraries/type-length-value/js/**'
- - 'single-pool/js/**'
- - 'stake-pool/js/**'
- - 'token/js/**'
- - 'token-group/js/**'
- 'token-lending/js/**'
- - 'token-metadata/js/**'
- 'token-swap/js/**'
- 'pnpm-lock.yaml'
- '.github/workflows/pull-request-js.yml'
@@ -42,24 +30,14 @@ jobs:
package:
[
name-service,
- stake-pool,
- token,
token-swap,
]
include:
# Restrict certain packages to supported Node.js versions.
- package: account-compression
node-version: 20.x
- - package: libraries
- node-version: 20.x
- - package: single-pool
- node-version: 20.5
- - package: token-group
- node-version: 20.x
- package: token-lending
node-version: 18.5
- - package: token-metadata
- node-version: 20.x
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
diff --git a/.github/workflows/pull-request-libraries.yml b/.github/workflows/pull-request-libraries.yml
index 256dacd2586..7b7a06e424f 100644
--- a/.github/workflows/pull-request-libraries.yml
+++ b/.github/workflows/pull-request-libraries.yml
@@ -6,14 +6,12 @@ on:
- 'libraries/**'
- 'ci/*-version.sh'
- '.github/workflows/pull-request-libraries.yml'
- - '!libraries/**/js/**'
push:
branches: [master]
paths:
- 'libraries/**'
- 'ci/*-version.sh'
- '.github/workflows/pull-request-libraries.yml'
- - '!libraries/**/js/**'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@@ -62,22 +60,3 @@ jobs:
- name: Build and test
run: ./ci/cargo-test-sbf.sh libraries
-
- js-test:
- runs-on: ubuntu-latest
- env:
- NODE_VERSION: 20.x
- steps:
- - uses: actions/checkout@v4
- - name: Use Node.js ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v4
- with:
- node-version: ${{ env.NODE_VERSION }}
- - uses: pnpm/action-setup@v4
- - uses: actions/cache@v4
- with:
- path: ~/.npm
- key: node-${{ hashFiles('pnpm-lock.yaml') }}
- restore-keys: |
- node-
- - run: ./ci/js-test-libraries.sh
diff --git a/.github/workflows/pull-request-record.yml b/.github/workflows/pull-request-record.yml
deleted file mode 100644
index 6199fe98226..00000000000
--- a/.github/workflows/pull-request-record.yml
+++ /dev/null
@@ -1,60 +0,0 @@
-name: Record Pull Request
-
-on:
- pull_request:
- paths:
- - 'record/**'
- - 'ci/*-version.sh'
- push:
- branches: [master]
- paths:
- - 'record/**'
- - 'ci/*-version.sh'
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
- cancel-in-progress: true
-
-jobs:
- cargo-test-sbf:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE}}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/bin/rustfilt
- key: cargo-sbf-bins-${{ runner.os }}
-
- - uses: actions/cache@v4
- with:
- path: ~/.cache/solana
- key: solana-${{ env.SOLANA_VERSION }}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
- ./ci/install-program-deps.sh
- echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
-
- - name: Build and test
- run: ./ci/cargo-test-sbf.sh record
diff --git a/.github/workflows/pull-request-single-pool.yml b/.github/workflows/pull-request-single-pool.yml
deleted file mode 100644
index 7a8483dc08e..00000000000
--- a/.github/workflows/pull-request-single-pool.yml
+++ /dev/null
@@ -1,132 +0,0 @@
-name: Single-Validator Stake Pool Pull Request
-
-on:
- pull_request:
- paths:
- - 'single-pool/**'
- - 'token/**'
- - 'associated-token-account/**'
- - 'ci/*-version.sh'
- - '.github/workflows/pull-request-single-pool.yml'
- - '!single-pool/js/**'
- - '!token/js/**'
- push:
- branches: [master]
- paths:
- - 'single-pool/**'
- - 'token/**'
- - 'associated-token-account/**'
- - 'ci/*-version.sh'
- - '.github/workflows/pull-request-single-pool.yml'
- - '!single-pool/js/**'
- - '!token/js/**'
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
- cancel-in-progress: true
-
-jobs:
- cargo-test-sbf:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE}}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/bin/rustfilt
- key: cargo-sbf-bins-${{ runner.os }}
-
- - uses: actions/cache@v4
- with:
- path: ~/.cache/solana
- key: solana-${{ env.SOLANA_VERSION }}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
- ./ci/install-program-deps.sh
- echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
-
- - name: Build and test
- run: ./ci/cargo-test-sbf.sh single-pool/program
-
- cargo-build-test-cli:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: ~/.cache/solana
- key: solana-${{ env.SOLANA_VERSION }}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
- ./ci/install-program-deps.sh
- echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
-
- - name: Build dependent programs
- run: |
- cargo build-sbf --manifest-path=single-pool/program/Cargo.toml
-
- - name: Build and test
- run: |
- cargo build --manifest-path ./single-pool/cli/Cargo.toml
- cargo test --manifest-path ./single-pool/cli/Cargo.toml
-
- js-test:
- runs-on: ubuntu-latest
- env:
- NODE_VERSION: 20.5
- steps:
- - uses: actions/checkout@v4
- - name: Use Node.js ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v4
- with:
- node-version: ${{ env.NODE_VERSION }}
- - uses: pnpm/action-setup@v4
- - uses: actions/cache@v4
- with:
- path: ~/.npm
- key: node-${{ hashFiles('pnpm-lock.yaml') }}
- restore-keys: |
- node-
- - run: ./ci/js-test-single-pool.sh
diff --git a/.github/workflows/pull-request-stake-pool.yml b/.github/workflows/pull-request-stake-pool.yml
deleted file mode 100644
index 0b7e686264e..00000000000
--- a/.github/workflows/pull-request-stake-pool.yml
+++ /dev/null
@@ -1,129 +0,0 @@
-name: Stake Pool Pull Request
-
-on:
- pull_request:
- paths:
- - 'stake-pool/**'
- - 'token/**'
- - 'ci/*-version.sh'
- - 'ci/warning/purge-ubuntu-runner.sh'
- - '.github/workflows/pull-request-stake-pool.yml'
- - '!stake-pool/js/**'
- - '!token/js/**'
- push:
- branches: [master]
- paths:
- - 'stake-pool/**'
- - 'token/**'
- - 'ci/*-version.sh'
- - 'ci/warning/purge-ubuntu-runner.sh'
- - '.github/workflows/pull-request-stake-pool.yml'
- - '!stake-pool/js/**'
- - '!token/js/**'
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
- cancel-in-progress: true
-
-jobs:
- cargo-test-sbf:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Check disk space
- run: df -h
-
- - name: Remove unneeded packages for more space
- run: bash ./ci/warning/purge-ubuntu-runner.sh
-
- - name: Check disk space again
- run: df -h
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE}}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/bin/rustfilt
- key: cargo-sbf-bins-${{ runner.os }}
-
- - uses: actions/cache@v4
- with:
- path: ~/.cache/solana
- key: solana-${{ env.SOLANA_VERSION }}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
- ./ci/install-program-deps.sh
- echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
-
- - name: Build and test
- run: ./ci/cargo-test-sbf.sh stake-pool
-
- - name: Upload programs
- uses: actions/upload-artifact@v4
- with:
- name: stake-pool-programs
- path: "target/deploy/*.so"
- if-no-files-found: error
-
- js-test:
- runs-on: ubuntu-latest
- env:
- NODE_VERSION: 16.x
- steps:
- - uses: actions/checkout@v4
- - name: Use Node.js ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v4
- with:
- node-version: ${{ env.NODE_VERSION }}
- - uses: pnpm/action-setup@v4
- - uses: actions/cache@v4
- with:
- path: ~/.npm
- key: node-${{ hashFiles('pnpm-lock.yaml') }}
- restore-keys: |
- node-
- - run: ./ci/js-test-stake-pool.sh
-
- py-test:
- runs-on: ubuntu-latest
- needs: cargo-test-sbf
- steps:
- - uses: actions/checkout@v4
-
- - name: Setup Python version
- uses: actions/setup-python@v4
- with:
- python-version: 3.8
-
- - uses: actions/cache@v4
- with:
- path: ~/.cache/pip
- key: pip-stake-pool-${{ hashFiles('stake-pool/py/requirements.txt') }}
-
- - name: Download programs
- uses: actions/download-artifact@v4
- with:
- name: stake-pool-programs
- path: target/deploy
-
- - run: ./ci/py-test-stake-pool.sh
diff --git a/.github/workflows/pull-request-token-group.yml b/.github/workflows/pull-request-token-group.yml
deleted file mode 100644
index 2e1ef89ef93..00000000000
--- a/.github/workflows/pull-request-token-group.yml
+++ /dev/null
@@ -1,91 +0,0 @@
-name: Token-Group Pull Request
-
-on:
- pull_request:
- paths:
- - 'token-group/**'
- - 'token/program-2022/**'
- - 'ci/*-version.sh'
- - '.github/workflows/pull-request-token-group.yml'
- - '!token-group/js/**'
- push:
- branches: [master]
- paths:
- - 'token-group/**'
- - 'token/program-2022/**'
- - 'ci/*-version.sh'
- - '.github/workflows/pull-request-token-group.yml'
- - '!token-group/js/**'
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
- cancel-in-progress: true
-
-jobs:
- cargo-test-sbf:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE}}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/bin/rustfilt
- key: cargo-sbf-bins-${{ runner.os }}
-
- - uses: actions/cache@v4
- with:
- path: ~/.cache/solana
- key: solana-${{ env.SOLANA_VERSION }}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
- ./ci/install-program-deps.sh
- echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
-
- - name: Test token-group interface
- run: |
- cargo test \
- --manifest-path=token-group/interface/Cargo.toml \
- -- --nocapture
-
- - name: Build and test example
- run: ./ci/cargo-test-sbf.sh token-group/example
-
- js-test:
- runs-on: ubuntu-latest
- env:
- NODE_VERSION: 20.x
- steps:
- - uses: actions/checkout@v4
- - name: Use Node.js ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v4
- with:
- node-version: ${{ env.NODE_VERSION }}
- - uses: pnpm/action-setup@v4
- - uses: actions/cache@v4
- with:
- path: ~/.npm
- key: node-${{ hashFiles('pnpm-lock.yaml') }}
- restore-keys: |
- node-
- - run: ./ci/js-test-token-group.sh
diff --git a/.github/workflows/pull-request-token-metadata.yml b/.github/workflows/pull-request-token-metadata.yml
deleted file mode 100644
index 3ec26f79970..00000000000
--- a/.github/workflows/pull-request-token-metadata.yml
+++ /dev/null
@@ -1,92 +0,0 @@
-name: Token-Metadata Pull Request
-
-on:
- pull_request:
- paths:
- - 'token-metadata/**'
- - 'token/program-2022/**'
- - 'ci/*-version.sh'
- - '.github/workflows/pull-request-token-metadata.yml'
- - '!token-metadata/js/**'
- push:
- branches: [master]
- paths:
- - 'token-metadata/**'
- - 'token/program-2022/**'
- - 'ci/*-version.sh'
- - '.github/workflows/pull-request-token-metadata.yml'
- - '!token-metadata/js/**'
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
- cancel-in-progress: true
-
-jobs:
- cargo-test-sbf:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE}}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/bin/rustfilt
- key: cargo-sbf-bins-${{ runner.os }}
-
- - uses: actions/cache@v4
- with:
- path: ~/.cache/solana
- key: solana-${{ env.SOLANA_VERSION }}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
- ./ci/install-program-deps.sh
- echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
-
- - name: Test token-metadata with "serde" activated
- run: |
- cargo test \
- --manifest-path=token-metadata/interface/Cargo.toml \
- --features serde-traits \
- -- --nocapture
-
- - name: Build and test example
- run: ./ci/cargo-test-sbf.sh token-metadata/example
-
- js-test:
- runs-on: ubuntu-latest
- env:
- NODE_VERSION: 20.x
- steps:
- - uses: actions/checkout@v4
- - name: Use Node.js ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v4
- with:
- node-version: ${{ env.NODE_VERSION }}
- - uses: pnpm/action-setup@v4
- - uses: actions/cache@v4
- with:
- path: ~/.npm
- key: node-${{ hashFiles('pnpm-lock.yaml') }}
- restore-keys: |
- node-
- - run: ./ci/js-test-token-metadata.sh
diff --git a/.github/workflows/pull-request-token.yml b/.github/workflows/pull-request-token.yml
deleted file mode 100644
index 18ed249ef75..00000000000
--- a/.github/workflows/pull-request-token.yml
+++ /dev/null
@@ -1,337 +0,0 @@
-name: Token Pull Request
-
-on:
- pull_request:
- paths:
- - 'associated-token-account/**'
- - 'token/**'
- - 'ci/*-version.sh'
- - '.github/workflows/pull-request-token.yml'
- - '!token/js/**'
- push:
- branches: [master]
- paths:
- - 'associated-token-account/**'
- - 'token/**'
- - 'ci/*-version.sh'
- - '.github/workflows/pull-request-token.yml'
- - '!token/js/**'
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
- cancel-in-progress: true
-
-jobs:
- cargo-test-sbf:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Remove unneeded packages for more space
- run: bash ./ci/warning/purge-ubuntu-runner.sh
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE}}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/bin/rustfilt
- key: cargo-sbf-bins-${{ runner.os }}
-
- - uses: actions/cache@v4
- with:
- path: ~/.cache/solana
- key: solana-${{ env.SOLANA_VERSION }}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
- ./ci/install-program-deps.sh
- echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
-
- - name: Build and test token
- run: ./ci/cargo-test-sbf.sh token
-
- cargo-test-token-2022-serde:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE}}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
-
- - name: Test token-2022 with "serde" activated
- run: |
- cargo test \
- --manifest-path=token/program-2022/Cargo.toml \
- --features serde-traits \
- -- --nocapture
-
- cargo-test-sbf-transfer-hook:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE}}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/bin/rustfilt
- key: cargo-sbf-bins-${{ runner.os }}
-
- - uses: actions/cache@v4
- with:
- path: ~/.cache/solana
- key: solana-${{ env.SOLANA_VERSION }}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
- ./ci/install-program-deps.sh
- echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
-
- - name: Build and test transfer hook example
- run: ./ci/cargo-test-sbf.sh token/transfer-hook/example
-
- - name: Upload program
- uses: actions/upload-artifact@v4
- with:
- name: spl-transfer-hook-example
- path: "target/deploy/*.so"
- if-no-files-found: error
-
- cargo-test-sbf-associated-token-account:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE}}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/bin/rustfilt
- key: cargo-sbf-bins-${{ runner.os }}
-
- - uses: actions/cache@v4
- with:
- path: ~/.cache/solana
- key: solana-${{ env.SOLANA_VERSION }}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
- ./ci/install-program-deps.sh
- echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
-
- - name: Build and test ATA
- run: ./ci/cargo-test-sbf.sh associated-token-account
-
- cargo-test-sbf-token-2022:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Remove unneeded packages for more space
- run: bash ./ci/warning/purge-ubuntu-runner.sh
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE_VERSION }}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
- ./ci/install-program-deps.sh
- echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
-
- - name: Build and test token-2022
- run: |
- cargo build-sbf --manifest-path token/program-2022/Cargo.toml
- cargo build-sbf --manifest-path instruction-padding/program/Cargo.toml
- ./ci/cargo-test-sbf.sh token/program-2022-test
-
- js-test:
- runs-on: ubuntu-latest
- env:
- NODE_VERSION: 16.x
- steps:
- - uses: actions/checkout@v4
- - name: Use Node.js ${{ env.NODE_VERSION }}
- uses: actions/setup-node@v4
- with:
- node-version: ${{ env.NODE_VERSION }}
- - uses: pnpm/action-setup@v4
- - uses: actions/cache@v4
- with:
- path: ~/.npm
- key: node-${{ hashFiles('pnpm-lock.yaml') }}
- restore-keys: |
- node-
- - run: ./ci/js-test-token.sh
-
- cargo-build-test-cli:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: ~/.cache/solana
- key: solana-${{ env.SOLANA_VERSION }}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
- ./ci/install-program-deps.sh
- echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
-
- - name: Build and test
- run: |
- BUILD_DEPENDENT_PROGRAMS=1 cargo build --manifest-path ./token/cli/Cargo.toml
- cargo test --manifest-path ./token/cli/Cargo.toml
-
- cargo-build-test-transfer-hook-cli:
- runs-on: ubuntu-latest
- needs: [cargo-test-sbf]
- steps:
- - uses: actions/checkout@v4
-
- - name: Set env vars
- run: |
- source ci/rust-version.sh
- echo "RUST_STABLE=$rust_stable" >> $GITHUB_ENV
- source ci/solana-version.sh
- echo "SOLANA_VERSION=$solana_version" >> $GITHUB_ENV
-
- - uses: dtolnay/rust-toolchain@master
- with:
- toolchain: ${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cargo/registry
- ~/.cargo/git
- key: cargo-build-${{ hashFiles('**/Cargo.lock') }}-${{ env.RUST_STABLE }}
-
- - uses: actions/cache@v4
- with:
- path: ~/.cache/solana
- key: solana-${{ env.SOLANA_VERSION }}
-
- - name: Install dependencies
- run: |
- ./ci/install-build-deps.sh
- ./ci/install-program-deps.sh
- echo "$HOME/.local/share/solana/install/active_release/bin" >> $GITHUB_PATH
-
- - name: Download spl-transfer-hook-example program
- uses: actions/download-artifact@v4
- with:
- name: spl-transfer-hook-example
- path: target/deploy
-
- - name: Build and test
- run: |
- cargo test --manifest-path ./token/transfer-hook/cli/Cargo.toml
diff --git a/Anchor.toml b/Anchor.toml
index e8bd9dfc048..5ec1ebb7bf3 100644
--- a/Anchor.toml
+++ b/Anchor.toml
@@ -6,9 +6,6 @@ solana_version = "2.1.0"
members = [
"governance/program",
"governance/chat/program",
- "stake-pool/program",
- "token/program",
- "token/program-2022",
]
exclude = [
"account-compression/"
@@ -21,6 +18,3 @@ wallet = "~/.config/solana/id.json"
[programs.mainnet]
spl_governance = "GovER5Lthms3bLBqWub97yVrMmEogzX7xNjdXpPPCVZw"
spl_governance_chat = "gCHAtYKrUUktTVzE4hEnZdLV4LXrdBf6Hh9qMaJALET"
-spl_stake_pool = "SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy"
-spl_token = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
-spl_token_2022 = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
diff --git a/Cargo.lock b/Cargo.lock
index 0aaac540b50..cdb00c16039 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -178,70 +178,12 @@ dependencies = [
"winapi 0.3.9",
]
-[[package]]
-name = "anstream"
-version = "0.6.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
-dependencies = [
- "anstyle",
- "anstyle-parse",
- "anstyle-query",
- "anstyle-wincon",
- "colorchoice",
- "is_terminal_polyfill",
- "utf8parse",
-]
-
-[[package]]
-name = "anstyle"
-version = "1.0.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
-
-[[package]]
-name = "anstyle-parse"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140"
-dependencies = [
- "utf8parse",
-]
-
-[[package]]
-name = "anstyle-query"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
-dependencies = [
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "anstyle-wincon"
-version = "3.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
-dependencies = [
- "anstyle",
- "windows-sys 0.48.0",
-]
-
[[package]]
name = "anyhow"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8"
-[[package]]
-name = "approx"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
-dependencies = [
- "num-traits",
-]
-
[[package]]
name = "aquamarine"
version = "0.3.3"
@@ -445,22 +387,6 @@ dependencies = [
"syn 1.0.107",
]
-[[package]]
-name = "assert_cmd"
-version = "2.0.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d"
-dependencies = [
- "anstyle",
- "bstr 1.6.0",
- "doc-comment",
- "libc",
- "predicates 3.0.3",
- "predicates-core",
- "predicates-tree",
- "wait-timeout",
-]
-
[[package]]
name = "assert_matches"
version = "1.5.0"
@@ -899,17 +825,6 @@ dependencies = [
"memchr",
]
-[[package]]
-name = "bstr"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05"
-dependencies = [
- "memchr",
- "regex-automata 0.3.0",
- "serde",
-]
-
[[package]]
name = "bumpalo"
version = "3.12.0"
@@ -1144,8 +1059,7 @@ checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
dependencies = [
"atty",
"bitflags 1.3.2",
- "clap_derive 3.2.25",
- "clap_lex 0.2.4",
+ "clap_lex",
"indexmap 1.9.3",
"once_cell",
"strsim 0.10.0",
@@ -1153,53 +1067,6 @@ dependencies = [
"textwrap 0.16.0",
]
-[[package]]
-name = "clap"
-version = "4.4.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64"
-dependencies = [
- "clap_builder",
- "clap_derive 4.4.7",
-]
-
-[[package]]
-name = "clap_builder"
-version = "4.4.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc"
-dependencies = [
- "anstream",
- "anstyle",
- "clap_lex 0.6.0",
- "strsim 0.10.0",
-]
-
-[[package]]
-name = "clap_derive"
-version = "3.2.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008"
-dependencies = [
- "heck 0.4.1",
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn 1.0.107",
-]
-
-[[package]]
-name = "clap_derive"
-version = "4.4.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
-dependencies = [
- "heck 0.4.1",
- "proc-macro2",
- "quote",
- "syn 2.0.87",
-]
-
[[package]]
name = "clap_lex"
version = "0.2.4"
@@ -1209,12 +1076,6 @@ dependencies = [
"os_str_bytes",
]
-[[package]]
-name = "clap_lex"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
-
[[package]]
name = "codespan-reporting"
version = "0.11.1"
@@ -1225,12 +1086,6 @@ dependencies = [
"unicode-width 0.1.9",
]
-[[package]]
-name = "colorchoice"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
-
[[package]]
name = "combine"
version = "3.8.1"
@@ -1591,7 +1446,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
- "serde",
]
[[package]]
@@ -1746,12 +1600,6 @@ dependencies = [
"syn 2.0.87",
]
-[[package]]
-name = "doc-comment"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
-
[[package]]
name = "downcast"
version = "0.11.0"
@@ -1906,15 +1754,6 @@ dependencies = [
"windows-sys 0.52.0",
]
-[[package]]
-name = "escape8259"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba4f4911e3666fcd7826997b4745c8224295a6f3072f1418c3067b97a67557ee"
-dependencies = [
- "rustversion",
-]
-
[[package]]
name = "etcd-client"
version = "0.11.1"
@@ -2272,7 +2111,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd"
dependencies = [
"aho-corasick 0.7.18",
- "bstr 0.2.17",
+ "bstr",
"fnv",
"log",
"regex",
@@ -2419,12 +2258,6 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
-[[package]]
-name = "heck"
-version = "0.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
-
[[package]]
name = "hermit-abi"
version = "0.1.19"
@@ -2734,7 +2567,6 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
- "serde",
]
[[package]]
@@ -2746,7 +2578,6 @@ dependencies = [
"equivalent",
"hashbrown 0.15.1",
"rayon",
- "serde",
]
[[package]]
@@ -2786,12 +2617,6 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
-[[package]]
-name = "is_terminal_polyfill"
-version = "1.70.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
-
[[package]]
name = "itertools"
version = "0.10.5"
@@ -3092,18 +2917,6 @@ dependencies = [
"libsecp256k1-core",
]
-[[package]]
-name = "libtest-mimic"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5297962ef19edda4ce33aaa484386e0a5b3d7f2f4e037cbeee00503ef6b29d33"
-dependencies = [
- "anstream",
- "anstyle",
- "clap 4.4.8",
- "escape8259",
-]
-
[[package]]
name = "libz-sys"
version = "1.1.5"
@@ -3327,7 +3140,7 @@ dependencies = [
"fragile",
"lazy_static",
"mockall_derive",
- "predicates 2.1.5",
+ "predicates",
"predicates-tree",
]
@@ -3939,18 +3752,6 @@ dependencies = [
"regex",
]
-[[package]]
-name = "predicates"
-version = "3.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9"
-dependencies = [
- "anstyle",
- "difflib",
- "itertools 0.10.5",
- "predicates-core",
-]
-
[[package]]
name = "predicates-core"
version = "1.0.6"
@@ -4405,16 +4206,10 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick 1.0.2",
"memchr",
- "regex-automata 0.4.8",
+ "regex-automata",
"regex-syntax",
]
-[[package]]
-name = "regex-automata"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa250384981ea14565685dea16a9ccc4d1c541a13f82b9c168572264d1df8c56"
-
[[package]]
name = "regex-automata"
version = "0.4.8"
@@ -4762,15 +4557,6 @@ dependencies = [
"winapi-util",
]
-[[package]]
-name = "scc"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec96560eea317a9cc4e0bb1f6a2c93c09a19b8c4fc5cb3fcc0ec1c094cd783e2"
-dependencies = [
- "sdd",
-]
-
[[package]]
name = "schannel"
version = "0.1.19"
@@ -4809,12 +4595,6 @@ dependencies = [
"untrusted 0.7.1",
]
-[[package]]
-name = "sdd"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b84345e4c9bd703274a082fb80caaa99b7612be48dfaa1dd9266577ec412309d"
-
[[package]]
name = "security-framework"
version = "2.10.0"
@@ -4913,16 +4693,9 @@ version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa"
dependencies = [
- "base64 0.22.1",
- "chrono",
- "hex",
- "indexmap 1.9.3",
- "indexmap 2.6.0",
"serde",
"serde_derive",
- "serde_json",
"serde_with_macros",
- "time",
]
[[package]]
@@ -4950,31 +4723,6 @@ dependencies = [
"unsafe-libyaml",
]
-[[package]]
-name = "serial_test"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9"
-dependencies = [
- "futures 0.3.31",
- "log",
- "once_cell",
- "parking_lot 0.12.0",
- "scc",
- "serial_test_derive",
-]
-
-[[package]]
-name = "serial_test_derive"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.87",
-]
-
[[package]]
name = "sha-1"
version = "0.8.2"
@@ -5782,8 +5530,8 @@ dependencies = [
"solana-vote",
"solana-vote-program",
"solana-wen-restart",
- "strum 0.24.1",
- "strum_macros 0.24.3",
+ "strum",
+ "strum_macros",
"sys-info",
"sysctl",
"tempfile",
@@ -6176,8 +5924,8 @@ dependencies = [
"spl-token 6.0.0",
"spl-token-2022 4.0.0",
"static_assertions",
- "strum 0.24.1",
- "strum_macros 0.24.3",
+ "strum",
+ "strum_macros",
"tar",
"tempfile",
"thiserror 1.0.69",
@@ -6889,8 +6637,8 @@ dependencies = [
"solana-zk-token-proof-program",
"solana-zk-token-sdk",
"static_assertions",
- "strum 0.24.1",
- "strum_macros 0.24.3",
+ "strum",
+ "strum_macros",
"symlink",
"tar",
"tempfile",
@@ -7765,6 +7513,8 @@ dependencies = [
[[package]]
name = "spl-associated-token-account"
version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76fee7d65013667032d499adc3c895e286197a35a0d3a4643c80e7fd3e9969e3"
dependencies = [
"borsh 1.5.3",
"num-derive",
@@ -7773,31 +7523,19 @@ dependencies = [
"spl-associated-token-account-client",
"spl-token 7.0.0",
"spl-token-2022 6.0.0",
- "thiserror 2.0.9",
+ "thiserror 1.0.69",
]
[[package]]
name = "spl-associated-token-account-client"
version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6f8349dbcbe575f354f9a533a21f272f3eb3808a49e2fdc1c34393b88ba76cb"
dependencies = [
"solana-instruction",
- "solana-program",
"solana-pubkey",
]
-[[package]]
-name = "spl-associated-token-account-test"
-version = "0.0.1"
-dependencies = [
- "solana-program",
- "solana-program-test",
- "solana-sdk",
- "spl-associated-token-account 6.0.0",
- "spl-associated-token-account-client",
- "spl-token 7.0.0",
- "spl-token-2022 6.0.0",
-]
-
[[package]]
name = "spl-binary-oracle-pair"
version = "0.1.0"
@@ -7834,27 +7572,19 @@ checksum = "a38ea8b6dedb7065887f12d62ed62c1743aa70749e8558f963609793f6fb12bc"
dependencies = [
"bytemuck",
"solana-program",
- "spl-discriminator-derive 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "spl-discriminator-derive",
]
[[package]]
name = "spl-discriminator"
-version = "0.4.0"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7398da23554a31660f17718164e31d31900956054f54f52d5ec1be51cb4f4b3"
dependencies = [
- "borsh 1.5.3",
"bytemuck",
"solana-program-error",
"solana-sha256-hasher",
- "spl-discriminator-derive 0.2.0",
-]
-
-[[package]]
-name = "spl-discriminator-derive"
-version = "0.2.0"
-dependencies = [
- "quote",
- "spl-discriminator-syn 0.2.0",
- "syn 2.0.87",
+ "spl-discriminator-derive",
]
[[package]]
@@ -7864,19 +7594,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750"
dependencies = [
"quote",
- "spl-discriminator-syn 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 2.0.87",
-]
-
-[[package]]
-name = "spl-discriminator-syn"
-version = "0.2.0"
-dependencies = [
- "proc-macro2",
- "quote",
- "sha2 0.10.8",
+ "spl-discriminator-syn",
"syn 2.0.87",
- "thiserror 1.0.69",
]
[[package]]
@@ -7895,6 +7614,8 @@ dependencies = [
[[package]]
name = "spl-elgamal-registry"
version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a157622a63a4d12fbd8b347fd75ee442cb913137fa98647824c992fb049a15b"
dependencies = [
"bytemuck",
"solana-program",
@@ -7958,31 +7679,6 @@ dependencies = [
"spl-token 7.0.0",
]
-[[package]]
-name = "spl-feature-proposal"
-version = "1.0.0"
-dependencies = [
- "borsh 1.5.3",
- "solana-program",
- "solana-program-test",
- "solana-sdk",
- "spl-token 7.0.0",
-]
-
-[[package]]
-name = "spl-feature-proposal-cli"
-version = "1.2.0"
-dependencies = [
- "chrono",
- "clap 2.34.0",
- "solana-clap-utils",
- "solana-cli-config",
- "solana-client",
- "solana-logger",
- "solana-sdk",
- "spl-feature-proposal",
-]
-
[[package]]
name = "spl-governance"
version = "4.0.0"
@@ -8100,23 +7796,6 @@ dependencies = [
"thiserror 2.0.9",
]
-[[package]]
-name = "spl-instruction-padding"
-version = "0.3.0"
-dependencies = [
- "num_enum",
- "solana-account-info",
- "solana-cpi",
- "solana-instruction",
- "solana-program",
- "solana-program-entrypoint",
- "solana-program-error",
- "solana-program-test",
- "solana-pubkey",
- "solana-sdk",
- "static_assertions",
-]
-
[[package]]
name = "spl-managed-token"
version = "0.1.0"
@@ -8217,22 +7896,21 @@ dependencies = [
[[package]]
name = "spl-pod"
version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41a7d5950993e1ff2680bd989df298eeb169367fb2f9deeef1f132de6e4e8016"
dependencies = [
- "base64 0.22.1",
"borsh 1.5.3",
"bytemuck",
"bytemuck_derive",
"num-derive",
"num-traits",
- "serde",
- "serde_json",
"solana-decode-error",
"solana-msg",
"solana-program-error",
"solana-program-option",
"solana-pubkey",
"solana-zk-sdk",
- "thiserror 2.0.9",
+ "thiserror 1.0.69",
]
[[package]]
@@ -8244,32 +7922,21 @@ dependencies = [
"num-derive",
"num-traits",
"solana-program",
- "spl-program-error-derive 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "spl-program-error-derive",
"thiserror 1.0.69",
]
[[package]]
name = "spl-program-error"
version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d39b5186f42b2b50168029d81e58e800b690877ef0b30580d107659250da1d1"
dependencies = [
- "lazy_static",
"num-derive",
"num-traits",
- "serial_test",
"solana-program",
- "solana-sdk",
- "spl-program-error-derive 0.4.1",
- "thiserror 2.0.9",
-]
-
-[[package]]
-name = "spl-program-error-derive"
-version = "0.4.1"
-dependencies = [
- "proc-macro2",
- "quote",
- "sha2 0.10.8",
- "syn 2.0.87",
+ "spl-program-error-derive",
+ "thiserror 1.0.69",
]
[[package]]
@@ -8287,6 +7954,8 @@ dependencies = [
[[package]]
name = "spl-record"
version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1288810a85bbe7e62ee3c6f7b8119e8c1016e90351411d12e4132e98c7ca7344"
dependencies = [
"bytemuck",
"num-derive",
@@ -8298,11 +7967,9 @@ dependencies = [
"solana-program-entrypoint",
"solana-program-error",
"solana-program-pack",
- "solana-program-test",
"solana-pubkey",
"solana-rent",
- "solana-sdk",
- "thiserror 2.0.9",
+ "thiserror 1.0.69",
]
[[package]]
@@ -8315,143 +7982,6 @@ dependencies = [
"solana-sdk",
]
-[[package]]
-name = "spl-single-pool"
-version = "1.0.1"
-dependencies = [
- "approx",
- "arrayref",
- "bincode",
- "borsh 1.5.3",
- "num-derive",
- "num-traits",
- "num_enum",
- "rand 0.8.5",
- "solana-program",
- "solana-program-test",
- "solana-sdk",
- "solana-security-txt",
- "solana-vote-program",
- "spl-associated-token-account 6.0.0",
- "spl-associated-token-account-client",
- "spl-token 7.0.0",
- "test-case",
- "thiserror 2.0.9",
-]
-
-[[package]]
-name = "spl-single-pool-cli"
-version = "1.0.0"
-dependencies = [
- "bincode",
- "borsh 1.5.3",
- "clap 3.2.25",
- "console",
- "serde",
- "serde_derive",
- "serde_json",
- "serde_with",
- "serial_test",
- "solana-account-decoder",
- "solana-clap-v3-utils",
- "solana-cli-config",
- "solana-cli-output",
- "solana-client",
- "solana-logger",
- "solana-remote-wallet",
- "solana-sdk",
- "solana-test-validator",
- "solana-transaction-status",
- "solana-vote-program",
- "spl-single-pool",
- "spl-token 7.0.0",
- "spl-token-client",
- "tempfile",
- "test-case",
- "tokio",
-]
-
-[[package]]
-name = "spl-slashing"
-version = "0.1.0"
-dependencies = [
- "bincode",
- "bitflags 2.6.0",
- "bytemuck",
- "generic-array 0.14.7",
- "lazy_static",
- "num-derive",
- "num-traits",
- "num_enum",
- "rand 0.8.5",
- "serde",
- "serde_bytes",
- "serde_derive",
- "serde_with",
- "solana-client",
- "solana-entry",
- "solana-ledger",
- "solana-program",
- "solana-program-test",
- "solana-sdk",
- "spl-pod 0.5.0",
- "spl-record",
- "thiserror 2.0.9",
-]
-
-[[package]]
-name = "spl-stake-pool"
-version = "2.0.1"
-dependencies = [
- "arrayref",
- "assert_matches",
- "bincode",
- "borsh 1.5.3",
- "bytemuck",
- "num-derive",
- "num-traits",
- "num_enum",
- "proptest",
- "serde",
- "serde_derive",
- "solana-program",
- "solana-program-test",
- "solana-sdk",
- "solana-security-txt",
- "solana-vote-program",
- "spl-pod 0.5.0",
- "spl-token 7.0.0",
- "spl-token-2022 6.0.0",
- "test-case",
- "thiserror 2.0.9",
-]
-
-[[package]]
-name = "spl-stake-pool-cli"
-version = "2.0.0"
-dependencies = [
- "bincode",
- "borsh 1.5.3",
- "bs58",
- "clap 2.34.0",
- "serde",
- "serde_derive",
- "serde_json",
- "solana-account-decoder",
- "solana-clap-utils",
- "solana-cli-config",
- "solana-cli-output",
- "solana-client",
- "solana-logger",
- "solana-program",
- "solana-remote-wallet",
- "solana-sdk",
- "spl-associated-token-account 6.0.0",
- "spl-associated-token-account-client",
- "spl-stake-pool",
- "spl-token 7.0.0",
-]
-
[[package]]
name = "spl-tlv-account-resolution"
version = "0.7.0"
@@ -8469,27 +7999,23 @@ dependencies = [
[[package]]
name = "spl-tlv-account-resolution"
version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd99ff1e9ed2ab86e3fd582850d47a739fec1be9f4661cba1782d3a0f26805f3"
dependencies = [
"bytemuck",
- "futures 0.3.31",
- "futures-util",
"num-derive",
"num-traits",
- "serde",
"solana-account-info",
- "solana-client",
"solana-decode-error",
"solana-instruction",
"solana-msg",
"solana-program-error",
- "solana-program-test",
"solana-pubkey",
- "solana-sdk",
- "spl-discriminator 0.4.0",
+ "spl-discriminator 0.4.1",
"spl-pod 0.5.0",
"spl-program-error 0.6.0",
"spl-type-length-value 0.7.0",
- "thiserror 2.0.9",
+ "thiserror 1.0.69",
]
[[package]]
@@ -8510,19 +8036,16 @@ dependencies = [
[[package]]
name = "spl-token"
version = "7.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed320a6c934128d4f7e54fe00e16b8aeaecf215799d060ae14f93378da6dc834"
dependencies = [
"arrayref",
"bytemuck",
- "lazy_static",
"num-derive",
"num-traits",
"num_enum",
- "proptest",
- "serial_test",
"solana-program",
- "solana-program-test",
- "solana-sdk",
- "thiserror 2.0.9",
+ "thiserror 1.0.69",
]
[[package]]
@@ -8552,28 +8075,20 @@ dependencies = [
[[package]]
name = "spl-token-2022"
version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b27f7405010ef816587c944536b0eafbcc35206ab6ba0f2ca79f1d28e488f4f"
dependencies = [
"arrayref",
- "base64 0.22.1",
"bytemuck",
- "lazy_static",
"num-derive",
"num-traits",
"num_enum",
- "proptest",
- "serde",
- "serde_json",
- "serde_with",
- "serial_test",
"solana-program",
- "solana-program-test",
- "solana-sdk",
"solana-security-txt",
"solana-zk-sdk",
"spl-elgamal-registry",
"spl-memo 6.0.0",
"spl-pod 0.5.0",
- "spl-tlv-account-resolution 0.9.0",
"spl-token 7.0.0",
"spl-token-confidential-transfer-ciphertext-arithmetic",
"spl-token-confidential-transfer-proof-extraction",
@@ -8582,81 +8097,14 @@ dependencies = [
"spl-token-metadata-interface 0.6.0",
"spl-transfer-hook-interface 0.9.0",
"spl-type-length-value 0.7.0",
- "thiserror 2.0.9",
-]
-
-[[package]]
-name = "spl-token-2022-test"
-version = "0.0.1"
-dependencies = [
- "async-trait",
- "borsh 1.5.3",
- "bytemuck",
- "futures-util",
- "solana-program",
- "solana-program-test",
- "solana-sdk",
- "spl-associated-token-account 6.0.0",
- "spl-elgamal-registry",
- "spl-instruction-padding",
- "spl-memo 6.0.0",
- "spl-pod 0.5.0",
- "spl-record",
- "spl-tlv-account-resolution 0.9.0",
- "spl-token-2022 6.0.0",
- "spl-token-client",
- "spl-token-confidential-transfer-proof-extraction",
- "spl-token-confidential-transfer-proof-generation",
- "spl-token-group-interface 0.5.0",
- "spl-token-metadata-interface 0.6.0",
- "spl-transfer-hook-example",
- "spl-transfer-hook-interface 0.9.0",
- "test-case",
- "walkdir",
-]
-
-[[package]]
-name = "spl-token-cli"
-version = "5.0.0"
-dependencies = [
- "assert_cmd",
- "base64 0.22.1",
- "clap 3.2.25",
- "console",
- "futures 0.3.31",
- "libtest-mimic",
- "serde",
- "serde_derive",
- "serde_json",
- "serial_test",
- "solana-account-decoder",
- "solana-clap-v3-utils",
- "solana-cli-config",
- "solana-cli-output",
- "solana-client",
- "solana-logger",
- "solana-remote-wallet",
- "solana-sdk",
- "solana-test-validator",
- "solana-transaction-status",
- "spl-associated-token-account-client",
- "spl-memo 6.0.0",
- "spl-token 7.0.0",
- "spl-token-2022 6.0.0",
- "spl-token-client",
- "spl-token-confidential-transfer-proof-generation",
- "spl-token-group-interface 0.5.0",
- "spl-token-metadata-interface 0.6.0",
- "strum 0.26.3",
- "strum_macros 0.26.4",
- "tempfile",
- "tokio",
- "walkdir",
+ "thiserror 1.0.69",
]
[[package]]
name = "spl-token-client"
version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9155237581388a928822ce91caf936cf54406d27bf21def44f18b25e304ba0e"
dependencies = [
"async-trait",
"bincode",
@@ -8680,85 +8128,44 @@ dependencies = [
"spl-token-group-interface 0.5.0",
"spl-token-metadata-interface 0.6.0",
"spl-transfer-hook-interface 0.9.0",
- "thiserror 2.0.9",
-]
-
-[[package]]
-name = "spl-token-collection"
-version = "0.1.0"
-dependencies = [
- "solana-program",
- "solana-program-test",
- "solana-sdk",
- "spl-discriminator 0.4.0",
- "spl-pod 0.5.0",
- "spl-program-error 0.6.0",
- "spl-token-2022 6.0.0",
- "spl-token-client",
- "spl-token-group-example",
- "spl-token-group-interface 0.5.0",
- "spl-token-metadata-interface 0.6.0",
- "spl-type-length-value 0.7.0",
+ "thiserror 1.0.69",
]
[[package]]
name = "spl-token-confidential-transfer-ciphertext-arithmetic"
version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1f1bf731fc65546330a7929a9735679add70f828dd076a4e69b59d3afb5423c"
dependencies = [
"base64 0.22.1",
"bytemuck",
- "curve25519-dalek 4.1.3",
"solana-curve25519",
"solana-zk-sdk",
- "spl-token-confidential-transfer-proof-generation",
]
[[package]]
name = "spl-token-confidential-transfer-proof-extraction"
version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "383937e637ccbe546f736d5115344351ebd4d2a076907582335261da58236816"
dependencies = [
"bytemuck",
"solana-curve25519",
"solana-program",
"solana-zk-sdk",
"spl-pod 0.5.0",
- "thiserror 2.0.9",
+ "thiserror 1.0.69",
]
[[package]]
name = "spl-token-confidential-transfer-proof-generation"
version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8627184782eec1894de8ea26129c61303f1f0adeed65c20e0b10bc584f09356d"
dependencies = [
"curve25519-dalek 4.1.3",
"solana-zk-sdk",
- "thiserror 2.0.9",
-]
-
-[[package]]
-name = "spl-token-confidential-transfer-proof-test"
-version = "0.0.1"
-dependencies = [
- "curve25519-dalek 4.1.3",
- "solana-zk-sdk",
- "spl-token-confidential-transfer-proof-extraction",
- "spl-token-confidential-transfer-proof-generation",
- "thiserror 2.0.9",
-]
-
-[[package]]
-name = "spl-token-group-example"
-version = "0.2.1"
-dependencies = [
- "solana-program",
- "solana-program-test",
- "solana-sdk",
- "spl-discriminator 0.4.0",
- "spl-pod 0.5.0",
- "spl-token-2022 6.0.0",
- "spl-token-client",
- "spl-token-group-interface 0.5.0",
- "spl-token-metadata-interface 0.6.0",
- "spl-type-length-value 0.7.0",
+ "thiserror 1.0.69",
]
[[package]]
@@ -8777,6 +8184,8 @@ dependencies = [
[[package]]
name = "spl-token-group-interface"
version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d595667ed72dbfed8c251708f406d7c2814a3fa6879893b323d56a10bedfc799"
dependencies = [
"bytemuck",
"num-derive",
@@ -8786,11 +8195,9 @@ dependencies = [
"solana-msg",
"solana-program-error",
"solana-pubkey",
- "solana-sha256-hasher",
- "spl-discriminator 0.4.0",
+ "spl-discriminator 0.4.1",
"spl-pod 0.5.0",
- "spl-type-length-value 0.7.0",
- "thiserror 2.0.9",
+ "thiserror 1.0.69",
]
[[package]]
@@ -8826,21 +8233,6 @@ dependencies = [
"spl-token-lending",
]
-[[package]]
-name = "spl-token-metadata-example"
-version = "0.3.0"
-dependencies = [
- "solana-program",
- "solana-program-test",
- "solana-sdk",
- "spl-pod 0.5.0",
- "spl-token-2022 6.0.0",
- "spl-token-client",
- "spl-token-metadata-interface 0.6.0",
- "spl-type-length-value 0.7.0",
- "test-case",
-]
-
[[package]]
name = "spl-token-metadata-interface"
version = "0.4.0"
@@ -8858,23 +8250,22 @@ dependencies = [
[[package]]
name = "spl-token-metadata-interface"
version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfb9c89dbc877abd735f05547dcf9e6e12c00c11d6d74d8817506cab4c99fdbb"
dependencies = [
"borsh 1.5.3",
"num-derive",
"num-traits",
- "serde",
- "serde_json",
"solana-borsh",
"solana-decode-error",
"solana-instruction",
"solana-msg",
"solana-program-error",
"solana-pubkey",
- "solana-sha256-hasher",
- "spl-discriminator 0.4.0",
+ "spl-discriminator 0.4.1",
"spl-pod 0.5.0",
"spl-type-length-value 0.7.0",
- "thiserror 2.0.9",
+ "thiserror 1.0.69",
]
[[package]]
@@ -8961,98 +8352,6 @@ dependencies = [
"thiserror 2.0.9",
]
-[[package]]
-name = "spl-transfer-hook-cli"
-version = "0.2.0"
-dependencies = [
- "clap 3.2.25",
- "futures-util",
- "serde",
- "serde_json",
- "serde_yaml",
- "solana-clap-v3-utils",
- "solana-cli-config",
- "solana-client",
- "solana-logger",
- "solana-remote-wallet",
- "solana-sdk",
- "solana-test-validator",
- "spl-tlv-account-resolution 0.9.0",
- "spl-token-2022 6.0.0",
- "spl-token-client",
- "spl-transfer-hook-example",
- "spl-transfer-hook-interface 0.9.0",
- "strum 0.26.3",
- "strum_macros 0.26.4",
- "tokio",
-]
-
-[[package]]
-name = "spl-transfer-hook-example"
-version = "0.6.0"
-dependencies = [
- "arrayref",
- "solana-program",
- "solana-program-test",
- "solana-sdk",
- "spl-tlv-account-resolution 0.9.0",
- "spl-token-2022 6.0.0",
- "spl-transfer-hook-interface 0.9.0",
- "spl-type-length-value 0.7.0",
-]
-
-[[package]]
-name = "spl-transfer-hook-example-downgrade"
-version = "1.0.0"
-dependencies = [
- "solana-account-info",
- "solana-program-entrypoint",
- "solana-program-error",
- "solana-pubkey",
-]
-
-[[package]]
-name = "spl-transfer-hook-example-fail"
-version = "1.0.0"
-dependencies = [
- "solana-account-info",
- "solana-program-entrypoint",
- "solana-program-error",
- "solana-pubkey",
-]
-
-[[package]]
-name = "spl-transfer-hook-example-success"
-version = "1.0.0"
-dependencies = [
- "solana-account-info",
- "solana-program-entrypoint",
- "solana-program-error",
- "solana-pubkey",
-]
-
-[[package]]
-name = "spl-transfer-hook-example-swap"
-version = "1.0.0"
-dependencies = [
- "solana-account-info",
- "solana-program-entrypoint",
- "solana-program-error",
- "solana-pubkey",
- "spl-token-2022 6.0.0",
-]
-
-[[package]]
-name = "spl-transfer-hook-example-swap-with-fee"
-version = "1.0.0"
-dependencies = [
- "solana-account-info",
- "solana-program-entrypoint",
- "solana-program-error",
- "solana-pubkey",
- "spl-token-2022 6.0.0",
-]
-
[[package]]
name = "spl-transfer-hook-interface"
version = "0.7.0"
@@ -9072,6 +8371,8 @@ dependencies = [
[[package]]
name = "spl-transfer-hook-interface"
version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4aa7503d52107c33c88e845e1351565050362c2314036ddf19a36cd25137c043"
dependencies = [
"arrayref",
"bytemuck",
@@ -9082,16 +8383,14 @@ dependencies = [
"solana-decode-error",
"solana-instruction",
"solana-msg",
- "solana-program",
"solana-program-error",
"solana-pubkey",
- "spl-discriminator 0.4.0",
+ "spl-discriminator 0.4.1",
"spl-pod 0.5.0",
"spl-program-error 0.6.0",
"spl-tlv-account-resolution 0.9.0",
"spl-type-length-value 0.7.0",
- "thiserror 2.0.9",
- "tokio",
+ "thiserror 1.0.69",
]
[[package]]
@@ -9110,6 +8409,8 @@ dependencies = [
[[package]]
name = "spl-type-length-value"
version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba70ef09b13af616a4c987797870122863cba03acc4284f226a4473b043923f9"
dependencies = [
"bytemuck",
"num-derive",
@@ -9118,29 +8419,9 @@ dependencies = [
"solana-decode-error",
"solana-msg",
"solana-program-error",
- "spl-discriminator 0.4.0",
+ "spl-discriminator 0.4.1",
"spl-pod 0.5.0",
- "spl-type-length-value-derive",
- "thiserror 2.0.9",
-]
-
-[[package]]
-name = "spl-type-length-value-derive"
-version = "0.1.0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.87",
-]
-
-[[package]]
-name = "spl-type-length-value-derive-test"
-version = "0.1.0"
-dependencies = [
- "borsh 1.5.3",
- "solana-borsh",
- "spl-discriminator 0.4.0",
- "spl-type-length-value 0.7.0",
+ "thiserror 1.0.69",
]
[[package]]
@@ -9191,15 +8472,9 @@ version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
dependencies = [
- "strum_macros 0.24.3",
+ "strum_macros",
]
-[[package]]
-name = "strum"
-version = "0.26.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
-
[[package]]
name = "strum_macros"
version = "0.24.3"
@@ -9213,19 +8488,6 @@ dependencies = [
"syn 1.0.107",
]
-[[package]]
-name = "strum_macros"
-version = "0.26.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
-dependencies = [
- "heck 0.5.0",
- "proc-macro2",
- "quote",
- "rustversion",
- "syn 2.0.87",
-]
-
[[package]]
name = "subtle"
version = "2.6.1"
@@ -10061,12 +9323,6 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
-[[package]]
-name = "utf8parse"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
-
[[package]]
name = "valuable"
version = "0.1.0"
diff --git a/Cargo.toml b/Cargo.toml
index 5b93b9a2544..ef88ac61895 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,9 +13,6 @@ opt-level = 3
[workspace]
members = [
- "associated-token-account/client",
- "associated-token-account/program",
- "associated-token-account/program-test",
"binary-option/program",
"binary-oracle-pair/program",
"examples/rust/cross-program-invocation",
@@ -24,68 +21,31 @@ members = [
"examples/rust/sysvar",
"examples/rust/transfer-lamports",
"examples/rust/transfer-tokens",
- "feature-proposal/program",
- "feature-proposal/cli",
"governance/addin-mock/program",
"governance/addin-api",
"governance/program",
"governance/test-sdk",
"governance/tools",
"governance/chat/program",
- "instruction-padding/program",
- "libraries/discriminator",
"libraries/concurrent-merkle-tree",
"libraries/math",
"libraries/math-example",
"libraries/merkle-tree-reference",
- "libraries/pod",
- "libraries/program-error",
- "libraries/tlv-account-resolution",
- "libraries/type-length-value",
- "libraries/type-length-value-derive-test",
"name-service/program",
"managed-token/program",
- "record/program",
"shared-memory/program",
- "single-pool/cli",
- "single-pool/program",
- "slashing/program",
- "stake-pool/cli",
- "stake-pool/program",
"stateless-asks/program",
- "token-collection/program",
- "token-group/example",
- "token-group/interface",
+ #"token-collection/program",
"token-lending/cli",
+ "token-lending/flash_loan_receiver",
"token-lending/program",
- "token-metadata/example",
- "token-metadata/interface",
"token-swap/program",
"token-swap/program/fuzz",
"token-upgrade/cli",
"token-upgrade/program",
"token-wrap/program",
- "token/cli",
- "token/program",
- "token/program-2022",
- "token/program-2022-test",
- "token/program-2022-test/transfer-hook-test-programs/downgrade",
- "token/program-2022-test/transfer-hook-test-programs/fail",
- "token/program-2022-test/transfer-hook-test-programs/success",
- "token/program-2022-test/transfer-hook-test-programs/swap",
- "token/program-2022-test/transfer-hook-test-programs/swap-with-fee",
- "token/transfer-hook/cli",
- "token/transfer-hook/example",
- "token/transfer-hook/interface",
- "token/confidential-transfer/ciphertext-arithmetic",
- "token/confidential-transfer/proof-extraction",
- "token/confidential-transfer/proof-generation",
- "token/confidential-transfer/proof-tests",
- "token/confidential-transfer/elgamal-registry",
- "token/client",
"utils/cgen",
"utils/test-client",
- "token-lending/flash_loan_receiver",
]
exclude = [
diff --git a/README.md b/README.md
index 2a88a26c616..e98b524760b 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,31 @@
+# PLEASE READ: This repo no longer contains the SPL program implementations
+
+This repo still exists in archived form, feel free to fork any reference
+implementations it still contains.
+
+## Migrated Packages
+
+The Solana Program Library repository has been broken up into separate repos for
+each program and set of clients, under the
+[solana-program organization](https://github.com/solana-program).
+
+The following programs have been moved:
+
+* [Associated-Token-Account](https://github.com/solana-program/associated-token-account)
+* [Feature Proposal](https://github.com/solana-program/feature-proposal)
+* [Instruction Padding](https://github.com/solana-program/instruction-padding)
+* [Libraries](https://github.com/solana-program/libraries)
+* [Memo](https://github.com/solana-program/memo)
+* [Record](https://github.com/solana-program/record)
+* [Single Pool](https://github.com/solana-program/single-pool)
+* [Slashing](https://github.com/solana-program/slashing)
+* [Stake Pool](https://github.com/solana-program/stake-pool)
+* [Token](https://github.com/solana-program/token)
+* [Token-2022](https://github.com/solana-program/token-2022)
+* [Token-Group](https://github.com/solana-program/token-group)
+* [Token-Metadata](https://github.com/solana-program/token-metadata)
+* [Token-2022 Transfer Hook](https://github.com/solana-program/transfer-hook)
+
# Solana Program Library
The Solana Program Library (SPL) is a collection of on-chain programs targeting
@@ -17,22 +45,17 @@ the Solana Mainnet Beta. Currently, this includes:
| Program | Version |
| --- | --- |
-| [token](https://github.com/solana-labs/solana-program-library/tree/master/token/program) | [3.4.0](https://github.com/solana-labs/solana-program-library/releases/tag/token-v3.4.0) |
-| [associated-token-account](https://github.com/solana-labs/solana-program-library/tree/master/associated-token-account/program) | [1.1.0](https://github.com/solana-labs/solana-program-library/releases/tag/associated-token-account-v1.1.0) |
-| [token-2022](https://github.com/solana-labs/solana-program-library/tree/master/token/program-2022) | [1.0.0](https://github.com/solana-labs/solana-program-library/releases/tag/token-2022-v1.0.0) |
+| [token](https://github.com/solana-program/token/tree/main/program) | [3.4.0](https://github.com/solana-labs/solana-program-library/releases/tag/token-v3.4.0) |
+| [associated-token-account](https://github.com/solana-program/associated-token-account/tree/main/program) | [1.1.0](https://github.com/solana-labs/solana-program-library/releases/tag/associated-token-account-v1.1.0) |
+| [token-2022](https://github.com/solana-program/token-2022/tree/main/program) | [1.0.0](https://github.com/solana-labs/solana-program-library/releases/tag/token-2022-v1.0.0) |
| [governance](https://github.com/solana-labs/solana-program-library/tree/master/governance/program) | [3.1.0](https://github.com/solana-labs/solana-program-library/releases/tag/governance-v3.1.0) |
-| [stake-pool](https://github.com/solana-labs/solana-program-library/tree/master/stake-pool/program) | [1.0.0](https://github.com/solana-labs/solana-program-library/releases/tag/stake-pool-v1.0.0) |
+| [stake-pool](https://github.com/solana-program/stake-pool/tree/main/program) | [1.0.0](https://github.com/solana-labs/solana-program-library/releases/tag/stake-pool-v1.0.0) |
| [account-compression](https://github.com/solana-labs/solana-program-library/tree/master/account-compression/programs/account-compression) | [0.1.3](https://github.com/solana-labs/solana-program-library/releases/tag/account-compression-v0.1.3) |
| [shared-memory](https://github.com/solana-labs/solana-program-library/tree/master/shared-memory/program) | [1.0.0](https://github.com/solana-labs/solana-program-library/commit/b40e0dd3fd6c0e509dc1e8dd3da0a6d609035bbd) |
-| [feature-proposal](https://github.com/solana-labs/solana-program-library/tree/master/feature-proposal/program) | [1.0.0](https://github.com/solana-labs/solana-program-library/releases/tag/feature-proposal-v1.0.0) |
+| [feature-proposal](https://github.com/solana-program/feature-proposal/tree/main/program) | [1.0.0](https://github.com/solana-labs/solana-program-library/releases/tag/feature-proposal-v1.0.0) |
| [name-service](https://github.com/solana-labs/solana-program-library/tree/master/name-service/program) | [0.3.0](https://github.com/solana-labs/solana-program-library/releases/tag/name-service-v0.3.0) |
-| [memo](https://github.com/solana-program/memo/tree/master/program) | [3.0.0](https://github.com/solana-labs/solana-program-library/releases/tag/memo-v3.0.0) |
-
-In addition, one program is planned for deployment to Solana Mainnet Beta:
-
-| Program | Version |
-| --- | --- |
-| [single-pool](https://github.com/solana-labs/solana-program-library/tree/master/single-pool/program) | [1.0.1](https://github.com/solana-labs/solana-program-library/releases/tag/single-pool-v1.0.1) |
+| [memo](https://github.com/solana-program/memo/tree/main/program) | [3.0.0](https://github.com/solana-labs/solana-program-library/releases/tag/memo-v3.0.0) |
+| [single-pool](https://github.com/solana-program/single-pool/tree/main/program) | [1.0.1](https://github.com/solana-labs/solana-program-library/releases/tag/single-pool-v1.0.1) |
## Audits
@@ -40,13 +63,13 @@ Only a subset of programs within the Solana Program Library repo are audited. Cu
| Program | Last Audit Date | Version |
| --- | --- | --- |
-| [token](https://github.com/solana-labs/solana-program-library/tree/master/token/program) | 2022-08-04 (Peer review) | [4fadd55](https://github.com/solana-labs/solana-program-library/commit/4fadd553e1c549afd1d62aeb5ffa7ef31d1999d1) |
-| [associated-token-account](https://github.com/solana-labs/solana-program-library/tree/master/associated-token-account/program) | 2022-08-04 (Peer review) | [c00194d](https://github.com/solana-labs/solana-program-library/commit/c00194d2257302f028f44a403c6dee95c0f9c3bc) |
-| [token-2022](https://github.com/solana-labs/solana-program-library/tree/master/token/program-2022) | [2023-11-03](https://github.com/solana-labs/security-audits/blob/master/spl/OtterSecToken2022Audit-2023-11-03.pdf) | [e924132](https://github.com/solana-labs/solana-program-library/tree/e924132d65ba0896249fb4983f6f97caff15721a) |
-| [stake-pool](https://github.com/solana-labs/solana-program-library/tree/master/stake-pool/program) | [2023-12-31](https://github.com/solana-labs/security-audits/blob/master/spl/HalbornStakePoolAudit-2023-12-31.pdf) | [a17fffe](https://github.com/solana-labs/solana-program-library/commit/a17fffe70d6cc13742abfbc4a4a375b087580bc1) |
+| [token](https://github.com/solana-program/token) | 2022-08-04 (Peer review) | [4fadd55](https://github.com/solana-labs/solana-program-library/commit/4fadd553e1c549afd1d62aeb5ffa7ef31d1999d1) |
+| [associated-token-account](https://github.com/solana-program/associated-token-account) | 2022-08-04 (Peer review) | [c00194d](https://github.com/solana-labs/solana-program-library/commit/c00194d2257302f028f44a403c6dee95c0f9c3bc) |
+| [token-2022](https://github.com/solana-program/token-2022) | [2023-11-03](https://github.com/solana-labs/security-audits/blob/master/spl/OtterSecToken2022Audit-2023-11-03.pdf) | [e924132](https://github.com/solana-labs/solana-program-library/tree/e924132d65ba0896249fb4983f6f97caff15721a) |
+| [stake-pool](https://github.com/solana-program/stake-pool) | [2023-12-31](https://github.com/solana-labs/security-audits/blob/master/spl/HalbornStakePoolAudit-2023-12-31.pdf) | [a17fffe](https://github.com/solana-labs/solana-program-library/commit/a17fffe70d6cc13742abfbc4a4a375b087580bc1) |
| [account-compression](https://github.com/solana-labs/solana-program-library/tree/master/account-compression/programs/account-compression) | [2022-12-05](https://github.com/solana-labs/security-audits/blob/master/spl/OtterSecAccountCompressionAudit-2022-12-03.pdf) | [6e81794](https://github.com/solana-labs/solana-program-library/commit/6e81794) |
| [shared-memory](https://github.com/solana-labs/solana-program-library/tree/master/shared-memory/program) | [2021-02-25](https://github.com/solana-labs/security-audits/blob/master/spl/KudelskiTokenSwapSharedMemAudit-2021-02-25.pdf) | [b40e0dd](https://github.com/solana-labs/solana-program-library/commit/b40e0dd3fd6c0e509dc1e8dd3da0a6d609035bbd) |
-| [single-pool](https://github.com/solana-labs/solana-program-library/tree/master/single-pool/program) | [2024-01-02](https://github.com/solana-labs/security-audits/blob/master/spl/ZellicSinglePoolAudit-2024-01-02.pdf) | [ef44df9](https://github.com/solana-labs/solana-program-library/commit/ef44df985e76a697ee9a8aabb3a223610e4cf1dc) |
+| [single-pool](https://github.com/solana-program/single-pool) | [2024-01-02](https://github.com/solana-labs/security-audits/blob/master/spl/ZellicSinglePoolAudit-2024-01-02.pdf) | [ef44df9](https://github.com/solana-labs/solana-program-library/commit/ef44df985e76a697ee9a8aabb3a223610e4cf1dc) |
All other programs may be updated from time to time. These programs are not
audited, so fork and deploy them at your own risk. Here is the full list of
@@ -54,11 +77,11 @@ unaudited programs:
* [binary-option](https://github.com/solana-labs/solana-program-library/tree/master/binary-option/program)
* [binary-oracle-pair](https://github.com/solana-labs/solana-program-library/tree/master/binary-oracle-pair/program)
-* [feature-proposal](https://github.com/solana-labs/solana-program-library/tree/master/feature-proposal/program)
-* [instruction-padding](https://github.com/solana-labs/solana-program-library/tree/master/instruction-padding/program)
+* [feature-proposal](https://github.com/solana-program/feature-proposal)
+* [instruction-padding](https://github.com/solana-program/instruction-padding)
* [managed-token](https://github.com/solana-labs/solana-program-library/tree/master/managed-token/program)
* [name-service](https://github.com/solana-labs/solana-program-library/tree/master/name-service/program)
-* [record](https://github.com/solana-labs/solana-program-library/tree/master/record/program)
+* [record](https://github.com/solana-program/record)
* [stateless-asks](https://github.com/solana-labs/solana-program-library/tree/master/stateless-asks/program)
* [token-lending](https://github.com/solana-labs/solana-program-library/tree/master/token-lending/program)
* [token-swap](https://github.com/solana-labs/solana-program-library/tree/master/token-swap/program)
@@ -70,13 +93,6 @@ More information about the repository's security policy at
The [security-audits repo](https://github.com/solana-labs/security-audits) contains
all past and present program audits.
-## Migrated Packages
-
-The Solana Program Library repository is being broken up into separate repos for
-each program and set of clients. The following programs have been moved:
-
-* [Memo](https://github.com/solana-program/memo)
-
## Program Packages
| Package | Description | Version | Docs |
diff --git a/SECURITY.md b/SECURITY.md
index 91e69bcda73..57d453670fd 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -1,73 +1,13 @@
-# Security Policy
-
-1. [Reporting security problems](#reporting)
-1. [Security Bug Bounties](#bounty)
-1. [Scope](#scope)
-1. [Incident Response Process](#process)
-
-
-## Reporting security problems in the Solana Program Library
-
-**DO NOT CREATE A GITHUB ISSUE** to report a security problem.
-
-Instead please use this [Report a Vulnerability](https://github.com/solana-labs/solana-program-library/security/advisories/new) link.
-Provide a helpful title and detailed description of the problem.
-
-If you haven't done so already, please **enable two-factor auth** in your GitHub account.
-
-Expect a response as fast as possible in the advisory, typically within 72 hours.
-
---
-
-If you do not receive a response in the advisory, send an email to
-security@solana.com with the full URL of the advisory you have created. DO NOT
-include attachments or provide detail sufficient for exploitation regarding the
-security issue in this email. **Only provide such details in the advisory**.
-
-If you do not receive a response from security@solana.com please followup with
-the team directly. You can do this in the `#core-technology` channel of the
-[Solana Tech discord server](https://solana.com/discord), by pinging the admins
-in the channel and referencing the fact that you submitted a security problem.
-
-
-
-
-## Security Bug Bounties
-The Solana Foundation offer bounties for critical Solana security issues. Please
-see the [Solana Security Bug
-Bounties](https://github.com/solana-labs/solana/security/policy#security-bug-bounties)
-for details on classes of bugs and payment amounts.
-
-
-## Scope
-
-Only a subset of programs within the Solana Program Library repo are deployed to
-the Solana Mainnet Beta. Currently, this includes:
-
-* [associated-token-account](https://github.com/solana-labs/solana-program-library/tree/master/associated-token-account/program)
-* [feature-proposal](https://github.com/solana-labs/solana-program-library/tree/master/feature-proposal/program)
-* [governance](https://github.com/solana-labs/solana-program-library/tree/master/governance/program)
-* [memo](https://github.com/solana-program/memo)
-* [name-service](https://github.com/solana-labs/solana-program-library/tree/master/name-service/program)
-* [stake-pool](https://github.com/solana-labs/solana-program-library/tree/master/stake-pool/program)
-* [token](https://github.com/solana-labs/solana-program-library/tree/master/token/program)
-* [token-2022](https://github.com/solana-labs/solana-program-library/tree/master/token/program-2022)
-
-If you discover a critical security issue in an out-of-scope program, your finding
-may still be valuable.
-
-Many programs, including
-[token-swap](https://github.com/solana-labs/solana-program-library/tree/master/token-swap/program)
-and [token-lending](https://github.com/solana-labs/solana-program-library/tree/master/token-lending/program),
-have been forked and deployed by prominent ecosystem projects, many of which
-have their own bug bounty programs.
-
-While we cannot guarantee a bounty from another entity, we can help determine who
-may be affected and put you in touch with the corresponding teams.
-
-
-## Incident Response Process
-
-In case an incident is discovered or reported, the
-[Solana Security Incident Response Process](https://github.com/solana-labs/solana/security/policy#incident-response-process)
-will be followed to contain, respond and remediate.
+## This repo will be archived soon
+Active development in this repo is ending 2024-03-02. Anza is continuing development
+in program-specific repos under the
+[solana-program organization](https://github.com/solana-program). Please refer to
+the security policy in individual repos:
+
+* [associated-token-account](https://github.com/solana-program/associated-token-account/security)
+* [feature-proposal](https://github.com/solana-program/feature-proposal/security)
+* [memo](https://github.com/solana-program/memo/security)
+* [single-pool](https://github.com/solana-program/single-pool/security)
+* [stake-pool](https://github.com/solana-program/stake-pool/security)
+* [token](https://github.com/solana-program/token/security)
+* [token-2022](https://github.com/solana-program/token-2022/security)
diff --git a/associated-token-account/README.md b/associated-token-account/README.md
new file mode 100644
index 00000000000..5ed8fdcbbe1
--- /dev/null
+++ b/associated-token-account/README.md
@@ -0,0 +1,2 @@
+NOTE: The associated-token-account program and clients are now maintained at
+[solana-program/associated-token-account](https://github.com/solana-program/associated-token-account).
diff --git a/associated-token-account/client/Cargo.toml b/associated-token-account/client/Cargo.toml
deleted file mode 100644
index 7a52979693f..00000000000
--- a/associated-token-account/client/Cargo.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[package]
-name = "spl-associated-token-account-client"
-version = "2.0.0"
-description = "Solana Program Library Associated Token Account Client"
-authors = ["Solana Labs Maintainers "]
-repository = "https://github.com/solana-labs/solana-program-library"
-license = "Apache-2.0"
-edition = "2021"
-
-[dependencies]
-solana-instruction = { version = "2.1.0", features = ["std"] }
-solana-pubkey = { version = "2.1.0", features = ["curve25519"] }
-
-[dev-dependencies]
-solana-program = "2.1.0"
-
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu"]
diff --git a/associated-token-account/client/src/address.rs b/associated-token-account/client/src/address.rs
deleted file mode 100644
index 6a608299600..00000000000
--- a/associated-token-account/client/src/address.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-//! Address derivation functions
-
-use solana_pubkey::Pubkey;
-
-/// Derives the associated token account address and bump seed
-/// for the given wallet address, token mint and token program id
-pub fn get_associated_token_address_and_bump_seed(
- wallet_address: &Pubkey,
- token_mint_address: &Pubkey,
- program_id: &Pubkey,
- token_program_id: &Pubkey,
-) -> (Pubkey, u8) {
- get_associated_token_address_and_bump_seed_internal(
- wallet_address,
- token_mint_address,
- program_id,
- token_program_id,
- )
-}
-
-mod inline_spl_token {
- solana_pubkey::declare_id!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
-}
-
-/// Derives the associated token account address for the given wallet address
-/// and token mint
-pub fn get_associated_token_address(
- wallet_address: &Pubkey,
- token_mint_address: &Pubkey,
-) -> Pubkey {
- get_associated_token_address_with_program_id(
- wallet_address,
- token_mint_address,
- &inline_spl_token::ID,
- )
-}
-
-/// Derives the associated token account address for the given wallet address,
-/// token mint and token program id
-pub fn get_associated_token_address_with_program_id(
- wallet_address: &Pubkey,
- token_mint_address: &Pubkey,
- token_program_id: &Pubkey,
-) -> Pubkey {
- get_associated_token_address_and_bump_seed(
- wallet_address,
- token_mint_address,
- &crate::program::id(),
- token_program_id,
- )
- .0
-}
-
-/// For internal use only.
-#[doc(hidden)]
-pub fn get_associated_token_address_and_bump_seed_internal(
- wallet_address: &Pubkey,
- token_mint_address: &Pubkey,
- program_id: &Pubkey,
- token_program_id: &Pubkey,
-) -> (Pubkey, u8) {
- Pubkey::find_program_address(
- &[
- &wallet_address.to_bytes(),
- &token_program_id.to_bytes(),
- &token_mint_address.to_bytes(),
- ],
- program_id,
- )
-}
diff --git a/associated-token-account/client/src/instruction.rs b/associated-token-account/client/src/instruction.rs
deleted file mode 100644
index 4f000d619d0..00000000000
--- a/associated-token-account/client/src/instruction.rs
+++ /dev/null
@@ -1,116 +0,0 @@
-//! Instruction creators for the program
-use {
- crate::{address::get_associated_token_address_with_program_id, program::id},
- solana_instruction::{AccountMeta, Instruction},
- solana_pubkey::Pubkey,
-};
-
-const SYSTEM_PROGRAM_ID: Pubkey = Pubkey::from_str_const("11111111111111111111111111111111");
-
-fn build_associated_token_account_instruction(
- funding_address: &Pubkey,
- wallet_address: &Pubkey,
- token_mint_address: &Pubkey,
- token_program_id: &Pubkey,
- instruction: u8,
-) -> Instruction {
- let associated_account_address = get_associated_token_address_with_program_id(
- wallet_address,
- token_mint_address,
- token_program_id,
- );
- // safety check, assert if not a creation instruction, which is only 0 or 1
- assert!(instruction <= 1);
- Instruction {
- program_id: id(),
- accounts: vec![
- AccountMeta::new(*funding_address, true),
- AccountMeta::new(associated_account_address, false),
- AccountMeta::new_readonly(*wallet_address, false),
- AccountMeta::new_readonly(*token_mint_address, false),
- AccountMeta::new_readonly(SYSTEM_PROGRAM_ID, false),
- AccountMeta::new_readonly(*token_program_id, false),
- ],
- data: vec![instruction],
- }
-}
-
-/// Creates Create instruction
-pub fn create_associated_token_account(
- funding_address: &Pubkey,
- wallet_address: &Pubkey,
- token_mint_address: &Pubkey,
- token_program_id: &Pubkey,
-) -> Instruction {
- build_associated_token_account_instruction(
- funding_address,
- wallet_address,
- token_mint_address,
- token_program_id,
- 0, // AssociatedTokenAccountInstruction::Create
- )
-}
-
-/// Creates CreateIdempotent instruction
-pub fn create_associated_token_account_idempotent(
- funding_address: &Pubkey,
- wallet_address: &Pubkey,
- token_mint_address: &Pubkey,
- token_program_id: &Pubkey,
-) -> Instruction {
- build_associated_token_account_instruction(
- funding_address,
- wallet_address,
- token_mint_address,
- token_program_id,
- 1, // AssociatedTokenAccountInstruction::CreateIdempotent
- )
-}
-
-/// Creates a `RecoverNested` instruction
-pub fn recover_nested(
- wallet_address: &Pubkey,
- owner_token_mint_address: &Pubkey,
- nested_token_mint_address: &Pubkey,
- token_program_id: &Pubkey,
-) -> Instruction {
- let owner_associated_account_address = get_associated_token_address_with_program_id(
- wallet_address,
- owner_token_mint_address,
- token_program_id,
- );
- let destination_associated_account_address = get_associated_token_address_with_program_id(
- wallet_address,
- nested_token_mint_address,
- token_program_id,
- );
- let nested_associated_account_address = get_associated_token_address_with_program_id(
- &owner_associated_account_address, // ATA is wrongly used as a wallet_address
- nested_token_mint_address,
- token_program_id,
- );
-
- Instruction {
- program_id: id(),
- accounts: vec![
- AccountMeta::new(nested_associated_account_address, false),
- AccountMeta::new_readonly(*nested_token_mint_address, false),
- AccountMeta::new(destination_associated_account_address, false),
- AccountMeta::new_readonly(owner_associated_account_address, false),
- AccountMeta::new_readonly(*owner_token_mint_address, false),
- AccountMeta::new(*wallet_address, true),
- AccountMeta::new_readonly(*token_program_id, false),
- ],
- data: vec![2], // AssociatedTokenAccountInstruction::RecoverNested
- }
-}
-
-#[cfg(test)]
-mod tests {
- use {super::*, solana_program::system_program};
-
- #[test]
- fn system_program_id() {
- assert_eq!(system_program::id(), SYSTEM_PROGRAM_ID);
- }
-}
diff --git a/associated-token-account/client/src/lib.rs b/associated-token-account/client/src/lib.rs
deleted file mode 100644
index ef32c233b0a..00000000000
--- a/associated-token-account/client/src/lib.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//! Client crate for interacting with the spl-associated-token-account program
-#![deny(missing_docs)]
-#![forbid(unsafe_code)]
-
-pub mod address;
-pub mod instruction;
-
-/// Module defining the program id
-pub mod program {
- solana_pubkey::declare_id!("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL");
-}
diff --git a/associated-token-account/program-test/Cargo.toml b/associated-token-account/program-test/Cargo.toml
deleted file mode 100644
index e576eb3d654..00000000000
--- a/associated-token-account/program-test/Cargo.toml
+++ /dev/null
@@ -1,20 +0,0 @@
-[package]
-authors = ["Solana Labs Maintainers "]
-description = "SPL Associated Token Account Program Tests"
-edition = "2021"
-license = "Apache-2.0"
-name = "spl-associated-token-account-test"
-repository = "https://github.com/solana-labs/solana-program-library"
-version = "0.0.1"
-
-[features]
-test-sbf = []
-
-[dev-dependencies]
-solana-program = "2.1.0"
-solana-program-test = "2.1.0"
-solana-sdk = "2.1.0"
-spl-associated-token-account = { version = "6.0.0", path = "../program", features = ["no-entrypoint"] }
-spl-associated-token-account-client = { version = "2.0.0", path = "../client" }
-spl-token = { version = "7.0", path = "../../token/program", features = ["no-entrypoint"] }
-spl-token-2022 = { version = "6.0.0", path = "../../token/program-2022", features = ["no-entrypoint"] }
diff --git a/associated-token-account/program-test/tests/create_idempotent.rs b/associated-token-account/program-test/tests/create_idempotent.rs
deleted file mode 100644
index 673366ce14c..00000000000
--- a/associated-token-account/program-test/tests/create_idempotent.rs
+++ /dev/null
@@ -1,244 +0,0 @@
-#![cfg(feature = "test-sbf")]
-
-mod program_test;
-
-use {
- program_test::program_test_2022,
- solana_program::{instruction::*, pubkey::Pubkey},
- solana_program_test::*,
- solana_sdk::{
- account::Account as SolanaAccount,
- program_option::COption,
- program_pack::Pack,
- signature::Signer,
- signer::keypair::Keypair,
- system_instruction::create_account,
- transaction::{Transaction, TransactionError},
- },
- spl_associated_token_account::{
- error::AssociatedTokenAccountError,
- instruction::{
- create_associated_token_account, create_associated_token_account_idempotent,
- },
- },
- spl_associated_token_account_client::address::get_associated_token_address_with_program_id,
- spl_token_2022::{
- extension::ExtensionType,
- instruction::initialize_account,
- state::{Account, AccountState},
- },
-};
-
-#[tokio::test]
-async fn success_account_exists() {
- let wallet_address = Pubkey::new_unique();
- let token_mint_address = Pubkey::new_unique();
- let associated_token_address = get_associated_token_address_with_program_id(
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
-
- let (mut banks_client, payer, recent_blockhash) =
- program_test_2022(token_mint_address, true).start().await;
- let rent = banks_client.get_rent().await.unwrap();
- let expected_token_account_len =
- ExtensionType::try_calculate_account_len::(&[ExtensionType::ImmutableOwner])
- .unwrap();
- let expected_token_account_balance = rent.minimum_balance(expected_token_account_len);
-
- let instruction = create_associated_token_account_idempotent(
- &payer.pubkey(),
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
-
- let transaction = Transaction::new_signed_with_payer(
- &[instruction],
- Some(&payer.pubkey()),
- &[&payer],
- recent_blockhash,
- );
- banks_client.process_transaction(transaction).await.unwrap();
-
- // Associated account now exists
- let associated_account = banks_client
- .get_account(associated_token_address)
- .await
- .expect("get_account")
- .expect("associated_account not none");
- assert_eq!(associated_account.data.len(), expected_token_account_len);
- assert_eq!(associated_account.owner, spl_token_2022::id());
- assert_eq!(associated_account.lamports, expected_token_account_balance);
-
- // Unchecked instruction fails
- let instruction = create_associated_token_account(
- &payer.pubkey(),
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
-
- let transaction = Transaction::new_signed_with_payer(
- &[instruction],
- Some(&payer.pubkey()),
- &[&payer],
- recent_blockhash,
- );
- assert_eq!(
- banks_client
- .process_transaction(transaction)
- .await
- .unwrap_err()
- .unwrap(),
- TransactionError::InstructionError(0, InstructionError::IllegalOwner)
- );
-
- // Get a new blockhash, succeed with create if non existent
- let recent_blockhash = banks_client
- .get_new_latest_blockhash(&recent_blockhash)
- .await
- .unwrap();
-
- let instruction = create_associated_token_account_idempotent(
- &payer.pubkey(),
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
-
- let transaction = Transaction::new_signed_with_payer(
- &[instruction],
- Some(&payer.pubkey()),
- &[&payer],
- recent_blockhash,
- );
- banks_client.process_transaction(transaction).await.unwrap();
-
- // Associated account is unchanged
- let associated_account = banks_client
- .get_account(associated_token_address)
- .await
- .expect("get_account")
- .expect("associated_account not none");
- assert_eq!(associated_account.data.len(), expected_token_account_len);
- assert_eq!(associated_account.owner, spl_token_2022::id());
- assert_eq!(associated_account.lamports, expected_token_account_balance);
-}
-
-#[tokio::test]
-async fn fail_account_exists_with_wrong_owner() {
- let wallet_address = Pubkey::new_unique();
- let token_mint_address = Pubkey::new_unique();
- let associated_token_address = get_associated_token_address_with_program_id(
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
-
- let wrong_owner = Pubkey::new_unique();
- let mut associated_token_account =
- SolanaAccount::new(1_000_000_000, Account::LEN, &spl_token_2022::id());
- let token_account = Account {
- mint: token_mint_address,
- owner: wrong_owner,
- amount: 0,
- delegate: COption::None,
- state: AccountState::Initialized,
- is_native: COption::None,
- delegated_amount: 0,
- close_authority: COption::None,
- };
- Account::pack(token_account, &mut associated_token_account.data).unwrap();
- let mut pt = program_test_2022(token_mint_address, true);
- pt.add_account(associated_token_address, associated_token_account);
- let (banks_client, payer, recent_blockhash) = pt.start().await;
-
- // fail creating token account if non existent
- let instruction = create_associated_token_account_idempotent(
- &payer.pubkey(),
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
- let transaction = Transaction::new_signed_with_payer(
- &[instruction],
- Some(&payer.pubkey()),
- &[&payer],
- recent_blockhash,
- );
-
- assert_eq!(
- banks_client
- .process_transaction(transaction)
- .await
- .unwrap_err()
- .unwrap(),
- TransactionError::InstructionError(
- 0,
- InstructionError::Custom(AssociatedTokenAccountError::InvalidOwner as u32)
- )
- );
-}
-
-#[tokio::test]
-async fn fail_non_ata() {
- let token_mint_address = Pubkey::new_unique();
- let (banks_client, payer, recent_blockhash) =
- program_test_2022(token_mint_address, true).start().await;
-
- let rent = banks_client.get_rent().await.unwrap();
- let token_account_len =
- ExtensionType::try_calculate_account_len::(&[ExtensionType::ImmutableOwner])
- .unwrap();
- let token_account_balance = rent.minimum_balance(token_account_len);
-
- let wallet_address = Pubkey::new_unique();
- let account = Keypair::new();
- let transaction = Transaction::new_signed_with_payer(
- &[
- create_account(
- &payer.pubkey(),
- &account.pubkey(),
- token_account_balance,
- token_account_len as u64,
- &spl_token_2022::id(),
- ),
- initialize_account(
- &spl_token_2022::id(),
- &account.pubkey(),
- &token_mint_address,
- &wallet_address,
- )
- .unwrap(),
- ],
- Some(&payer.pubkey()),
- &[&payer, &account],
- recent_blockhash,
- );
- banks_client.process_transaction(transaction).await.unwrap();
-
- let mut instruction = create_associated_token_account_idempotent(
- &payer.pubkey(),
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
- instruction.accounts[1] = AccountMeta::new(account.pubkey(), false); // <-- Invalid associated_account_address
-
- let transaction = Transaction::new_signed_with_payer(
- &[instruction],
- Some(&payer.pubkey()),
- &[&payer],
- recent_blockhash,
- );
- assert_eq!(
- banks_client
- .process_transaction(transaction)
- .await
- .unwrap_err()
- .unwrap(),
- TransactionError::InstructionError(0, InstructionError::InvalidSeeds)
- );
-}
diff --git a/associated-token-account/program-test/tests/extended_mint.rs b/associated-token-account/program-test/tests/extended_mint.rs
deleted file mode 100644
index 1ee0b5513e5..00000000000
--- a/associated-token-account/program-test/tests/extended_mint.rs
+++ /dev/null
@@ -1,216 +0,0 @@
-// Mark this test as BPF-only due to current `ProgramTest` limitations when
-// CPIing into the system program
-#![cfg(feature = "test-sbf")]
-
-mod program_test;
-
-use {
- program_test::program_test_2022,
- solana_program::{instruction::*, pubkey::Pubkey, system_instruction},
- solana_program_test::*,
- solana_sdk::{
- signature::Signer,
- signer::keypair::Keypair,
- transaction::{Transaction, TransactionError},
- },
- spl_associated_token_account::instruction::create_associated_token_account,
- spl_associated_token_account_client::address::get_associated_token_address_with_program_id,
- spl_token_2022::{
- error::TokenError,
- extension::{
- transfer_fee, BaseStateWithExtensions, ExtensionType, StateWithExtensionsOwned,
- },
- state::{Account, Mint},
- },
-};
-
-#[tokio::test]
-async fn test_associated_token_account_with_transfer_fees() {
- let wallet_sender = Keypair::new();
- let wallet_address_sender = wallet_sender.pubkey();
- let wallet_address_receiver = Pubkey::new_unique();
- let (mut banks_client, payer, recent_blockhash) =
- program_test_2022(Pubkey::new_unique(), true).start().await;
- let rent = banks_client.get_rent().await.unwrap();
-
- // create extended mint
- // ... in the future, a mint can be pre-loaded in program_test.rs like the
- // regular mint
- let mint_account = Keypair::new();
- let token_mint_address = mint_account.pubkey();
- let mint_authority = Keypair::new();
- let space =
- ExtensionType::try_calculate_account_len::(&[ExtensionType::TransferFeeConfig])
- .unwrap();
- let maximum_fee = 100;
- let mut transaction = Transaction::new_with_payer(
- &[
- system_instruction::create_account(
- &payer.pubkey(),
- &mint_account.pubkey(),
- rent.minimum_balance(space),
- space as u64,
- &spl_token_2022::id(),
- ),
- transfer_fee::instruction::initialize_transfer_fee_config(
- &spl_token_2022::id(),
- &token_mint_address,
- Some(&mint_authority.pubkey()),
- Some(&mint_authority.pubkey()),
- 1_000,
- maximum_fee,
- )
- .unwrap(),
- spl_token_2022::instruction::initialize_mint(
- &spl_token_2022::id(),
- &token_mint_address,
- &mint_authority.pubkey(),
- Some(&mint_authority.pubkey()),
- 0,
- )
- .unwrap(),
- ],
- Some(&payer.pubkey()),
- );
- transaction.sign(&[&payer, &mint_account], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- // create extended ATAs
- let mut transaction = Transaction::new_with_payer(
- &[create_associated_token_account(
- &payer.pubkey(),
- &wallet_address_sender,
- &token_mint_address,
- &spl_token_2022::id(),
- )],
- Some(&payer.pubkey()),
- );
- transaction.sign(&[&payer], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- let recent_blockhash = banks_client
- .get_new_latest_blockhash(&recent_blockhash)
- .await
- .unwrap();
-
- let mut transaction = Transaction::new_with_payer(
- &[create_associated_token_account(
- &payer.pubkey(),
- &wallet_address_receiver,
- &token_mint_address,
- &spl_token_2022::id(),
- )],
- Some(&payer.pubkey()),
- );
- transaction.sign(&[&payer], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- let associated_token_address_sender = get_associated_token_address_with_program_id(
- &wallet_address_sender,
- &token_mint_address,
- &spl_token_2022::id(),
- );
- let associated_token_address_receiver = get_associated_token_address_with_program_id(
- &wallet_address_receiver,
- &token_mint_address,
- &spl_token_2022::id(),
- );
-
- // mint tokens
- let sender_amount = 50 * maximum_fee;
- let mut transaction = Transaction::new_with_payer(
- &[spl_token_2022::instruction::mint_to(
- &spl_token_2022::id(),
- &token_mint_address,
- &associated_token_address_sender,
- &mint_authority.pubkey(),
- &[],
- sender_amount,
- )
- .unwrap()],
- Some(&payer.pubkey()),
- );
- transaction.sign(&[&payer, &mint_authority], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- // not enough tokens
- let mut transaction = Transaction::new_with_payer(
- &[transfer_fee::instruction::transfer_checked_with_fee(
- &spl_token_2022::id(),
- &associated_token_address_sender,
- &token_mint_address,
- &associated_token_address_receiver,
- &wallet_address_sender,
- &[],
- 10_001,
- 0,
- maximum_fee,
- )
- .unwrap()],
- Some(&payer.pubkey()),
- );
- transaction.sign(&[&payer, &wallet_sender], recent_blockhash);
- let err = banks_client
- .process_transaction(transaction)
- .await
- .unwrap_err()
- .unwrap();
- assert_eq!(
- err,
- TransactionError::InstructionError(
- 0,
- InstructionError::Custom(TokenError::InsufficientFunds as u32)
- )
- );
-
- let recent_blockhash = banks_client
- .get_new_latest_blockhash(&recent_blockhash)
- .await
- .unwrap();
-
- // success
- let transfer_amount = 500;
- let fee = 50;
- let mut transaction = Transaction::new_with_payer(
- &[transfer_fee::instruction::transfer_checked_with_fee(
- &spl_token_2022::id(),
- &associated_token_address_sender,
- &token_mint_address,
- &associated_token_address_receiver,
- &wallet_address_sender,
- &[],
- transfer_amount,
- 0,
- fee,
- )
- .unwrap()],
- Some(&payer.pubkey()),
- );
- transaction.sign(&[&payer, &wallet_sender], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- let sender_account = banks_client
- .get_account(associated_token_address_sender)
- .await
- .unwrap()
- .unwrap();
- let sender_state = StateWithExtensionsOwned::::unpack(sender_account.data).unwrap();
- assert_eq!(sender_state.base.amount, sender_amount - transfer_amount);
- let extension = sender_state
- .get_extension::()
- .unwrap();
- assert_eq!(extension.withheld_amount, 0.into());
-
- let receiver_account = banks_client
- .get_account(associated_token_address_receiver)
- .await
- .unwrap()
- .unwrap();
- let receiver_state =
- StateWithExtensionsOwned::::unpack(receiver_account.data).unwrap();
- assert_eq!(receiver_state.base.amount, transfer_amount - fee);
- let extension = receiver_state
- .get_extension::()
- .unwrap();
- assert_eq!(extension.withheld_amount, fee.into());
-}
diff --git a/associated-token-account/program-test/tests/fixtures/token-mint-data.bin b/associated-token-account/program-test/tests/fixtures/token-mint-data.bin
deleted file mode 100644
index 4a48512c02a..00000000000
Binary files a/associated-token-account/program-test/tests/fixtures/token-mint-data.bin and /dev/null differ
diff --git a/associated-token-account/program-test/tests/process_create_associated_token_account.rs b/associated-token-account/program-test/tests/process_create_associated_token_account.rs
deleted file mode 100644
index e693310385c..00000000000
--- a/associated-token-account/program-test/tests/process_create_associated_token_account.rs
+++ /dev/null
@@ -1,318 +0,0 @@
-// Mark this test as BPF-only due to current `ProgramTest` limitations when
-// CPIing into the system program
-#![cfg(feature = "test-sbf")]
-
-mod program_test;
-
-use {
- program_test::program_test_2022,
- solana_program::{instruction::*, pubkey::Pubkey, system_instruction, sysvar},
- solana_program_test::*,
- solana_sdk::{
- signature::Signer,
- transaction::{Transaction, TransactionError},
- },
- spl_associated_token_account::instruction::create_associated_token_account,
- spl_associated_token_account_client::address::get_associated_token_address_with_program_id,
- spl_token_2022::{extension::ExtensionType, state::Account},
-};
-
-#[tokio::test]
-async fn test_associated_token_address() {
- let wallet_address = Pubkey::new_unique();
- let token_mint_address = Pubkey::new_unique();
- let associated_token_address = get_associated_token_address_with_program_id(
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
-
- let (banks_client, payer, recent_blockhash) =
- program_test_2022(token_mint_address, true).start().await;
- let rent = banks_client.get_rent().await.unwrap();
-
- let expected_token_account_len =
- ExtensionType::try_calculate_account_len::(&[ExtensionType::ImmutableOwner])
- .unwrap();
- let expected_token_account_balance = rent.minimum_balance(expected_token_account_len);
-
- // Associated account does not exist
- assert_eq!(
- banks_client
- .get_account(associated_token_address)
- .await
- .expect("get_account"),
- None,
- );
-
- let mut transaction = Transaction::new_with_payer(
- &[create_associated_token_account(
- &payer.pubkey(),
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- )],
- Some(&payer.pubkey()),
- );
- transaction.sign(&[&payer], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- // Associated account now exists
- let associated_account = banks_client
- .get_account(associated_token_address)
- .await
- .expect("get_account")
- .expect("associated_account not none");
- assert_eq!(associated_account.data.len(), expected_token_account_len,);
- assert_eq!(associated_account.owner, spl_token_2022::id());
- assert_eq!(associated_account.lamports, expected_token_account_balance);
-}
-
-#[tokio::test]
-async fn test_create_with_fewer_lamports() {
- let wallet_address = Pubkey::new_unique();
- let token_mint_address = Pubkey::new_unique();
- let associated_token_address = get_associated_token_address_with_program_id(
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
-
- let (banks_client, payer, recent_blockhash) =
- program_test_2022(token_mint_address, true).start().await;
- let rent = banks_client.get_rent().await.unwrap();
- let expected_token_account_len =
- ExtensionType::try_calculate_account_len::(&[ExtensionType::ImmutableOwner])
- .unwrap();
- let expected_token_account_balance = rent.minimum_balance(expected_token_account_len);
-
- // Transfer lamports into `associated_token_address` before creating it - enough
- // to be rent-exempt for 0 data, but not for an initialized token account
- let mut transaction = Transaction::new_with_payer(
- &[system_instruction::transfer(
- &payer.pubkey(),
- &associated_token_address,
- rent.minimum_balance(0),
- )],
- Some(&payer.pubkey()),
- );
- transaction.sign(&[&payer], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- assert_eq!(
- banks_client
- .get_balance(associated_token_address)
- .await
- .unwrap(),
- rent.minimum_balance(0)
- );
-
- // Check that the program adds the extra lamports
- let mut transaction = Transaction::new_with_payer(
- &[create_associated_token_account(
- &payer.pubkey(),
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- )],
- Some(&payer.pubkey()),
- );
- transaction.sign(&[&payer], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- assert_eq!(
- banks_client
- .get_balance(associated_token_address)
- .await
- .unwrap(),
- expected_token_account_balance,
- );
-}
-
-#[tokio::test]
-async fn test_create_with_excess_lamports() {
- let wallet_address = Pubkey::new_unique();
- let token_mint_address = Pubkey::new_unique();
- let associated_token_address = get_associated_token_address_with_program_id(
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
-
- let (banks_client, payer, recent_blockhash) =
- program_test_2022(token_mint_address, true).start().await;
- let rent = banks_client.get_rent().await.unwrap();
-
- let expected_token_account_len =
- ExtensionType::try_calculate_account_len::(&[ExtensionType::ImmutableOwner])
- .unwrap();
- let expected_token_account_balance = rent.minimum_balance(expected_token_account_len);
-
- // Transfer 1 lamport into `associated_token_address` before creating it
- let mut transaction = Transaction::new_with_payer(
- &[system_instruction::transfer(
- &payer.pubkey(),
- &associated_token_address,
- expected_token_account_balance + 1,
- )],
- Some(&payer.pubkey()),
- );
- transaction.sign(&[&payer], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- assert_eq!(
- banks_client
- .get_balance(associated_token_address)
- .await
- .unwrap(),
- expected_token_account_balance + 1
- );
-
- // Check that the program doesn't add any lamports
- let mut transaction = Transaction::new_with_payer(
- &[create_associated_token_account(
- &payer.pubkey(),
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- )],
- Some(&payer.pubkey()),
- );
- transaction.sign(&[&payer], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- assert_eq!(
- banks_client
- .get_balance(associated_token_address)
- .await
- .unwrap(),
- expected_token_account_balance + 1
- );
-}
-
-#[tokio::test]
-async fn test_create_account_mismatch() {
- let wallet_address = Pubkey::new_unique();
- let token_mint_address = Pubkey::new_unique();
- let _associated_token_address = get_associated_token_address_with_program_id(
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
-
- let (banks_client, payer, recent_blockhash) =
- program_test_2022(token_mint_address, true).start().await;
-
- let mut instruction = create_associated_token_account(
- &payer.pubkey(),
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
- instruction.accounts[1] = AccountMeta::new(Pubkey::default(), false); // <-- Invalid associated_account_address
-
- let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
- transaction.sign(&[&payer], recent_blockhash);
- assert_eq!(
- banks_client
- .process_transaction(transaction)
- .await
- .unwrap_err()
- .unwrap(),
- TransactionError::InstructionError(0, InstructionError::InvalidSeeds)
- );
-
- let mut instruction = create_associated_token_account(
- &payer.pubkey(),
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
- instruction.accounts[2] = AccountMeta::new(Pubkey::default(), false); // <-- Invalid wallet_address
-
- let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
- transaction.sign(&[&payer], recent_blockhash);
- assert_eq!(
- banks_client
- .process_transaction(transaction)
- .await
- .unwrap_err()
- .unwrap(),
- TransactionError::InstructionError(0, InstructionError::InvalidSeeds)
- );
-
- let mut instruction = create_associated_token_account(
- &payer.pubkey(),
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
- instruction.accounts[3] = AccountMeta::new(Pubkey::default(), false); // <-- Invalid token_mint_address
-
- let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
- transaction.sign(&[&payer], recent_blockhash);
- assert_eq!(
- banks_client
- .process_transaction(transaction)
- .await
- .unwrap_err()
- .unwrap(),
- TransactionError::InstructionError(0, InstructionError::InvalidSeeds)
- );
-}
-
-#[tokio::test]
-async fn test_create_associated_token_account_using_legacy_implicit_instruction() {
- let wallet_address = Pubkey::new_unique();
- let token_mint_address = Pubkey::new_unique();
- let associated_token_address = get_associated_token_address_with_program_id(
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
-
- let (banks_client, payer, recent_blockhash) =
- program_test_2022(token_mint_address, true).start().await;
- let rent = banks_client.get_rent().await.unwrap();
- let expected_token_account_len =
- ExtensionType::try_calculate_account_len::(&[ExtensionType::ImmutableOwner])
- .unwrap();
- let expected_token_account_balance = rent.minimum_balance(expected_token_account_len);
-
- // Associated account does not exist
- assert_eq!(
- banks_client
- .get_account(associated_token_address)
- .await
- .expect("get_account"),
- None,
- );
-
- let mut create_associated_token_account_ix = create_associated_token_account(
- &payer.pubkey(),
- &wallet_address,
- &token_mint_address,
- &spl_token_2022::id(),
- );
-
- // Use implicit instruction and rent account to replicate the legacy invocation
- create_associated_token_account_ix.data = vec![];
- create_associated_token_account_ix
- .accounts
- .push(AccountMeta::new_readonly(sysvar::rent::id(), false));
-
- let mut transaction =
- Transaction::new_with_payer(&[create_associated_token_account_ix], Some(&payer.pubkey()));
- transaction.sign(&[&payer], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- // Associated account now exists
- let associated_account = banks_client
- .get_account(associated_token_address)
- .await
- .expect("get_account")
- .expect("associated_account not none");
- assert_eq!(associated_account.data.len(), expected_token_account_len);
- assert_eq!(associated_account.owner, spl_token_2022::id());
- assert_eq!(associated_account.lamports, expected_token_account_balance);
-}
diff --git a/associated-token-account/program-test/tests/program_test.rs b/associated-token-account/program-test/tests/program_test.rs
deleted file mode 100644
index 7008931e7ef..00000000000
--- a/associated-token-account/program-test/tests/program_test.rs
+++ /dev/null
@@ -1,84 +0,0 @@
-use {
- solana_program::pubkey::Pubkey,
- solana_program_test::{ProgramTest, *},
- spl_associated_token_account::{id, processor::process_instruction},
-};
-
-#[allow(dead_code)]
-pub fn program_test(token_mint_address: Pubkey, use_latest_spl_token: bool) -> ProgramTest {
- let mut pc = ProgramTest::new(
- "spl_associated_token_account",
- id(),
- processor!(process_instruction),
- );
-
- if use_latest_spl_token {
- pc.prefer_bpf(false);
- // TODO: Remove when spl-token is available by default in program-test
- pc.add_program(
- "spl_token",
- spl_token::id(),
- processor!(spl_token::processor::Processor::process),
- );
- }
-
- // Add a token mint account
- //
- // The account data was generated by running:
- // $ solana account EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
- // --output-file tests/fixtures/token-mint-data.bin
- //
- pc.add_account_with_file_data(
- token_mint_address,
- 1461600,
- spl_token::id(),
- "token-mint-data.bin",
- );
-
- // Dial down the BPF compute budget to detect if the program gets bloated in the
- // future
- pc.set_compute_max_units(60_000);
-
- pc
-}
-
-#[allow(dead_code)]
-pub fn program_test_2022(
- token_mint_address: Pubkey,
- use_latest_spl_token_2022: bool,
-) -> ProgramTest {
- let mut pc = ProgramTest::new(
- "spl_associated_token_account",
- id(),
- processor!(process_instruction),
- );
-
- if use_latest_spl_token_2022 {
- pc.prefer_bpf(false);
- // TODO: Remove when spl-token-2022 is available by default in program-test
- pc.add_program(
- "spl_token_2022",
- spl_token_2022::id(),
- processor!(spl_token_2022::processor::Processor::process),
- );
- }
-
- // Add a token mint account
- //
- // The account data was generated by running:
- // $ solana account EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
- // --output-file tests/fixtures/token-mint-data.bin
- //
- pc.add_account_with_file_data(
- token_mint_address,
- 1461600,
- spl_token_2022::id(),
- "token-mint-data.bin",
- );
-
- // Dial down the BPF compute budget to detect if the program gets bloated in the
- // future
- pc.set_compute_max_units(50_000);
-
- pc
-}
diff --git a/associated-token-account/program-test/tests/recover_nested.rs b/associated-token-account/program-test/tests/recover_nested.rs
deleted file mode 100644
index bd06ae529d6..00000000000
--- a/associated-token-account/program-test/tests/recover_nested.rs
+++ /dev/null
@@ -1,678 +0,0 @@
-// Mark this test as BPF-only due to current `ProgramTest` limitations when
-// CPIing into the system program
-#![cfg(feature = "test-sbf")]
-
-mod program_test;
-
-use {
- program_test::{program_test, program_test_2022},
- solana_program::{pubkey::Pubkey, system_instruction},
- solana_program_test::*,
- solana_sdk::{
- instruction::{AccountMeta, InstructionError},
- signature::Signer,
- signer::keypair::Keypair,
- transaction::{Transaction, TransactionError},
- },
- spl_associated_token_account::instruction,
- spl_associated_token_account_client::address::get_associated_token_address_with_program_id,
- spl_token_2022::{
- extension::{ExtensionType, StateWithExtensionsOwned},
- state::{Account, Mint},
- },
-};
-
-async fn create_mint(context: &mut ProgramTestContext, program_id: &Pubkey) -> (Pubkey, Keypair) {
- let mint_account = Keypair::new();
- let token_mint_address = mint_account.pubkey();
- let mint_authority = Keypair::new();
- let space = ExtensionType::try_calculate_account_len::(&[]).unwrap();
- let rent = context.banks_client.get_rent().await.unwrap();
- let transaction = Transaction::new_signed_with_payer(
- &[
- system_instruction::create_account(
- &context.payer.pubkey(),
- &mint_account.pubkey(),
- rent.minimum_balance(space),
- space as u64,
- program_id,
- ),
- spl_token_2022::instruction::initialize_mint(
- program_id,
- &token_mint_address,
- &mint_authority.pubkey(),
- Some(&mint_authority.pubkey()),
- 0,
- )
- .unwrap(),
- ],
- Some(&context.payer.pubkey()),
- &[&context.payer, &mint_account],
- context.last_blockhash,
- );
- context
- .banks_client
- .process_transaction(transaction)
- .await
- .unwrap();
- (token_mint_address, mint_authority)
-}
-
-async fn create_associated_token_account(
- context: &mut ProgramTestContext,
- owner: &Pubkey,
- mint: &Pubkey,
- program_id: &Pubkey,
-) -> Pubkey {
- let transaction = Transaction::new_signed_with_payer(
- &[instruction::create_associated_token_account(
- &context.payer.pubkey(),
- owner,
- mint,
- program_id,
- )],
- Some(&context.payer.pubkey()),
- &[&context.payer],
- context.last_blockhash,
- );
- context
- .banks_client
- .process_transaction(transaction)
- .await
- .unwrap();
-
- get_associated_token_address_with_program_id(owner, mint, program_id)
-}
-
-#[allow(clippy::too_many_arguments)]
-async fn try_recover_nested(
- context: &mut ProgramTestContext,
- program_id: &Pubkey,
- nested_mint: Pubkey,
- nested_mint_authority: Keypair,
- nested_associated_token_address: Pubkey,
- destination_token_address: Pubkey,
- wallet: Keypair,
- recover_transaction: Transaction,
- expected_error: Option,
-) {
- let nested_account = context
- .banks_client
- .get_account(nested_associated_token_address)
- .await
- .unwrap()
- .unwrap();
- let lamports = nested_account.lamports;
-
- // mint to nested account
- let amount = 100;
- let transaction = Transaction::new_signed_with_payer(
- &[spl_token_2022::instruction::mint_to(
- program_id,
- &nested_mint,
- &nested_associated_token_address,
- &nested_mint_authority.pubkey(),
- &[],
- amount,
- )
- .unwrap()],
- Some(&context.payer.pubkey()),
- &[&context.payer, &nested_mint_authority],
- context.last_blockhash,
- );
- context
- .banks_client
- .process_transaction(transaction)
- .await
- .unwrap();
-
- // transfer / close nested account
- let result = context
- .banks_client
- .process_transaction(recover_transaction)
- .await;
-
- if let Some(expected_error) = expected_error {
- let error = result.unwrap_err().unwrap();
- assert_eq!(error, TransactionError::InstructionError(0, expected_error));
- } else {
- result.unwrap();
- // nested account is gone
- assert!(context
- .banks_client
- .get_account(nested_associated_token_address)
- .await
- .unwrap()
- .is_none());
- let destination_account = context
- .banks_client
- .get_account(destination_token_address)
- .await
- .unwrap()
- .unwrap();
- let destination_state =
- StateWithExtensionsOwned::::unpack(destination_account.data).unwrap();
- assert_eq!(destination_state.base.amount, amount);
- let wallet_account = context
- .banks_client
- .get_account(wallet.pubkey())
- .await
- .unwrap()
- .unwrap();
- assert_eq!(wallet_account.lamports, lamports);
- }
-}
-
-async fn check_same_mint(context: &mut ProgramTestContext, program_id: &Pubkey) {
- let wallet = Keypair::new();
- let (mint, mint_authority) = create_mint(context, program_id).await;
-
- let owner_associated_token_address =
- create_associated_token_account(context, &wallet.pubkey(), &mint, program_id).await;
- let nested_associated_token_address = create_associated_token_account(
- context,
- &owner_associated_token_address,
- &mint,
- program_id,
- )
- .await;
-
- context.last_blockhash = context
- .banks_client
- .get_new_latest_blockhash(&context.last_blockhash)
- .await
- .unwrap();
- let transaction = Transaction::new_signed_with_payer(
- &[instruction::recover_nested(
- &wallet.pubkey(),
- &mint,
- &mint,
- program_id,
- )],
- Some(&context.payer.pubkey()),
- &[&context.payer, &wallet],
- context.last_blockhash,
- );
- try_recover_nested(
- context,
- program_id,
- mint,
- mint_authority,
- nested_associated_token_address,
- owner_associated_token_address,
- wallet,
- transaction,
- None,
- )
- .await;
-}
-
-#[tokio::test]
-async fn success_same_mint_2022() {
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test_2022(dummy_mint, true);
- let mut context = pt.start_with_context().await;
- check_same_mint(&mut context, &spl_token_2022::id()).await;
-}
-
-#[tokio::test]
-async fn success_same_mint() {
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test(dummy_mint, true);
- let mut context = pt.start_with_context().await;
- check_same_mint(&mut context, &spl_token::id()).await;
-}
-
-async fn check_different_mints(context: &mut ProgramTestContext, program_id: &Pubkey) {
- let wallet = Keypair::new();
- let (owner_mint, _owner_mint_authority) = create_mint(context, program_id).await;
- let (nested_mint, nested_mint_authority) = create_mint(context, program_id).await;
-
- let owner_associated_token_address =
- create_associated_token_account(context, &wallet.pubkey(), &owner_mint, program_id).await;
- let nested_associated_token_address = create_associated_token_account(
- context,
- &owner_associated_token_address,
- &nested_mint,
- program_id,
- )
- .await;
- let destination_token_address =
- create_associated_token_account(context, &wallet.pubkey(), &nested_mint, program_id).await;
-
- context.last_blockhash = context
- .banks_client
- .get_new_latest_blockhash(&context.last_blockhash)
- .await
- .unwrap();
- let transaction = Transaction::new_signed_with_payer(
- &[instruction::recover_nested(
- &wallet.pubkey(),
- &owner_mint,
- &nested_mint,
- program_id,
- )],
- Some(&context.payer.pubkey()),
- &[&context.payer, &wallet],
- context.last_blockhash,
- );
- try_recover_nested(
- context,
- program_id,
- nested_mint,
- nested_mint_authority,
- nested_associated_token_address,
- destination_token_address,
- wallet,
- transaction,
- None,
- )
- .await;
-}
-
-#[tokio::test]
-async fn success_different_mints() {
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test(dummy_mint, true);
- let mut context = pt.start_with_context().await;
- check_different_mints(&mut context, &spl_token::id()).await;
-}
-
-#[tokio::test]
-async fn success_different_mints_2022() {
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test_2022(dummy_mint, true);
- let mut context = pt.start_with_context().await;
- check_different_mints(&mut context, &spl_token_2022::id()).await;
-}
-
-async fn check_missing_wallet_signature(context: &mut ProgramTestContext, program_id: &Pubkey) {
- let wallet = Keypair::new();
- let (mint, mint_authority) = create_mint(context, program_id).await;
-
- let owner_associated_token_address =
- create_associated_token_account(context, &wallet.pubkey(), &mint, program_id).await;
-
- let nested_associated_token_address = create_associated_token_account(
- context,
- &owner_associated_token_address,
- &mint,
- program_id,
- )
- .await;
-
- let mut recover = instruction::recover_nested(&wallet.pubkey(), &mint, &mint, program_id);
- recover.accounts[5] = AccountMeta::new(wallet.pubkey(), false);
- context.last_blockhash = context
- .banks_client
- .get_new_latest_blockhash(&context.last_blockhash)
- .await
- .unwrap();
- let transaction = Transaction::new_signed_with_payer(
- &[recover],
- Some(&context.payer.pubkey()),
- &[&context.payer],
- context.last_blockhash,
- );
- try_recover_nested(
- context,
- program_id,
- mint,
- mint_authority,
- nested_associated_token_address,
- owner_associated_token_address,
- wallet,
- transaction,
- Some(InstructionError::MissingRequiredSignature),
- )
- .await;
-}
-
-#[tokio::test]
-async fn fail_missing_wallet_signature_2022() {
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test_2022(dummy_mint, true);
- let mut context = pt.start_with_context().await;
- check_missing_wallet_signature(&mut context, &spl_token_2022::id()).await;
-}
-
-#[tokio::test]
-async fn fail_missing_wallet_signature() {
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test(dummy_mint, true);
- let mut context = pt.start_with_context().await;
- check_missing_wallet_signature(&mut context, &spl_token::id()).await;
-}
-
-async fn check_wrong_signer(context: &mut ProgramTestContext, program_id: &Pubkey) {
- let wallet = Keypair::new();
- let wrong_wallet = Keypair::new();
- let (mint, mint_authority) = create_mint(context, program_id).await;
-
- let owner_associated_token_address =
- create_associated_token_account(context, &wallet.pubkey(), &mint, program_id).await;
- let nested_associated_token_address = create_associated_token_account(
- context,
- &owner_associated_token_address,
- &mint,
- program_id,
- )
- .await;
-
- context.last_blockhash = context
- .banks_client
- .get_new_latest_blockhash(&context.last_blockhash)
- .await
- .unwrap();
- let transaction = Transaction::new_signed_with_payer(
- &[instruction::recover_nested(
- &wrong_wallet.pubkey(),
- &mint,
- &mint,
- program_id,
- )],
- Some(&context.payer.pubkey()),
- &[&context.payer, &wrong_wallet],
- context.last_blockhash,
- );
- try_recover_nested(
- context,
- program_id,
- mint,
- mint_authority,
- nested_associated_token_address,
- owner_associated_token_address,
- wrong_wallet,
- transaction,
- Some(InstructionError::IllegalOwner),
- )
- .await;
-}
-
-#[tokio::test]
-async fn fail_wrong_signer_2022() {
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test_2022(dummy_mint, true);
- let mut context = pt.start_with_context().await;
- check_wrong_signer(&mut context, &spl_token_2022::id()).await;
-}
-
-#[tokio::test]
-async fn fail_wrong_signer() {
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test(dummy_mint, true);
- let mut context = pt.start_with_context().await;
- check_wrong_signer(&mut context, &spl_token::id()).await;
-}
-
-async fn check_not_nested(context: &mut ProgramTestContext, program_id: &Pubkey) {
- let wallet = Keypair::new();
- let wrong_wallet = Pubkey::new_unique();
- let (mint, mint_authority) = create_mint(context, program_id).await;
-
- let owner_associated_token_address =
- create_associated_token_account(context, &wallet.pubkey(), &mint, program_id).await;
- let nested_associated_token_address =
- create_associated_token_account(context, &wrong_wallet, &mint, program_id).await;
-
- context.last_blockhash = context
- .banks_client
- .get_new_latest_blockhash(&context.last_blockhash)
- .await
- .unwrap();
- let transaction = Transaction::new_signed_with_payer(
- &[instruction::recover_nested(
- &wallet.pubkey(),
- &mint,
- &mint,
- program_id,
- )],
- Some(&context.payer.pubkey()),
- &[&context.payer, &wallet],
- context.last_blockhash,
- );
- try_recover_nested(
- context,
- program_id,
- mint,
- mint_authority,
- nested_associated_token_address,
- owner_associated_token_address,
- wallet,
- transaction,
- Some(InstructionError::IllegalOwner),
- )
- .await;
-}
-
-#[tokio::test]
-async fn fail_not_nested_2022() {
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test_2022(dummy_mint, true);
- let mut context = pt.start_with_context().await;
- check_not_nested(&mut context, &spl_token_2022::id()).await;
-}
-
-#[tokio::test]
-async fn fail_not_nested() {
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test(dummy_mint, true);
- let mut context = pt.start_with_context().await;
- check_not_nested(&mut context, &spl_token::id()).await;
-}
-
-async fn check_wrong_address_derivation_owner(
- context: &mut ProgramTestContext,
- program_id: &Pubkey,
-) {
- let wallet = Keypair::new();
- let wrong_wallet = Pubkey::new_unique();
- let (mint, mint_authority) = create_mint(context, program_id).await;
-
- let owner_associated_token_address =
- create_associated_token_account(context, &wallet.pubkey(), &mint, program_id).await;
- let nested_associated_token_address = create_associated_token_account(
- context,
- &owner_associated_token_address,
- &mint,
- program_id,
- )
- .await;
-
- let wrong_owner_associated_token_address =
- get_associated_token_address_with_program_id(&mint, &wrong_wallet, program_id);
- let mut recover = instruction::recover_nested(&wallet.pubkey(), &mint, &mint, program_id);
- recover.accounts[3] = AccountMeta::new(wrong_owner_associated_token_address, false);
- context.last_blockhash = context
- .banks_client
- .get_new_latest_blockhash(&context.last_blockhash)
- .await
- .unwrap();
- let transaction = Transaction::new_signed_with_payer(
- &[recover],
- Some(&context.payer.pubkey()),
- &[&context.payer, &wallet],
- context.last_blockhash,
- );
- try_recover_nested(
- context,
- program_id,
- mint,
- mint_authority,
- nested_associated_token_address,
- wrong_owner_associated_token_address,
- wallet,
- transaction,
- Some(InstructionError::InvalidSeeds),
- )
- .await;
-}
-
-#[tokio::test]
-async fn fail_wrong_address_derivation_owner_2022() {
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test_2022(dummy_mint, true);
- let mut context = pt.start_with_context().await;
- check_wrong_address_derivation_owner(&mut context, &spl_token_2022::id()).await;
-}
-
-#[tokio::test]
-async fn fail_wrong_address_derivation_owner() {
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test(dummy_mint, true);
- let mut context = pt.start_with_context().await;
- check_wrong_address_derivation_owner(&mut context, &spl_token::id()).await;
-}
-
-async fn check_owner_account_does_not_exist(context: &mut ProgramTestContext, program_id: &Pubkey) {
- let wallet = Keypair::new();
- let (mint, mint_authority) = create_mint(context, program_id).await;
-
- let owner_associated_token_address =
- get_associated_token_address_with_program_id(&wallet.pubkey(), &mint, program_id);
- let nested_associated_token_address = create_associated_token_account(
- context,
- &owner_associated_token_address,
- &mint,
- program_id,
- )
- .await;
-
- context.last_blockhash = context
- .banks_client
- .get_new_latest_blockhash(&context.last_blockhash)
- .await
- .unwrap();
- let transaction = Transaction::new_signed_with_payer(
- &[instruction::recover_nested(
- &wallet.pubkey(),
- &mint,
- &mint,
- program_id,
- )],
- Some(&context.payer.pubkey()),
- &[&context.payer, &wallet],
- context.last_blockhash,
- );
- try_recover_nested(
- context,
- program_id,
- mint,
- mint_authority,
- nested_associated_token_address,
- owner_associated_token_address,
- wallet,
- transaction,
- Some(InstructionError::IllegalOwner),
- )
- .await;
-}
-
-#[tokio::test]
-async fn fail_owner_account_does_not_exist() {
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test_2022(dummy_mint, true);
- let mut context = pt.start_with_context().await;
- check_owner_account_does_not_exist(&mut context, &spl_token_2022::id()).await;
-}
-
-#[tokio::test]
-async fn fail_wrong_spl_token_program() {
- let wallet = Keypair::new();
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test_2022(dummy_mint, true);
- let mut context = pt.start_with_context().await;
- let program_id = spl_token_2022::id();
- let wrong_program_id = spl_token::id();
- let (mint, mint_authority) = create_mint(&mut context, &program_id).await;
-
- let owner_associated_token_address =
- create_associated_token_account(&mut context, &wallet.pubkey(), &mint, &program_id).await;
- let nested_associated_token_address = create_associated_token_account(
- &mut context,
- &owner_associated_token_address,
- &mint,
- &program_id,
- )
- .await;
-
- context.last_blockhash = context
- .banks_client
- .get_new_latest_blockhash(&context.last_blockhash)
- .await
- .unwrap();
- let transaction = Transaction::new_signed_with_payer(
- &[instruction::recover_nested(
- &wallet.pubkey(),
- &mint,
- &mint,
- &wrong_program_id,
- )],
- Some(&context.payer.pubkey()),
- &[&context.payer, &wallet],
- context.last_blockhash,
- );
- try_recover_nested(
- &mut context,
- &program_id,
- mint,
- mint_authority,
- nested_associated_token_address,
- owner_associated_token_address,
- wallet,
- transaction,
- Some(InstructionError::IllegalOwner),
- )
- .await;
-}
-
-#[tokio::test]
-async fn fail_destination_not_wallet_ata() {
- let wallet = Keypair::new();
- let wrong_wallet = Pubkey::new_unique();
- let dummy_mint = Pubkey::new_unique();
- let pt = program_test_2022(dummy_mint, true);
- let program_id = spl_token_2022::id();
- let mut context = pt.start_with_context().await;
- let (mint, mint_authority) = create_mint(&mut context, &program_id).await;
-
- let owner_associated_token_address =
- create_associated_token_account(&mut context, &wallet.pubkey(), &mint, &program_id).await;
- let nested_associated_token_address = create_associated_token_account(
- &mut context,
- &owner_associated_token_address,
- &mint,
- &program_id,
- )
- .await;
- let wrong_destination_associated_token_account_address =
- create_associated_token_account(&mut context, &wrong_wallet, &mint, &program_id).await;
-
- let mut recover = instruction::recover_nested(&wallet.pubkey(), &mint, &mint, &program_id);
- recover.accounts[2] =
- AccountMeta::new(wrong_destination_associated_token_account_address, false);
-
- context.last_blockhash = context
- .banks_client
- .get_new_latest_blockhash(&context.last_blockhash)
- .await
- .unwrap();
- let transaction = Transaction::new_signed_with_payer(
- &[recover],
- Some(&context.payer.pubkey()),
- &[&context.payer, &wallet],
- context.last_blockhash,
- );
- try_recover_nested(
- &mut context,
- &program_id,
- mint,
- mint_authority,
- nested_associated_token_address,
- owner_associated_token_address,
- wallet,
- transaction,
- Some(InstructionError::InvalidSeeds),
- )
- .await;
-}
diff --git a/associated-token-account/program-test/tests/spl_token_create.rs b/associated-token-account/program-test/tests/spl_token_create.rs
deleted file mode 100644
index 21970414946..00000000000
--- a/associated-token-account/program-test/tests/spl_token_create.rs
+++ /dev/null
@@ -1,112 +0,0 @@
-// Mark this test as BPF-only due to current `ProgramTest` limitations when
-// CPIing into the system program
-#![cfg(feature = "test-sbf")]
-
-mod program_test;
-
-#[allow(deprecated)]
-use spl_associated_token_account::create_associated_token_account as deprecated_create_associated_token_account;
-use {
- program_test::program_test,
- solana_program::pubkey::Pubkey,
- solana_program_test::*,
- solana_sdk::{program_pack::Pack, signature::Signer, transaction::Transaction},
- spl_associated_token_account::instruction::create_associated_token_account,
- spl_associated_token_account_client::address::get_associated_token_address,
- spl_token::state::Account,
-};
-
-#[tokio::test]
-async fn success_create() {
- let wallet_address = Pubkey::new_unique();
- let token_mint_address = Pubkey::new_unique();
- let associated_token_address =
- get_associated_token_address(&wallet_address, &token_mint_address);
-
- let (banks_client, payer, recent_blockhash) =
- program_test(token_mint_address, true).start().await;
- let rent = banks_client.get_rent().await.unwrap();
- let expected_token_account_len = Account::LEN;
- let expected_token_account_balance = rent.minimum_balance(expected_token_account_len);
-
- // Associated account does not exist
- assert_eq!(
- banks_client
- .get_account(associated_token_address)
- .await
- .expect("get_account"),
- None,
- );
-
- let transaction = Transaction::new_signed_with_payer(
- &[create_associated_token_account(
- &payer.pubkey(),
- &wallet_address,
- &token_mint_address,
- &spl_token::id(),
- )],
- Some(&payer.pubkey()),
- &[&payer],
- recent_blockhash,
- );
- banks_client.process_transaction(transaction).await.unwrap();
-
- // Associated account now exists
- let associated_account = banks_client
- .get_account(associated_token_address)
- .await
- .expect("get_account")
- .expect("associated_account not none");
- assert_eq!(associated_account.data.len(), expected_token_account_len);
- assert_eq!(associated_account.owner, spl_token::id());
- assert_eq!(associated_account.lamports, expected_token_account_balance);
-}
-
-#[tokio::test]
-async fn success_using_deprecated_instruction_creator() {
- let wallet_address = Pubkey::new_unique();
- let token_mint_address = Pubkey::new_unique();
- let associated_token_address =
- get_associated_token_address(&wallet_address, &token_mint_address);
-
- let (banks_client, payer, recent_blockhash) =
- program_test(token_mint_address, true).start().await;
- let rent = banks_client.get_rent().await.unwrap();
- let expected_token_account_len = Account::LEN;
- let expected_token_account_balance = rent.minimum_balance(expected_token_account_len);
-
- // Associated account does not exist
- assert_eq!(
- banks_client
- .get_account(associated_token_address)
- .await
- .expect("get_account"),
- None,
- );
-
- // Use legacy instruction creator
- #[allow(deprecated)]
- let create_associated_token_account_ix = deprecated_create_associated_token_account(
- &payer.pubkey(),
- &wallet_address,
- &token_mint_address,
- );
-
- let transaction = Transaction::new_signed_with_payer(
- &[create_associated_token_account_ix],
- Some(&payer.pubkey()),
- &[&payer],
- recent_blockhash,
- );
- banks_client.process_transaction(transaction).await.unwrap();
-
- // Associated account now exists
- let associated_account = banks_client
- .get_account(associated_token_address)
- .await
- .expect("get_account")
- .expect("associated_account not none");
- assert_eq!(associated_account.data.len(), expected_token_account_len);
- assert_eq!(associated_account.owner, spl_token::id());
- assert_eq!(associated_account.lamports, expected_token_account_balance);
-}
diff --git a/associated-token-account/program/Cargo.toml b/associated-token-account/program/Cargo.toml
deleted file mode 100644
index 8360d217eb0..00000000000
--- a/associated-token-account/program/Cargo.toml
+++ /dev/null
@@ -1,32 +0,0 @@
-[package]
-name = "spl-associated-token-account"
-version = "6.0.0"
-description = "Solana Program Library Associated Token Account"
-authors = ["Solana Labs Maintainers "]
-repository = "https://github.com/solana-labs/solana-program-library"
-license = "Apache-2.0"
-edition = "2021"
-
-[features]
-no-entrypoint = []
-test-sbf = []
-
-[dependencies]
-borsh = "1.5.3"
-num-derive = "0.4"
-num-traits = "0.2"
-solana-program = "2.1.0"
-spl-associated-token-account-client = { version = "2.0.0", path = "../client" }
-spl-token = { version = "7.0", path = "../../token/program", features = [
- "no-entrypoint",
-] }
-spl-token-2022 = { version = "6.0.0", path = "../../token/program-2022", features = [
- "no-entrypoint",
-] }
-thiserror = "2.0"
-
-[lib]
-crate-type = ["cdylib", "lib"]
-
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu"]
diff --git a/associated-token-account/program/Xargo.toml b/associated-token-account/program/Xargo.toml
deleted file mode 100644
index 1744f098ae1..00000000000
--- a/associated-token-account/program/Xargo.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[target.bpfel-unknown-unknown.dependencies.std]
-features = []
\ No newline at end of file
diff --git a/associated-token-account/program/program-id.md b/associated-token-account/program/program-id.md
deleted file mode 100644
index de8233b720f..00000000000
--- a/associated-token-account/program/program-id.md
+++ /dev/null
@@ -1 +0,0 @@
-ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL
diff --git a/associated-token-account/program/run-tests.sh b/associated-token-account/program/run-tests.sh
deleted file mode 100755
index 603e3c552b2..00000000000
--- a/associated-token-account/program/run-tests.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-cd "$(dirname "$0")"
-cargo clippy
-cargo build
-cargo build-sbf
-
-if [[ $1 = -v ]]; then
- export RUST_LOG=solana=debug
-fi
-
-cargo test
-cargo test-sbf
diff --git a/associated-token-account/program/src/entrypoint.rs b/associated-token-account/program/src/entrypoint.rs
deleted file mode 100644
index 8876e45b78b..00000000000
--- a/associated-token-account/program/src/entrypoint.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//! Program entrypoint
-
-#![cfg(not(feature = "no-entrypoint"))]
-
-use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey};
-
-solana_program::entrypoint!(process_instruction);
-fn process_instruction(
- program_id: &Pubkey,
- accounts: &[AccountInfo],
- instruction_data: &[u8],
-) -> ProgramResult {
- crate::processor::process_instruction(program_id, accounts, instruction_data)
-}
diff --git a/associated-token-account/program/src/error.rs b/associated-token-account/program/src/error.rs
deleted file mode 100644
index ae858a0d537..00000000000
--- a/associated-token-account/program/src/error.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-//! Error types
-
-use {
- num_derive::FromPrimitive,
- solana_program::{decode_error::DecodeError, program_error::ProgramError},
- thiserror::Error,
-};
-
-/// Errors that may be returned by the program.
-#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)]
-pub enum AssociatedTokenAccountError {
- // 0
- /// Associated token account owner does not match address derivation
- #[error("Associated token account owner does not match address derivation")]
- InvalidOwner,
-}
-impl From for ProgramError {
- fn from(e: AssociatedTokenAccountError) -> Self {
- ProgramError::Custom(e as u32)
- }
-}
-impl DecodeError for AssociatedTokenAccountError {
- fn type_of() -> &'static str {
- "AssociatedTokenAccountError"
- }
-}
diff --git a/associated-token-account/program/src/instruction.rs b/associated-token-account/program/src/instruction.rs
deleted file mode 100644
index 51453b9ae14..00000000000
--- a/associated-token-account/program/src/instruction.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-//! Program instructions
-
-use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
-pub use spl_associated_token_account_client::instruction::*;
-
-/// Instructions supported by the AssociatedTokenAccount program
-#[derive(Clone, Debug, PartialEq, BorshDeserialize, BorshSerialize, BorshSchema)]
-pub enum AssociatedTokenAccountInstruction {
- /// Creates an associated token account for the given wallet address and
- /// token mint Returns an error if the account exists.
- ///
- /// 0. `[writeable,signer]` Funding account (must be a system account)
- /// 1. `[writeable]` Associated token account address to be created
- /// 2. `[]` Wallet address for the new associated token account
- /// 3. `[]` The token mint for the new associated token account
- /// 4. `[]` System program
- /// 5. `[]` SPL Token program
- Create,
- /// Creates an associated token account for the given wallet address and
- /// token mint, if it doesn't already exist. Returns an error if the
- /// account exists, but with a different owner.
- ///
- /// 0. `[writeable,signer]` Funding account (must be a system account)
- /// 1. `[writeable]` Associated token account address to be created
- /// 2. `[]` Wallet address for the new associated token account
- /// 3. `[]` The token mint for the new associated token account
- /// 4. `[]` System program
- /// 5. `[]` SPL Token program
- CreateIdempotent,
- /// Transfers from and closes a nested associated token account: an
- /// associated token account owned by an associated token account.
- ///
- /// The tokens are moved from the nested associated token account to the
- /// wallet's associated token account, and the nested account lamports are
- /// moved to the wallet.
- ///
- /// Note: Nested token accounts are an anti-pattern, and almost always
- /// created unintentionally, so this instruction should only be used to
- /// recover from errors.
- ///
- /// 0. `[writeable]` Nested associated token account, must be owned by `3`
- /// 1. `[]` Token mint for the nested associated token account
- /// 2. `[writeable]` Wallet's associated token account
- /// 3. `[]` Owner associated token account address, must be owned by `5`
- /// 4. `[]` Token mint for the owner associated token account
- /// 5. `[writeable, signer]` Wallet address for the owner associated token
- /// account
- /// 6. `[]` SPL Token program
- RecoverNested,
-}
diff --git a/associated-token-account/program/src/lib.rs b/associated-token-account/program/src/lib.rs
deleted file mode 100644
index 5778456aa27..00000000000
--- a/associated-token-account/program/src/lib.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-//! Convention for associating token accounts with a user wallet
-#![deny(missing_docs)]
-#![forbid(unsafe_code)]
-
-mod entrypoint;
-pub mod error;
-pub mod instruction;
-pub mod processor;
-pub mod tools;
-
-// Export current SDK types for downstream users building with a different SDK
-// version
-pub use solana_program;
-use solana_program::{
- instruction::{AccountMeta, Instruction},
- pubkey::Pubkey,
- sysvar,
-};
-#[deprecated(
- since = "4.1.0",
- note = "Use `spl-associated-token-account-client` crate instead."
-)]
-pub use spl_associated_token_account_client::address::{
- get_associated_token_address, get_associated_token_address_with_program_id,
-};
-// Export current SDK types for downstream users building with a different SDK
-// version
-pub use spl_associated_token_account_client::program::{check_id, id, ID};
-
-/// Create an associated token account for the given wallet address and token
-/// mint
-///
-/// Accounts expected by this instruction:
-///
-/// 0. `[writeable,signer]` Funding account (must be a system account)
-/// 1. `[writeable]` Associated token account address to be created
-/// 2. `[]` Wallet address for the new associated token account
-/// 3. `[]` The token mint for the new associated token account
-/// 4. `[]` System program
-/// 5. `[]` SPL Token program
-#[deprecated(
- since = "1.0.5",
- note = "please use `instruction::create_associated_token_account` instead"
-)]
-pub fn create_associated_token_account(
- funding_address: &Pubkey,
- wallet_address: &Pubkey,
- token_mint_address: &Pubkey,
-) -> Instruction {
- let associated_account_address =
- get_associated_token_address(wallet_address, token_mint_address);
-
- Instruction {
- program_id: id(),
- accounts: vec![
- AccountMeta::new(*funding_address, true),
- AccountMeta::new(associated_account_address, false),
- AccountMeta::new_readonly(*wallet_address, false),
- AccountMeta::new_readonly(*token_mint_address, false),
- AccountMeta::new_readonly(solana_program::system_program::id(), false),
- AccountMeta::new_readonly(spl_token::id(), false),
- AccountMeta::new_readonly(sysvar::rent::id(), false),
- ],
- data: vec![],
- }
-}
diff --git a/associated-token-account/program/src/processor.rs b/associated-token-account/program/src/processor.rs
deleted file mode 100644
index f0063908c78..00000000000
--- a/associated-token-account/program/src/processor.rs
+++ /dev/null
@@ -1,309 +0,0 @@
-//! Program state processor
-
-use {
- crate::{
- error::AssociatedTokenAccountError,
- instruction::AssociatedTokenAccountInstruction,
- tools::account::{create_pda_account, get_account_len},
- },
- borsh::BorshDeserialize,
- solana_program::{
- account_info::{next_account_info, AccountInfo},
- entrypoint::ProgramResult,
- msg,
- program::{invoke, invoke_signed},
- program_error::ProgramError,
- pubkey::Pubkey,
- rent::Rent,
- system_program,
- sysvar::Sysvar,
- },
- spl_associated_token_account_client::address::get_associated_token_address_and_bump_seed_internal,
- spl_token_2022::{
- extension::{ExtensionType, StateWithExtensions},
- state::{Account, Mint},
- },
-};
-
-/// Specify when to create the associated token account
-#[derive(PartialEq)]
-enum CreateMode {
- /// Always try to create the ATA
- Always,
- /// Only try to create the ATA if non-existent
- Idempotent,
-}
-
-/// Instruction processor
-pub fn process_instruction(
- program_id: &Pubkey,
- accounts: &[AccountInfo],
- input: &[u8],
-) -> ProgramResult {
- let instruction = if input.is_empty() {
- AssociatedTokenAccountInstruction::Create
- } else {
- AssociatedTokenAccountInstruction::try_from_slice(input)
- .map_err(|_| ProgramError::InvalidInstructionData)?
- };
-
- msg!("{:?}", instruction);
-
- match instruction {
- AssociatedTokenAccountInstruction::Create => {
- process_create_associated_token_account(program_id, accounts, CreateMode::Always)
- }
- AssociatedTokenAccountInstruction::CreateIdempotent => {
- process_create_associated_token_account(program_id, accounts, CreateMode::Idempotent)
- }
- AssociatedTokenAccountInstruction::RecoverNested => {
- process_recover_nested(program_id, accounts)
- }
- }
-}
-
-/// Processes CreateAssociatedTokenAccount instruction
-fn process_create_associated_token_account(
- program_id: &Pubkey,
- accounts: &[AccountInfo],
- create_mode: CreateMode,
-) -> ProgramResult {
- let account_info_iter = &mut accounts.iter();
-
- let funder_info = next_account_info(account_info_iter)?;
- let associated_token_account_info = next_account_info(account_info_iter)?;
- let wallet_account_info = next_account_info(account_info_iter)?;
- let spl_token_mint_info = next_account_info(account_info_iter)?;
- let system_program_info = next_account_info(account_info_iter)?;
- let spl_token_program_info = next_account_info(account_info_iter)?;
- let spl_token_program_id = spl_token_program_info.key;
-
- let (associated_token_address, bump_seed) = get_associated_token_address_and_bump_seed_internal(
- wallet_account_info.key,
- spl_token_mint_info.key,
- program_id,
- spl_token_program_id,
- );
- if associated_token_address != *associated_token_account_info.key {
- msg!("Error: Associated address does not match seed derivation");
- return Err(ProgramError::InvalidSeeds);
- }
-
- if create_mode == CreateMode::Idempotent
- && associated_token_account_info.owner == spl_token_program_id
- {
- let ata_data = associated_token_account_info.data.borrow();
- if let Ok(associated_token_account) = StateWithExtensions::::unpack(&ata_data) {
- if associated_token_account.base.owner != *wallet_account_info.key {
- let error = AssociatedTokenAccountError::InvalidOwner;
- msg!("{}", error);
- return Err(error.into());
- }
- if associated_token_account.base.mint != *spl_token_mint_info.key {
- return Err(ProgramError::InvalidAccountData);
- }
- return Ok(());
- }
- }
- if *associated_token_account_info.owner != system_program::id() {
- return Err(ProgramError::IllegalOwner);
- }
-
- let rent = Rent::get()?;
-
- let associated_token_account_signer_seeds: &[&[_]] = &[
- &wallet_account_info.key.to_bytes(),
- &spl_token_program_id.to_bytes(),
- &spl_token_mint_info.key.to_bytes(),
- &[bump_seed],
- ];
-
- let account_len = get_account_len(
- spl_token_mint_info,
- spl_token_program_info,
- &[ExtensionType::ImmutableOwner],
- )?;
-
- create_pda_account(
- funder_info,
- &rent,
- account_len,
- spl_token_program_id,
- system_program_info,
- associated_token_account_info,
- associated_token_account_signer_seeds,
- )?;
-
- msg!("Initialize the associated token account");
- invoke(
- &spl_token_2022::instruction::initialize_immutable_owner(
- spl_token_program_id,
- associated_token_account_info.key,
- )?,
- &[
- associated_token_account_info.clone(),
- spl_token_program_info.clone(),
- ],
- )?;
- invoke(
- &spl_token_2022::instruction::initialize_account3(
- spl_token_program_id,
- associated_token_account_info.key,
- spl_token_mint_info.key,
- wallet_account_info.key,
- )?,
- &[
- associated_token_account_info.clone(),
- spl_token_mint_info.clone(),
- wallet_account_info.clone(),
- spl_token_program_info.clone(),
- ],
- )
-}
-
-/// Processes `RecoverNested` instruction
-pub fn process_recover_nested(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
- let account_info_iter = &mut accounts.iter();
-
- let nested_associated_token_account_info = next_account_info(account_info_iter)?;
- let nested_token_mint_info = next_account_info(account_info_iter)?;
- let destination_associated_token_account_info = next_account_info(account_info_iter)?;
- let owner_associated_token_account_info = next_account_info(account_info_iter)?;
- let owner_token_mint_info = next_account_info(account_info_iter)?;
- let wallet_account_info = next_account_info(account_info_iter)?;
- let spl_token_program_info = next_account_info(account_info_iter)?;
- let spl_token_program_id = spl_token_program_info.key;
-
- // Check owner address derivation
- let (owner_associated_token_address, bump_seed) =
- get_associated_token_address_and_bump_seed_internal(
- wallet_account_info.key,
- owner_token_mint_info.key,
- program_id,
- spl_token_program_id,
- );
- if owner_associated_token_address != *owner_associated_token_account_info.key {
- msg!("Error: Owner associated address does not match seed derivation");
- return Err(ProgramError::InvalidSeeds);
- }
-
- // Check nested address derivation
- let (nested_associated_token_address, _) = get_associated_token_address_and_bump_seed_internal(
- owner_associated_token_account_info.key,
- nested_token_mint_info.key,
- program_id,
- spl_token_program_id,
- );
- if nested_associated_token_address != *nested_associated_token_account_info.key {
- msg!("Error: Nested associated address does not match seed derivation");
- return Err(ProgramError::InvalidSeeds);
- }
-
- // Check destination address derivation
- let (destination_associated_token_address, _) =
- get_associated_token_address_and_bump_seed_internal(
- wallet_account_info.key,
- nested_token_mint_info.key,
- program_id,
- spl_token_program_id,
- );
- if destination_associated_token_address != *destination_associated_token_account_info.key {
- msg!("Error: Destination associated address does not match seed derivation");
- return Err(ProgramError::InvalidSeeds);
- }
-
- if !wallet_account_info.is_signer {
- msg!("Wallet of the owner associated token account must sign");
- return Err(ProgramError::MissingRequiredSignature);
- }
-
- if owner_token_mint_info.owner != spl_token_program_id {
- msg!("Owner mint not owned by provided token program");
- return Err(ProgramError::IllegalOwner);
- }
-
- // Account data is dropped at the end of this, so the CPI can succeed
- // without a double-borrow
- let (amount, decimals) = {
- // Check owner associated token account data
- if owner_associated_token_account_info.owner != spl_token_program_id {
- msg!("Owner associated token account not owned by provided token program, recreate the owner associated token account first");
- return Err(ProgramError::IllegalOwner);
- }
- let owner_account_data = owner_associated_token_account_info.data.borrow();
- let owner_account = StateWithExtensions::::unpack(&owner_account_data)?;
- if owner_account.base.owner != *wallet_account_info.key {
- msg!("Owner associated token account not owned by provided wallet");
- return Err(AssociatedTokenAccountError::InvalidOwner.into());
- }
-
- // Check nested associated token account data
- if nested_associated_token_account_info.owner != spl_token_program_id {
- msg!("Nested associated token account not owned by provided token program");
- return Err(ProgramError::IllegalOwner);
- }
- let nested_account_data = nested_associated_token_account_info.data.borrow();
- let nested_account = StateWithExtensions::::unpack(&nested_account_data)?;
- if nested_account.base.owner != *owner_associated_token_account_info.key {
- msg!("Nested associated token account not owned by provided associated token account");
- return Err(AssociatedTokenAccountError::InvalidOwner.into());
- }
- let amount = nested_account.base.amount;
-
- // Check nested token mint data
- if nested_token_mint_info.owner != spl_token_program_id {
- msg!("Nested mint account not owned by provided token program");
- return Err(ProgramError::IllegalOwner);
- }
- let nested_mint_data = nested_token_mint_info.data.borrow();
- let nested_mint = StateWithExtensions::::unpack(&nested_mint_data)?;
- let decimals = nested_mint.base.decimals;
- (amount, decimals)
- };
-
- // Transfer everything out
- let owner_associated_token_account_signer_seeds: &[&[_]] = &[
- &wallet_account_info.key.to_bytes(),
- &spl_token_program_id.to_bytes(),
- &owner_token_mint_info.key.to_bytes(),
- &[bump_seed],
- ];
- invoke_signed(
- &spl_token_2022::instruction::transfer_checked(
- spl_token_program_id,
- nested_associated_token_account_info.key,
- nested_token_mint_info.key,
- destination_associated_token_account_info.key,
- owner_associated_token_account_info.key,
- &[],
- amount,
- decimals,
- )?,
- &[
- nested_associated_token_account_info.clone(),
- nested_token_mint_info.clone(),
- destination_associated_token_account_info.clone(),
- owner_associated_token_account_info.clone(),
- spl_token_program_info.clone(),
- ],
- &[owner_associated_token_account_signer_seeds],
- )?;
-
- // Close the nested account so it's never used again
- invoke_signed(
- &spl_token_2022::instruction::close_account(
- spl_token_program_id,
- nested_associated_token_account_info.key,
- wallet_account_info.key,
- owner_associated_token_account_info.key,
- &[],
- )?,
- &[
- nested_associated_token_account_info.clone(),
- wallet_account_info.clone(),
- owner_associated_token_account_info.clone(),
- spl_token_program_info.clone(),
- ],
- &[owner_associated_token_account_signer_seeds],
- )
-}
diff --git a/associated-token-account/program/src/tools/account.rs b/associated-token-account/program/src/tools/account.rs
deleted file mode 100644
index 2001e227e50..00000000000
--- a/associated-token-account/program/src/tools/account.rs
+++ /dev/null
@@ -1,100 +0,0 @@
-//! Account utility functions
-
-use {
- solana_program::{
- account_info::AccountInfo,
- entrypoint::ProgramResult,
- program::{get_return_data, invoke, invoke_signed},
- program_error::ProgramError,
- pubkey::Pubkey,
- rent::Rent,
- system_instruction,
- },
- spl_token_2022::extension::ExtensionType,
- std::convert::TryInto,
-};
-
-/// Creates associated token account using Program Derived Address for the given
-/// seeds
-pub fn create_pda_account<'a>(
- payer: &AccountInfo<'a>,
- rent: &Rent,
- space: usize,
- owner: &Pubkey,
- system_program: &AccountInfo<'a>,
- new_pda_account: &AccountInfo<'a>,
- new_pda_signer_seeds: &[&[u8]],
-) -> ProgramResult {
- if new_pda_account.lamports() > 0 {
- let required_lamports = rent
- .minimum_balance(space)
- .max(1)
- .saturating_sub(new_pda_account.lamports());
-
- if required_lamports > 0 {
- invoke(
- &system_instruction::transfer(payer.key, new_pda_account.key, required_lamports),
- &[
- payer.clone(),
- new_pda_account.clone(),
- system_program.clone(),
- ],
- )?;
- }
-
- invoke_signed(
- &system_instruction::allocate(new_pda_account.key, space as u64),
- &[new_pda_account.clone(), system_program.clone()],
- &[new_pda_signer_seeds],
- )?;
-
- invoke_signed(
- &system_instruction::assign(new_pda_account.key, owner),
- &[new_pda_account.clone(), system_program.clone()],
- &[new_pda_signer_seeds],
- )
- } else {
- invoke_signed(
- &system_instruction::create_account(
- payer.key,
- new_pda_account.key,
- rent.minimum_balance(space).max(1),
- space as u64,
- owner,
- ),
- &[
- payer.clone(),
- new_pda_account.clone(),
- system_program.clone(),
- ],
- &[new_pda_signer_seeds],
- )
- }
-}
-
-/// Determines the required initial data length for a new token account based on
-/// the extensions initialized on the Mint
-pub fn get_account_len<'a>(
- mint: &AccountInfo<'a>,
- spl_token_program: &AccountInfo<'a>,
- extension_types: &[ExtensionType],
-) -> Result {
- invoke(
- &spl_token_2022::instruction::get_account_data_size(
- spl_token_program.key,
- mint.key,
- extension_types,
- )?,
- &[mint.clone(), spl_token_program.clone()],
- )?;
- get_return_data()
- .ok_or(ProgramError::InvalidInstructionData)
- .and_then(|(key, data)| {
- if key != *spl_token_program.key {
- return Err(ProgramError::IncorrectProgramId);
- }
- data.try_into()
- .map(usize::from_le_bytes)
- .map_err(|_| ProgramError::InvalidInstructionData)
- })
-}
diff --git a/associated-token-account/program/src/tools/mod.rs b/associated-token-account/program/src/tools/mod.rs
deleted file mode 100644
index 5cb1ab5f753..00000000000
--- a/associated-token-account/program/src/tools/mod.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-//! Utility functions
-
-pub mod account;
diff --git a/binary-option/program/Cargo.toml b/binary-option/program/Cargo.toml
index fba2c8613f7..b9b64a6b6e1 100644
--- a/binary-option/program/Cargo.toml
+++ b/binary-option/program/Cargo.toml
@@ -11,7 +11,7 @@ test-sbf = []
[dependencies]
solana-program = "2.1.0"
thiserror = "2.0"
-spl-token = { version = "7.0", path = "../../token/program", features = [
+spl-token = { version = "7.0", features = [
"no-entrypoint",
] }
arrayref = "0.3.9"
diff --git a/binary-oracle-pair/program/Cargo.toml b/binary-oracle-pair/program/Cargo.toml
index 72d27062941..afea331bd9d 100644
--- a/binary-oracle-pair/program/Cargo.toml
+++ b/binary-oracle-pair/program/Cargo.toml
@@ -14,7 +14,7 @@ test-sbf = []
num-derive = "0.4"
num-traits = "0.2"
solana-program = "2.1.0"
-spl-token = { version = "7.0", path = "../../token/program", features = [
+spl-token = { version = "7.0", features = [
"no-entrypoint",
] }
thiserror = "2.0"
diff --git a/ci/js-test-libraries.sh b/ci/js-test-libraries.sh
deleted file mode 100755
index 9d8ef554e54..00000000000
--- a/ci/js-test-libraries.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-cd "$(dirname "$0")/.."
-
-set -x
-pnpm install
-pnpm format
-
-cd libraries/type-length-value/js
-pnpm lint
-pnpm build
-pnpm test
diff --git a/ci/js-test-single-pool.sh b/ci/js-test-single-pool.sh
deleted file mode 100755
index 63ae054e328..00000000000
--- a/ci/js-test-single-pool.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-cd "$(dirname "$0")/.."
-source ./ci/solana-version.sh install
-
-pnpm install
-pnpm format
-
-cd single-pool/js/packages/modern
-pnpm lint
-pnpm build
-
-cd ../classic
-pnpm build:program
-pnpm lint
-pnpm build
-pnpm test
diff --git a/ci/js-test-stake-pool.sh b/ci/js-test-stake-pool.sh
deleted file mode 100755
index 500e96acfd5..00000000000
--- a/ci/js-test-stake-pool.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-cd "$(dirname "$0")/.."
-
-pnpm install
-pnpm format
-pnpm build
-
-cd stake-pool/js
-pnpm lint
-pnpm test
diff --git a/ci/js-test-token-group.sh b/ci/js-test-token-group.sh
deleted file mode 100755
index daead80d8bf..00000000000
--- a/ci/js-test-token-group.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-cd "$(dirname "$0")/.."
-
-set -x
-pnpm install
-pnpm format
-pnpm build
-
-cd token-group/js
-pnpm lint
-pnpm test
diff --git a/ci/js-test-token-metadata.sh b/ci/js-test-token-metadata.sh
deleted file mode 100755
index c12a3ebcb40..00000000000
--- a/ci/js-test-token-metadata.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-cd "$(dirname "$0")/.."
-
-set -x
-pnpm install
-pnpm format
-pnpm build
-
-cd token-metadata/js
-pnpm lint
-pnpm test
diff --git a/ci/js-test-token.sh b/ci/js-test-token.sh
deleted file mode 100755
index 089ee200c66..00000000000
--- a/ci/js-test-token.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-cd "$(dirname "$0")/.."
-source ./ci/solana-version.sh install
-
-set -x
-pnpm install
-pnpm format
-pnpm build
-
-cd token/js
-pnpm build:program
-pnpm lint
-pnpm test
diff --git a/ci/py-test-stake-pool.sh b/ci/py-test-stake-pool.sh
deleted file mode 100755
index 4c3ca8cfe72..00000000000
--- a/ci/py-test-stake-pool.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-cd "$(dirname "$0")/.."
-source ./ci/solana-version.sh install
-
-cd stake-pool/py
-python3 -m venv venv
-source ./venv/bin/activate
-pip3 install -r requirements.txt
-pip3 install -r optional-requirements.txt
-check_dirs=(
- "bot"
- "spl_token"
- "stake"
- "stake_pool"
- "system"
- "tests"
- "vote"
-)
-flake8 "${check_dirs[@]}"
-mypy "${check_dirs[@]}"
-python3 -m pytest
diff --git a/coverage.sh b/coverage.sh
index cb12b4b493a..edaca0b88ba 100755
--- a/coverage.sh
+++ b/coverage.sh
@@ -22,7 +22,6 @@ reportName="lcov-${CI_COMMIT:0:9}"
if [[ -z $1 ]]; then
programs=(
libraries/math
- token/program
token-lending/program
token-swap/program
)
diff --git a/docs/src/associated-token-account.md b/docs/src/associated-token-account.md
index 0fefb54858c..ff23010aa7c 100644
--- a/docs/src/associated-token-account.md
+++ b/docs/src/associated-token-account.md
@@ -38,10 +38,10 @@ document are available at:
## Source
The Associated Token Account Program's source is available on
-[GitHub](https://github.com/solana-labs/solana-program-library).
-
+[GitHub](https://github.com/solana-program/associated-token-account).
## Interface
+
The Associated Token Account Program is written in Rust and available on
[crates.io](https://crates.io/crates/spl-associated-token-account) and
[docs.rs](https://docs.rs/spl-associated-token-account).
diff --git a/docs/src/feature-proposal.md b/docs/src/feature-proposal.md
index ec560b2378e..705d991ad0c 100644
--- a/docs/src/feature-proposal.md
+++ b/docs/src/feature-proposal.md
@@ -35,7 +35,7 @@ when appropriate.
## Source
The Feature Proposal Program's source is available on
-[GitHub](https://github.com/solana-labs/solana-program-library)
+[GitHub](https://github.com/solana-program/feature-proposal).
## Interface
The Feature Proposal Program is written in Rust and available on [crates.io](https://crates.io/crates/spl-feature-proposal) and [docs.rs](https://docs.rs/spl-feature-proposal).
@@ -58,7 +58,7 @@ This section describes the life cycle of a feature proposal.
### Implement the Feature
The first step is to conceive of the new feature and realize it in the
-Solana code base, working with the core Solana developers at https://github.com/solana-labs/solana.
+Solana code base, working with the core Solana developers at https://github.com/anza-xyz/agave
During the implementation, a *feature id* will be required to identify the new
feature in the code base to avoid the new functionality until its activation.
diff --git a/docs/src/single-pool.mdx b/docs/src/single-pool.mdx
index 197c3cacbae..357a025d296 100644
--- a/docs/src/single-pool.mdx
+++ b/docs/src/single-pool.mdx
@@ -24,7 +24,7 @@ The program is a stripped-down adaptation of the existing multi-validator stake
## Source
The Single Pool Program's source is available on
-[GitHub](https://github.com/solana-labs/solana-program-library/tree/master/single-pool/program).
+[GitHub](https://github.com/solana-program/single-pool).
## Security Audits
@@ -32,13 +32,13 @@ The Single Pool Program has received three audits to ensure total safety of fund
* Zellic (2024-01-02)
- Review commit hash [`ef44df9`](https://github.com/solana-labs/solana-program-library/commit/ef44df985e76a697ee9a8aabb3a223610e4cf1dc)
- - Final report https://github.com/solana-labs/security-audits/blob/master/spl/ZellicSinglePoolAudit-2024-01-02.pdf
+ - Final report https://github.com/anza-xyz/security-audits/blob/master/spl/ZellicSinglePoolAudit-2024-01-02.pdf
* Neodyme (2023-08-08)
- Review commit hash [`735d729`](https://github.com/solana-labs/solana-program-library/commit/735d7292e35d35101750a4452d2647bdbf848e8b)
- - Final report https://github.com/solana-labs/security-audits/blob/master/spl/NeodymeSinglePoolAudit-2023-08-08.pdf
+ - Final report https://github.com/anza-xyz/security-audits/blob/master/spl/NeodymeSinglePoolAudit-2023-08-08.pdf
* Zellic (2023-06-21)
- Review commit hash [`9dbdc3b`](https://github.com/solana-labs/solana-program-library/commit/9dbdc3bdae31dda1dcb35346aab2d879deecf194)
- - Final report https://github.com/solana-labs/security-audits/blob/master/spl/ZellicSinglePoolAudit-2023-06-21.pdf
+ - Final report https://github.com/anza-xyz/security-audits/blob/master/spl/ZellicSinglePoolAudit-2023-06-21.pdf
## Interface
diff --git a/docs/src/stake-pool.md b/docs/src/stake-pool.md
index 8f630abb81d..637b32c33e8 100644
--- a/docs/src/stake-pool.md
+++ b/docs/src/stake-pool.md
@@ -27,7 +27,7 @@ To get started with stake pools:
## Source
The Stake Pool Program's source is available on
-[GitHub](https://github.com/solana-labs/solana-program-library/tree/master/stake-pool).
+[GitHub](https://github.com/solana-program/stake-pool).
For information about the types and instructions, the Stake Pool Rust docs are
available at [docs.rs](https://docs.rs/spl-stake-pool/latest/spl_stake_pool/index.html).
@@ -41,28 +41,28 @@ chronological order, and the commit hash that each was reviewed at:
* Quantstamp
- Initial review commit hash [`99914c9`](https://github.com/solana-labs/solana-program-library/tree/99914c9fc7246b22ef04416586ab1722c89576de)
- Re-review commit hash [`3b48fa0`](https://github.com/solana-labs/solana-program-library/tree/3b48fa09d38d1b66ffb4fef186b606f1bc4fdb31)
- - Final report https://github.com/solana-labs/security-audits/blob/master/spl/QuantstampStakePoolAudit-2021-10-22.pdf
+ - Final report https://github.com/anza-xyz/security-audits/blob/master/spl/QuantstampStakePoolAudit-2021-10-22.pdf
* Neodyme
- Review commit hash [`0a85a9a`](https://github.com/solana-labs/solana-program-library/tree/0a85a9a533795b6338ea144e433893c6c0056210)
- - Report https://github.com/solana-labs/security-audits/blob/master/spl/NeodymeStakePoolAudit-2021-10-16.pdf
+ - Report https://github.com/anza-xyz/security-audits/blob/master/spl/NeodymeStakePoolAudit-2021-10-16.pdf
* Kudelski
- Review commit hash [`3dd6767`](https://github.com/solana-labs/solana-program-library/tree/3dd67672974f92d3b648bb50ee74f4747a5f8973)
- - Report https://github.com/solana-labs/security-audits/blob/master/spl/KudelskiStakePoolAudit-2021-07-07.pdf
+ - Report https://github.com/anza-xyz/security-audits/blob/master/spl/KudelskiStakePoolAudit-2021-07-07.pdf
* Neodyme Second Audit
- Review commit hash [`fd92ccf`](https://github.com/solana-labs/solana-program-library/tree/fd92ccf9e9308508b719d6e5f36474f57023b0b2)
- - Report https://github.com/solana-labs/security-audits/blob/master/spl/NeodymeStakePoolAudit-2022-12-10.pdf
+ - Report https://github.com/anza-xyz/security-audits/blob/master/spl/NeodymeStakePoolAudit-2022-12-10.pdf
* OtterSec
- Review commit hash [`eba709b`](https://github.com/solana-labs/solana-program-library/tree/eba709b9317f8c7b8b197045161cb744241f0bff)
- - Report https://github.com/solana-labs/security-audits/blob/master/spl/OtterSecStakePoolAudit-2023-01-20.pdf
+ - Report https://github.com/anza-xyz/security-audits/blob/master/spl/OtterSecStakePoolAudit-2023-01-20.pdf
* Neodyme Third Audit
- Review commit hash [`b341022`](https://github.com/solana-labs/solana-program-library/tree/b34102211f2a5ea6b83f3ee22f045fb115d87813)
- - Report https://github.com/solana-labs/security-audits/blob/master/spl/NeodymeStakePoolAudit-2023-01-31.pdf
+ - Report https://github.com/anza-xyz/security-audits/blob/master/spl/NeodymeStakePoolAudit-2023-01-31.pdf
* Halborn
- Review commit hash [`eba709b`](https://github.com/solana-labs/solana-program-library/tree/eba709b9317f8c7b8b197045161cb744241f0bff)
- - Report https://github.com/solana-labs/security-audits/blob/master/spl/HalbornStakePoolAudit-2023-01-25.pdf
+ - Report https://github.com/anza-xyz/security-audits/blob/master/spl/HalbornStakePoolAudit-2023-01-25.pdf
* Neodyme Fourth Audit
- Review commit hash [`6ed7254`](https://github.com/solana-labs/solana-program-library/tree/6ed7254d1a578ffbc2b091d28cb92b25e7cc511d)
- - Report https://github.com/solana-labs/security-audits/blob/master/spl/NeodymeStakePoolAudit-2023-11-14.pdf
+ - Report https://github.com/anza-xyz/security-audits/blob/master/spl/NeodymeStakePoolAudit-2023-11-14.pdf
* Halborn Second Audit
- Review commit hash [`a17fffe`](https://github.com/solana-labs/solana-program-library/tree/a17fffe70d6cc13742abfbc4a4a375b087580bc1)
- - Report https://github.com/solana-labs/security-audits/blob/master/spl/HalbornStakePoolAudit-2023-12-31.pdf
+ - Report https://github.com/anza-xyz/security-audits/blob/master/spl/HalbornStakePoolAudit-2023-12-31.pdf
diff --git a/docs/src/token-2022.md b/docs/src/token-2022.md
index 21fb3d866b2..c4aa63f2055 100644
--- a/docs/src/token-2022.md
+++ b/docs/src/token-2022.md
@@ -82,7 +82,7 @@ is written after the end of the `Account` in Token, which is the byte at index
`165`. This means it is always possible to differentiate mints and accounts.
You can read more about how this is done at the
-[source code](https://github.com/solana-labs/solana-program-library/blob/master/token/program-2022/src/extension/mod.rs).
+[source code](https://github.com/solana-program/token-2022/blob/main/program/src/extension/mod.rs).
Mint extensions currently include:
@@ -128,7 +128,7 @@ The Token functionality will always apply to Token-2022.
## Source
The Token-2022 Program's source is available on
-[GitHub](https://github.com/solana-labs/solana-program-library/tree/master/token/program-2022).
+[GitHub](https://github.com/solana-program/token-2022).
For information about the types and instructions, the Rust docs are available at
[docs.rs](https://docs.rs/spl-token-2022/latest/spl_token_2022/).
@@ -142,19 +142,19 @@ Here are the completed audits as of 13 December 2023:
* Halborn
- Review commit hash [`c3137a`](https://github.com/solana-labs/solana-program-library/tree/c3137af9dfa2cc0873cc84c4418dea88ac542965/token/program-2022)
- - Final report https://github.com/solana-labs/security-audits/blob/master/spl/HalbornToken2022Audit-2022-07-27.pdf
+ - Final report https://github.com/anza-xyz/security-audits/blob/master/spl/HalbornToken2022Audit-2022-07-27.pdf
* Zellic
- Review commit hash [`54695b`](https://github.com/solana-labs/solana-program-library/tree/54695b233484722458b18c0e26ebb8334f98422c/token/program-2022)
- - Final report https://github.com/solana-labs/security-audits/blob/master/spl/ZellicToken2022Audit-2022-12-05.pdf
+ - Final report https://github.com/anza-xyz/security-audits/blob/master/spl/ZellicToken2022Audit-2022-12-05.pdf
* Trail of Bits
- Review commit hash [`50abad`](https://github.com/solana-labs/solana-program-library/tree/50abadd819df2e406567d6eca31c213264c1c7cd/token/program-2022)
- - Final report https://github.com/solana-labs/security-audits/blob/master/spl/TrailOfBitsToken2022Audit-2023-02-10.pdf
+ - Final report https://github.com/anza-xyz/security-audits/blob/master/spl/TrailOfBitsToken2022Audit-2023-02-10.pdf
* NCC Group
- Review commit hash [`4e43aa`](https://github.com/solana-labs/solana/tree/4e43aa6c18e6bb4d98559f80eb004de18bc6b418/zk-token-sdk)
- - Final report https://github.com/solana-labs/security-audits/blob/master/spl/NCCToken2022Audit-2023-04-05.pdf
+ - Final report https://github.com/anza-xyz/security-audits/blob/master/spl/NCCToken2022Audit-2023-04-05.pdf
* OtterSec
- Review commit hash [`e92413`](https://github.com/solana-labs/solana-program-library/tree/e924132d65ba0896249fb4983f6f97caff15721a)
- - Final report https://github.com/solana-labs/security-audits/blob/master/spl/OtterSecToken2022Audit-2023-11-03.pdf
+ - Final report https://github.com/anza-xyz/security-audits/blob/master/spl/OtterSecToken2022Audit-2023-11-03.pdf
* OtterSec (ZK Token SDK)
- Review commit hash [`9e703f8`](https://github.com/solana-labs/solana/tree/9e703f8/zk-token-sdk)
- - Final report https://github.com/solana-labs/security-audits/blob/master/spl/OtterSecZkTokenSdkAudit-2023-11-04.pdf
+ - Final report https://github.com/anza-xyz/security-audits/blob/master/spl/OtterSecZkTokenSdkAudit-2023-11-04.pdf
diff --git a/docs/src/token-2022/extensions.mdx b/docs/src/token-2022/extensions.mdx
index 12965fee813..4fd48665e1f 100644
--- a/docs/src/token-2022/extensions.mdx
+++ b/docs/src/token-2022/extensions.mdx
@@ -22,7 +22,7 @@ See the [Token Setup Guide](../token#setup) to install the client utilities.
Token-2022 shares the same CLI and NPM packages for maximal compatibility.
All JS examples are adapted from the tests, and available in full at the
-[Token JS examples](https://github.com/solana-labs/solana-program-library/tree/master/token/js/examples).
+[Token JS examples](https://github.com/solana-program/token-2022/tree/main/clients/js-legacy/examples).
## Extensions
@@ -1528,29 +1528,29 @@ explained in detail in many of the linked `README` files below under
#### Resources
The interface description and structs exist at
-[spl-transfer-hook-interface](https://github.com/solana-labs/solana-program-library/tree/master/token/transfer-hook/interface),
+[spl-transfer-hook-interface](https://github.com/solana-program/transfer-hook/tree/main/interface),
along with a sample minimal program implementation. You can find detailed
instructions on how to implement this interface for an on-chain program or
interact with a program that implements transfer-hook in the repository's
-[README](https://github.com/solana-labs/solana-program-library/tree/master/token/transfer-hook/interface/README.md).
+[README](https://github.com/solana-program/transfer-hook/tree/main/interface/README.md).
The `spl-transfer-hook-interface` library provides offchain and onchain helpers
for resolving the additional accounts required. See
-[onchain.rs](https://github.com/solana-labs/solana-program-library/blob/master/token/transfer-hook/interface/src/onchain.rs)
+[onchain.rs](https://github.com/solana-program/transfer-hook/blob/main/interface/src/onchain.rs)
for usage on-chain, and
-[offchain.rs](https://github.com/solana-labs/solana-program-library/tree/master/token/transfer-hook/interface/src/offchain.rs)
+[offchain.rs](https://github.com/solana-program/transfer-hook/blob/main/interface/src/offchain.rs)
for fetching the additional required account metas with any async off-chain client
like `BanksClient` or `RpcClient`.
A usable example program exists at
-[spl-transfer-hook-example](https://github.com/solana-labs/solana-program-library/tree/master/token/transfer-hook/example).
+[spl-transfer-hook-example](https://github.com/solana-program/transfer-hook/tree/main/program).
Token-2022 uses this example program in tests to ensure that it properly uses
the transfer hook interface.
The example program and the interface are powered by the
-[spl-tlv-account-resolution](https://github.com/solana-labs/solana-program-library/tree/master/libraries/tlv-account-resolution)
+[spl-tlv-account-resolution](https://github.com/solana-program/libraries/tree/main/tlv-account-resolution)
library, which is explained in detail in the repository's
-[README](https://github.com/solana-labs/solana-program-library/tree/master/libraries/tlv-account-resolution/README.md)
+[README](https://github.com/solana-program/libraries/tree/main/tlv-account-resolution/README.md)
#### Example: Create a mint with a transfer hook
@@ -1660,7 +1660,7 @@ await updateTransferHook(
#### Example: Manage a transfer-hook program
A sample CLI for managing a transfer-hook program exists at
-[spl-transfer-hook-cli](https://github.com/solana-labs/solana-program-library/tree/master/token/transfer-hook/cli).
+[spl-transfer-hook-cli](https://github.com/solana-program/transfer-hook/tree/main/clients/cli).
A mint manager can fork the tool for their own program.
It only contains a command to create the required transfer-hook account for the
@@ -1720,7 +1720,7 @@ To facilitate token-metadata usage, Token-2022 allows a mint creator to include
their token's metadata directly in the mint account.
Token-2022 implements all of the instructions from the
-[spl-token-metadata-interface](https://github.com/solana-labs/solana-program-library/tree/master/token-metadata/interface).
+[spl-token-metadata-interface](https://github.com/solana-program/token-metadata/tree/main/interface).
The metadata extension should work directly with the metadata-pointer extension.
During mint creation, you should also add the metadata-pointer extension, pointed
@@ -1966,7 +1966,7 @@ configurations for a group, which describe things like the update authority
and the group's maximum size, can be stored directly in the mint itself.
Token-2022 implements all of the instructions from the
-[spl-token-group-interface](https://github.com/solana-labs/solana-program-library/tree/master/token-group/interface).
+[spl-token-group-interface](https://github.com/solana-program/token-group/tree/main/interface).
The group extension works directly with the group-pointer extension.
To initialize group configurations within a mint, you must add the group-pointer
diff --git a/docs/src/token.mdx b/docs/src/token.mdx
index 65397ac1658..cb68488ce67 100644
--- a/docs/src/token.mdx
+++ b/docs/src/token.mdx
@@ -22,17 +22,17 @@ document are available at:
## Source
The Token Program's source is available on
-[GitHub](https://github.com/solana-labs/solana-program-library)
+[GitHub](https://github.com/solana-program/token).
## Interface
The Token Program is written in Rust and available on [crates.io](https://crates.io/crates/spl-token) and [docs.rs](https://docs.rs/spl-token).
Auto-generated C bindings are also available
-[here](https://github.com/solana-labs/solana-program-library/blob/master/token/program/inc/token.h)
+[here](https://github.com/solana-program/token/blob/main/program/inc/token.h)
[JavaScript
-bindings](https://github.com/solana-labs/solana-program-library/tree/master/token/js)
+bindings](https://github.com/solana-program/token-2022/tree/main/clients/js-legacy)
are available that support loading the Token Program on to a chain and issue
instructions.
diff --git a/docs/src/transfer-hook-interface.md b/docs/src/transfer-hook-interface.md
index a39f36adf87..b7d12bdc4c4 100644
--- a/docs/src/transfer-hook-interface.md
+++ b/docs/src/transfer-hook-interface.md
@@ -9,7 +9,7 @@ During transfers, Token-2022 calls a mint's configured transfer hook program
using this interface, as described in the
[Transfer Hook Extension Guide](../../token-2022/extensions#transfer-hook).
Additionally, a
-[reference implementation](https://github.com/solana-labs/solana-program-library/tree/master/token/transfer-hook/example)
+[reference implementation](https://github.com/solana-program/transfer-hook/tree/main/program)
can be found in the SPL GitHub repository, detailing
how one might implement this interface in their own program.
diff --git a/docs/src/transfer-hook-interface/configuring-extra-accounts.md b/docs/src/transfer-hook-interface/configuring-extra-accounts.md
index 7de29932ccb..2587b69929d 100644
--- a/docs/src/transfer-hook-interface/configuring-extra-accounts.md
+++ b/docs/src/transfer-hook-interface/configuring-extra-accounts.md
@@ -43,7 +43,7 @@ of entries.
This custom slice structure is called a `PodSlice` and is part of the Solana
Program Library's
-[Pod](https://github.com/solana-labs/solana-program-library/tree/master/libraries/pod)
+[Pod](https://github.com/solana-program/libraries/tree/main/pod)
library. The Pod library provides a handful of fixed-length types that
implement the `bytemuck`
[`Pod`](https://docs.rs/bytemuck/latest/bytemuck/trait.Pod.html) trait, as well
@@ -51,7 +51,7 @@ as the `PodSlice`.
Another SPL library
useful for Type-Length-Value encoded data is
-[Type-Length-Value](https://github.com/solana-labs/solana-program-library/tree/master/libraries/type-length-value)
+[Type-Length-Value](https://github.com/solana-program/libraries/tree/main/type-length-value)
which is used extensively to manage TLV-encoded data structures.
### Dynamic Account Resolution
@@ -62,7 +62,7 @@ required accounts you've specified in the validation account.
These additional accounts must be _resolved_, and another library used to pull off
the resolution of additional accounts for transfer hooks is
-[TLV Account Resolution](https://github.com/solana-labs/solana-program-library/tree/master/libraries/tlv-account-resolution).
+[TLV Account Resolution](https://github.com/solana-program/libraries/tree/main/tlv-account-resolution).
Using the TLV Account Resolution library, transfer hook programs can empower
**dynamic account resolution** of additional required accounts. This means that
@@ -72,9 +72,9 @@ validation account's data.
In fact, the Transfer Hook interface offers helpers that perform this account
resolution in the
-[onchain](https://github.com/solana-labs/solana-program-library/blob/master/token/transfer-hook/interface/src/onchain.rs)
+[onchain](https://github.com/solana-program/transfer-hook/blob/main/interface/src/onchain.rs)
and
-[offchain](https://github.com/solana-labs/solana-program-library/blob/master/token/transfer-hook/interface/src/offchain.rs)
+[offchain](https://github.com/solana-program/transfer-hook/blob/main/interface/src/offchain.rs)
modules of the Transfer Hook interface crate.
The account resolution is powered by the way configurations for additional
@@ -84,7 +84,7 @@ and roles (signer, writeable, etc.) for accounts.
### The `ExtraAccountMeta` Struct
A member of the TLV Account Resolution library, the
-[`ExtraAccountMeta`](https://github.com/solana-labs/solana-program-library/blob/65a92e6e0a4346920582d9b3893cacafd85bb017/libraries/tlv-account-resolution/src/account.rs#L75)
+[`ExtraAccountMeta`](https://github.com/solana-program/libraries/blob/c5cc979f188ddc136de2ff556173a6f655322915/tlv-account-resolution/src/account.rs#L123)
struct allows account configurations to be serialized into a fixed-length data
format of length 35 bytes.
@@ -130,7 +130,7 @@ Well, you don't. Instead, you tell the account resolution functionality _where_
to find the seeds you need.
To do this, the transfer hook program can use the
-[`Seed`](https://github.com/solana-labs/solana-program-library/blob/65a92e6e0a4346920582d9b3893cacafd85bb017/libraries/tlv-account-resolution/src/seeds.rs#L38)
+[`Seed`](https://github.com/solana-program/libraries/blob/c5cc979f188ddc136de2ff556173a6f655322915/tlv-account-resolution/src/seeds.rs#L38)
enum to describe their seeds and where to find them. With the exception of
literals, these seed configurations comprise only a small handful of bytes.
diff --git a/docs/src/transfer-hook-interface/examples.md b/docs/src/transfer-hook-interface/examples.md
index 7cc01943081..7a4fc1ed0b8 100644
--- a/docs/src/transfer-hook-interface/examples.md
+++ b/docs/src/transfer-hook-interface/examples.md
@@ -3,14 +3,14 @@ title: Examples
---
More examples can be found in the
-[Transfer Hook example tests](https://github.com/solana-labs/solana-program-library/blob/master/token/transfer-hook/example/tests/functional.rs),
+[Transfer Hook example tests](https://github.com/solana-program/transfer-hook/blob/main/program/tests/functional.rs),
as well as the
-[TLV Account Resolution tests](https://github.com/solana-labs/solana-program-library/blob/master/libraries/tlv-account-resolution/src/state.rs).
+[TLV Account Resolution tests](https://github.com/solana-program/libraries/blob/main/tlv-account-resolution/src/state.rs).
### Initializing Extra Account Metas On-Chain
The
-[`ExtraAccountMetaList`](https://github.com/solana-labs/solana-program-library/blob/65a92e6e0a4346920582d9b3893cacafd85bb017/libraries/tlv-account-resolution/src/state.rs#L167)
+[`ExtraAccountMetaList`](https://github.com/solana-program/libraries/blob/c5cc979f188ddc136de2ff556173a6f655322915/tlv-account-resolution/src/state.rs#L164)
struct is designed to make working with extra account
configurations as seamless as possible.
@@ -19,12 +19,12 @@ serialized `ExtraAccountMeta` configurations by simply providing a mutable
reference to the buffer and a slice of `ExtraAccountMeta`. The generic `T` is
the instruction whose discriminator the extra account configurations should be
assigned to. In our case, this will be
-[`spl_transfer_hook_interface::instruction::ExecuteInstruction`](https://github.com/solana-labs/solana-program-library/blob/eb32c5e72c6d917e732bded9863db7657b23e428/token/transfer-hook/interface/src/instruction.rs#L68)
+[`spl_transfer_hook_interface::instruction::ExecuteInstruction`](https://github.com/solana-program/transfer-hook/blob/e00f3b5c591fd55b4aed6a1e9b1ccc502cb6da05/interface/src/instruction.rs#L67)
from the Transfer Hook interface.
> Note: All instructions from the SPL Transfer Hook interface implement the
> trait
-> [`SplDiscriminate`](https://github.com/solana-labs/solana-program-library/blob/65a92e6e0a4346920582d9b3893cacafd85bb017/libraries/discriminator/src/discriminator.rs#L9),
+> [`SplDiscriminate`](https://github.com/solana-program/libraries/blob/c5cc979f188ddc136de2ff556173a6f655322915/discriminator/src/discriminator.rs#L10),
> which provides a constant 8-byte discriminator that
> can be used to create a TLV data entry.
@@ -83,7 +83,7 @@ program directly or for a program that will CPI to your transfer hook program,
you must include all required accounts - including the extra accounts.
Below is an example of the logic contained in the Transfer Hook interface's
-[offchain helper](https://github.com/solana-labs/solana-program-library/blob/65a92e6e0a4346920582d9b3893cacafd85bb017/token/transfer-hook/interface/src/offchain.rs#L50).
+[offchain helper](https://github.com/solana-program/transfer-hook/blob/e00f3b5c591fd55b4aed6a1e9b1ccc502cb6da05/interface/src/offchain.rs#L48).
```rust
// You'll need to provide an "account data function", which is a function that
@@ -151,7 +151,7 @@ offchain account resolution, the executing program has to know how to build a
CPI instruction with the proper accounts as well!
Below is an example of the logic contained in the Transfer Hook interface's
-[onchain helper](https://github.com/solana-labs/solana-program-library/blob/65a92e6e0a4346920582d9b3893cacafd85bb017/token/transfer-hook/interface/src/onchain.rs#L67).
+[onchain helper](https://github.com/solana-program/transfer-hook/blob/e00f3b5c591fd55b4aed6a1e9b1ccc502cb6da05/interface/src/onchain.rs#L15).
```rust
// Find the validation account from the list of `AccountInfo`s and load its
diff --git a/examples/rust/transfer-tokens/Cargo.toml b/examples/rust/transfer-tokens/Cargo.toml
index 05d0fd85b67..52f0e02c6e1 100644
--- a/examples/rust/transfer-tokens/Cargo.toml
+++ b/examples/rust/transfer-tokens/Cargo.toml
@@ -13,7 +13,7 @@ test-sbf = []
[dependencies]
solana-program = "2.1.0"
-spl-token = { version = "7.0", path = "../../../token/program", features = [ "no-entrypoint" ] }
+spl-token = { version = "7.0", features = [ "no-entrypoint" ] }
[dev-dependencies]
solana-program-test = "2.1.0"
diff --git a/feature-proposal/README.md b/feature-proposal/README.md
new file mode 100644
index 00000000000..b5637f9a4a5
--- /dev/null
+++ b/feature-proposal/README.md
@@ -0,0 +1,2 @@
+NOTE: The feature-proposal program and clients are now maintained at
+[solana-program/feature-proposal](https://github.com/solana-program/feature-proposal).
diff --git a/feature-proposal/cli/Cargo.toml b/feature-proposal/cli/Cargo.toml
deleted file mode 100644
index bc62d44e532..00000000000
--- a/feature-proposal/cli/Cargo.toml
+++ /dev/null
@@ -1,25 +0,0 @@
-[package]
-name = "spl-feature-proposal-cli"
-version = "1.2.0"
-description = "SPL Feature Proposal Command-line Utility"
-authors = ["Solana Labs Maintainers "]
-repository = "https://github.com/solana-labs/solana-program-library"
-license = "Apache-2.0"
-edition = "2021"
-
-[dependencies]
-chrono = "0.4.39"
-clap = "2.33.3"
-solana-clap-utils = "2.1.0"
-solana-cli-config = "2.1.0"
-solana-client = "2.1.0"
-solana-logger = "2.1.0"
-solana-sdk = "2.1.0"
-spl-feature-proposal = { version = "1.0", path = "../program", features = ["no-entrypoint"] }
-
-[[bin]]
-name = "spl-feature-proposal"
-path = "src/main.rs"
-
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu"]
diff --git a/feature-proposal/cli/src/main.rs b/feature-proposal/cli/src/main.rs
deleted file mode 100644
index e3a40fee622..00000000000
--- a/feature-proposal/cli/src/main.rs
+++ /dev/null
@@ -1,486 +0,0 @@
-#![allow(clippy::arithmetic_side_effects)]
-use {
- chrono::{DateTime, SecondsFormat, Utc},
- clap::{
- crate_description, crate_name, crate_version, value_t_or_exit, App, AppSettings, Arg,
- SubCommand,
- },
- solana_clap_utils::{
- input_parsers::{keypair_of, pubkey_of},
- input_validators::{is_keypair, is_url, is_valid_percentage, is_valid_pubkey},
- },
- solana_client::rpc_client::RpcClient,
- solana_sdk::{
- clock::UnixTimestamp,
- commitment_config::CommitmentConfig,
- program_pack::Pack,
- pubkey::Pubkey,
- signature::{read_keypair_file, Keypair, Signer},
- transaction::Transaction,
- },
- spl_feature_proposal::state::{AcceptanceCriteria, FeatureProposal},
- std::{
- collections::HashMap,
- fs::File,
- io::Write,
- time::{Duration, SystemTime, UNIX_EPOCH},
- },
-};
-
-struct Config {
- keypair: Keypair,
- json_rpc_url: String,
- verbose: bool,
-}
-
-fn main() -> Result<(), Box> {
- let app_matches = App::new(crate_name!())
- .about(crate_description!())
- .version(crate_version!())
- .setting(AppSettings::SubcommandRequiredElseHelp)
- .arg({
- let arg = Arg::with_name("config_file")
- .short("C")
- .long("config")
- .value_name("PATH")
- .takes_value(true)
- .global(true)
- .help("Configuration file to use");
- if let Some(ref config_file) = *solana_cli_config::CONFIG_FILE {
- arg.default_value(config_file)
- } else {
- arg
- }
- })
- .arg(
- Arg::with_name("keypair")
- .long("keypair")
- .value_name("KEYPAIR")
- .validator(is_keypair)
- .takes_value(true)
- .global(true)
- .help("Filepath or URL to a keypair [default: client keypair]"),
- )
- .arg(
- Arg::with_name("verbose")
- .long("verbose")
- .short("v")
- .takes_value(false)
- .global(true)
- .help("Show additional information"),
- )
- .arg(
- Arg::with_name("json_rpc_url")
- .long("url")
- .value_name("URL")
- .takes_value(true)
- .global(true)
- .validator(is_url)
- .help("JSON RPC URL for the cluster [default: value from configuration file]"),
- )
- .subcommand(
- SubCommand::with_name("address")
- .about("Display address information for the feature proposal")
- .arg(
- Arg::with_name("feature_proposal")
- .value_name("FEATURE_PROPOSAL_ADDRESS")
- .validator(is_valid_pubkey)
- .index(1)
- .required(true)
- .help("The address of the feature proposal"),
- ),
- )
- .subcommand(
- SubCommand::with_name("propose")
- .about("Initiate a feature proposal")
- .arg(
- Arg::with_name("feature_proposal")
- .value_name("FEATURE_PROPOSAL_KEYPAIR")
- .validator(is_keypair)
- .index(1)
- .required(true)
- .help("The keypair of the feature proposal"),
- )
- .arg(
- Arg::with_name("percent_stake_required")
- .long("percent-stake-required")
- .value_name("PERCENTAGE")
- .validator(is_valid_percentage)
- .required(true)
- .default_value("67")
- .help("Percentage of the active stake required for the proposal to pass"),
- )
- .arg(
- Arg::with_name("distribution_file")
- .long("distribution-file")
- .value_name("FILENAME")
- .required(true)
- .default_value("feature-proposal.csv")
- .help("Allocations CSV file for use with solana-tokens"),
- )
- .arg(
- Arg::with_name("confirm")
- .long("confirm")
- .help("Confirm that the feature proposal should actually be initiated"),
- ),
- )
- .subcommand(
- SubCommand::with_name("tally")
- .about("Tally the current results for a proposed feature")
- .arg(
- Arg::with_name("feature_proposal")
- .value_name("FEATURE_PROPOSAL_ADDRESS")
- .validator(is_valid_pubkey)
- .index(1)
- .required(true)
- .help("The address of the feature proposal"),
- ),
- )
- .get_matches();
-
- let (sub_command, sub_matches) = app_matches.subcommand();
- let matches = sub_matches.unwrap();
-
- let config = {
- let cli_config = if let Some(config_file) = matches.value_of("config_file") {
- solana_cli_config::Config::load(config_file).unwrap_or_default()
- } else {
- solana_cli_config::Config::default()
- };
-
- Config {
- json_rpc_url: matches
- .value_of("json_rpc_url")
- .unwrap_or(&cli_config.json_rpc_url)
- .to_string(),
- keypair: read_keypair_file(
- matches
- .value_of("keypair")
- .unwrap_or(&cli_config.keypair_path),
- )?,
- verbose: matches.is_present("verbose"),
- }
- };
- solana_logger::setup_with_default("solana=info");
- let rpc_client =
- RpcClient::new_with_commitment(config.json_rpc_url.clone(), CommitmentConfig::confirmed());
-
- match (sub_command, sub_matches) {
- ("address", Some(arg_matches)) => {
- let feature_proposal_address = pubkey_of(arg_matches, "feature_proposal").unwrap();
-
- println!(
- "Feature Id: {}",
- spl_feature_proposal::get_feature_id_address(&feature_proposal_address)
- );
- println!(
- "Token Mint Address: {}",
- spl_feature_proposal::get_mint_address(&feature_proposal_address)
- );
- println!(
- "Acceptance Token Address: {}",
- spl_feature_proposal::get_acceptance_token_address(&feature_proposal_address)
- );
-
- Ok(())
- }
- ("propose", Some(arg_matches)) => {
- let feature_proposal_keypair = keypair_of(arg_matches, "feature_proposal").unwrap();
- let distribution_file = value_t_or_exit!(arg_matches, "distribution_file", String);
- let percent_stake_required =
- value_t_or_exit!(arg_matches, "percent_stake_required", u8);
-
- // Hard code deadline for now...
- let fortnight = Duration::from_secs(60 * 60 * 24 * 14);
- let deadline = SystemTime::now()
- .duration_since(UNIX_EPOCH)
- .unwrap()
- .checked_add(fortnight)
- .unwrap()
- .as_secs() as UnixTimestamp;
-
- process_propose(
- &rpc_client,
- &config,
- &feature_proposal_keypair,
- distribution_file,
- percent_stake_required,
- deadline,
- arg_matches.is_present("confirm"),
- )
- }
- ("tally", Some(arg_matches)) => {
- if config.verbose {
- println!("JSON RPC URL: {}", config.json_rpc_url);
- }
-
- let feature_proposal_address = pubkey_of(arg_matches, "feature_proposal").unwrap();
- process_tally(&rpc_client, &config, &feature_proposal_address)
- }
- _ => unreachable!(),
- }
-}
-
-fn get_feature_proposal(
- rpc_client: &RpcClient,
- feature_proposal_address: &Pubkey,
-) -> Result {
- let account = rpc_client
- .get_multiple_accounts(&[*feature_proposal_address])
- .map_err(|err| err.to_string())?
- .into_iter()
- .next()
- .unwrap();
-
- match account {
- None => Err(format!(
- "Feature proposal {} does not exist",
- feature_proposal_address
- )),
- Some(account) => FeatureProposal::unpack_from_slice(&account.data).map_err(|err| {
- format!(
- "Failed to deserialize feature proposal {}: {}",
- feature_proposal_address, err
- )
- }),
- }
-}
-
-fn unix_timestamp_to_string(unix_timestamp: UnixTimestamp) -> String {
- format!(
- "{} (UnixTimestamp: {})",
- DateTime::::from_timestamp(unix_timestamp, 0)
- .map(|x| x.to_rfc3339_opts(SecondsFormat::Secs, true))
- .unwrap_or("unknown".to_string()),
- unix_timestamp,
- )
-}
-
-fn process_propose(
- rpc_client: &RpcClient,
- config: &Config,
- feature_proposal_keypair: &Keypair,
- distribution_file: String,
- percent_stake_required: u8,
- deadline: UnixTimestamp,
- confirm: bool,
-) -> Result<(), Box> {
- let distributor_token_address =
- spl_feature_proposal::get_distributor_token_address(&feature_proposal_keypair.pubkey());
- let feature_id_address =
- spl_feature_proposal::get_feature_id_address(&feature_proposal_keypair.pubkey());
- let acceptance_token_address =
- spl_feature_proposal::get_acceptance_token_address(&feature_proposal_keypair.pubkey());
- let mint_address = spl_feature_proposal::get_mint_address(&feature_proposal_keypair.pubkey());
-
- println!("Feature Id: {}", feature_id_address);
- println!("Token Mint Address: {}", mint_address);
- println!("Distributor Token Address: {}", distributor_token_address);
- println!("Acceptance Token Address: {}", acceptance_token_address);
-
- let vote_accounts = rpc_client.get_vote_accounts()?;
- let mut distribution = HashMap::new();
- for (pubkey, activated_stake) in vote_accounts
- .current
- .into_iter()
- .chain(vote_accounts.delinquent)
- .map(|vote_account| (vote_account.node_pubkey, vote_account.activated_stake))
- {
- distribution
- .entry(pubkey)
- .and_modify(|e| *e += activated_stake)
- .or_insert(activated_stake);
- }
-
- let tokens_to_mint: u64 = distribution.iter().map(|x| x.1).sum();
- let tokens_required = tokens_to_mint * percent_stake_required as u64 / 100;
-
- println!("Number of validators: {}", distribution.len());
- println!(
- "Tokens to be minted: {}",
- spl_feature_proposal::amount_to_ui_amount(tokens_to_mint)
- );
- println!(
- "Tokens required for acceptance: {} ({}%)",
- spl_feature_proposal::amount_to_ui_amount(tokens_required),
- percent_stake_required
- );
-
- println!("Token distribution file: {}", distribution_file);
- {
- let mut file = File::create(&distribution_file)?;
- file.write_all(b"recipient,amount\n")?;
- for (node_address, activated_stake) in distribution.iter() {
- file.write_all(format!("{},{}\n", node_address, activated_stake).as_bytes())?;
- }
- }
-
- let mut transaction = Transaction::new_with_payer(
- &[spl_feature_proposal::instruction::propose(
- &config.keypair.pubkey(),
- &feature_proposal_keypair.pubkey(),
- tokens_to_mint,
- AcceptanceCriteria {
- tokens_required,
- deadline,
- },
- )],
- Some(&config.keypair.pubkey()),
- );
- let blockhash = rpc_client.get_latest_blockhash()?;
- transaction.try_sign(&[&config.keypair, feature_proposal_keypair], blockhash)?;
-
- println!("JSON RPC URL: {}", config.json_rpc_url);
-
- println!();
- println!("Distribute the proposal tokens to all validators by running:");
- println!(
- " $ solana-tokens distribute-spl-tokens \
- --from {} \
- --input-csv {} \
- --db-path db.{} \
- --fee-payer ~/.config/solana/id.json \
- --owner ",
- distributor_token_address,
- distribution_file,
- &feature_proposal_keypair.pubkey().to_string()[..8]
- );
- println!(
- " $ solana-tokens spl-token-balances \
- --mint {} --input-csv {}",
- mint_address, distribution_file
- );
- println!();
-
- println!(
- "Once the distribution is complete, request validators vote for \
- the proposal by first looking up their token account address:"
- );
- println!(
- " $ spl-token accounts --owner ~/validator-keypair.json {}",
- mint_address
- );
- println!("and then submit their vote by running:");
- println!(
- " $ spl-token transfer --owner ~/validator-keypair.json ALL {}",
- acceptance_token_address
- );
- println!();
- println!("Periodically the votes must be tallied by running:");
- println!(
- " $ spl-feature-proposal tally {}",
- feature_proposal_keypair.pubkey()
- );
- println!("Tallying is permissionless and may be run by anybody.");
- println!("Once this feature proposal is accepted, the {} feature will be activated at the next epoch.", feature_id_address);
-
- println!();
- println!(
- "Proposal will expire at {}",
- unix_timestamp_to_string(deadline)
- );
- println!();
- if !confirm {
- println!("Add --confirm flag to initiate the feature proposal");
- return Ok(());
- }
- rpc_client.send_and_confirm_transaction_with_spinner(&transaction)?;
-
- println!();
- println!("Feature proposal created!");
- Ok(())
-}
-
-fn process_tally(
- rpc_client: &RpcClient,
- config: &Config,
- feature_proposal_address: &Pubkey,
-) -> Result<(), Box> {
- let feature_proposal = get_feature_proposal(rpc_client, feature_proposal_address)?;
-
- let feature_id_address = spl_feature_proposal::get_feature_id_address(feature_proposal_address);
- let acceptance_token_address =
- spl_feature_proposal::get_acceptance_token_address(feature_proposal_address);
-
- println!("Feature Id: {}", feature_id_address);
- println!("Acceptance Token Address: {}", acceptance_token_address);
-
- match feature_proposal {
- FeatureProposal::Uninitialized => {
- return Err("Feature proposal is uninitialized".into());
- }
- FeatureProposal::Pending(acceptance_criteria) => {
- let acceptance_token_address =
- spl_feature_proposal::get_acceptance_token_address(feature_proposal_address);
- let acceptance_token_balance = rpc_client
- .get_token_account_balance(&acceptance_token_address)?
- .amount
- .parse::()
- .unwrap_or(0);
-
- println!();
- println!(
- "{} tokens required to accept the proposal",
- spl_feature_proposal::amount_to_ui_amount(acceptance_criteria.tokens_required)
- );
- println!(
- "{} tokens have been received",
- spl_feature_proposal::amount_to_ui_amount(acceptance_token_balance)
- );
- println!(
- "Proposal will expire at {}",
- unix_timestamp_to_string(acceptance_criteria.deadline)
- );
- println!();
-
- // Don't bother issuing a transaction if it's clear the Tally won't succeed
- if acceptance_token_balance < acceptance_criteria.tokens_required
- && (SystemTime::now()
- .duration_since(UNIX_EPOCH)
- .unwrap()
- .as_secs() as UnixTimestamp)
- < acceptance_criteria.deadline
- {
- println!("Feature proposal pending");
- return Ok(());
- }
- }
- FeatureProposal::Accepted { .. } => {
- println!("Feature proposal accepted");
- return Ok(());
- }
- FeatureProposal::Expired => {
- println!("Feature proposal expired");
- return Ok(());
- }
- }
-
- let mut transaction = Transaction::new_with_payer(
- &[spl_feature_proposal::instruction::tally(
- feature_proposal_address,
- )],
- Some(&config.keypair.pubkey()),
- );
- let blockhash = rpc_client.get_latest_blockhash()?;
- transaction.try_sign(&[&config.keypair], blockhash)?;
-
- rpc_client.send_and_confirm_transaction_with_spinner(&transaction)?;
-
- // Check the status of the proposal after the tally completes
- let feature_proposal = get_feature_proposal(rpc_client, feature_proposal_address)?;
- match feature_proposal {
- FeatureProposal::Uninitialized => Err("Feature proposal is uninitialized".into()),
- FeatureProposal::Pending { .. } => {
- println!("Feature proposal pending");
- Ok(())
- }
- FeatureProposal::Accepted { .. } => {
- println!("Feature proposal accepted");
- Ok(())
- }
- FeatureProposal::Expired => {
- println!("Feature proposal expired");
- Ok(())
- }
- }
-}
diff --git a/feature-proposal/program/Cargo.toml b/feature-proposal/program/Cargo.toml
deleted file mode 100644
index 79c9ea1e37c..00000000000
--- a/feature-proposal/program/Cargo.toml
+++ /dev/null
@@ -1,32 +0,0 @@
-[package]
-name = "spl-feature-proposal"
-version = "1.0.0"
-description = "Solana Program Library Feature Proposal Program"
-authors = ["Solana Labs Maintainers "]
-repository = "https://github.com/solana-labs/solana-program-library"
-license = "Apache-2.0"
-edition = "2021"
-
-[features]
-no-entrypoint = []
-test-sbf = []
-
-[dependencies]
-borsh = "1.5.3"
-solana-program = "2.1.0"
-spl-token = { version = "7.0", path = "../../token/program", features = [
- "no-entrypoint",
-] }
-
-[dev-dependencies]
-solana-program-test = "2.1.0"
-solana-sdk = "2.1.0"
-
-[lib]
-crate-type = ["cdylib", "lib"]
-
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu"]
-
-[lints]
-workspace = true
diff --git a/feature-proposal/program/Xargo.toml b/feature-proposal/program/Xargo.toml
deleted file mode 100644
index 1744f098ae1..00000000000
--- a/feature-proposal/program/Xargo.toml
+++ /dev/null
@@ -1,2 +0,0 @@
-[target.bpfel-unknown-unknown.dependencies.std]
-features = []
\ No newline at end of file
diff --git a/feature-proposal/program/program-id.md b/feature-proposal/program/program-id.md
deleted file mode 100644
index f1475c155c4..00000000000
--- a/feature-proposal/program/program-id.md
+++ /dev/null
@@ -1 +0,0 @@
-Feat1YXHhH6t1juaWF74WLcfv4XoNocjXA6sPWHNgAse
diff --git a/feature-proposal/program/run-tests.sh b/feature-proposal/program/run-tests.sh
deleted file mode 100755
index 7ee90bf4b3e..00000000000
--- a/feature-proposal/program/run-tests.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env bash
-
-set -ex
-cd "$(dirname "$0")"
-cargo fmt -- --check
-cargo clippy
-cargo build
-cargo build-sbf
-
-if [[ $1 = -v ]]; then
- export RUST_LOG=solana=debug
-fi
-
-cargo test
-cargo test-sbf
diff --git a/feature-proposal/program/src/entrypoint.rs b/feature-proposal/program/src/entrypoint.rs
deleted file mode 100644
index 62a02f2a465..00000000000
--- a/feature-proposal/program/src/entrypoint.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//! Program entrypoint
-
-#![cfg(all(target_os = "solana", not(feature = "no-entrypoint")))]
-
-use solana_program::{account_info::AccountInfo, entrypoint::ProgramResult, pubkey::Pubkey};
-
-solana_program::entrypoint!(process_instruction);
-fn process_instruction(
- program_id: &Pubkey,
- accounts: &[AccountInfo],
- instruction_data: &[u8],
-) -> ProgramResult {
- crate::processor::process_instruction(program_id, accounts, instruction_data)
-}
diff --git a/feature-proposal/program/src/instruction.rs b/feature-proposal/program/src/instruction.rs
deleted file mode 100644
index ea8238e4149..00000000000
--- a/feature-proposal/program/src/instruction.rs
+++ /dev/null
@@ -1,227 +0,0 @@
-//! Program instructions
-
-use {
- crate::{state::AcceptanceCriteria, *},
- borsh::{BorshDeserialize, BorshSchema, BorshSerialize},
- solana_program::{
- instruction::{AccountMeta, Instruction},
- msg,
- program_error::ProgramError,
- program_pack::{Pack, Sealed},
- pubkey::Pubkey,
- sysvar,
- },
-};
-
-/// Instructions supported by the Feature Proposal program
-#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, BorshSchema, PartialEq)]
-pub enum FeatureProposalInstruction {
- /// Propose a new feature.
- ///
- /// This instruction will create a variety of accounts to support the
- /// feature proposal, all funded by account 0:
- /// * A new token mint with a supply of `tokens_to_mint`, owned by the
- /// program and never modified again
- /// * A new "distributor" token account that holds the total supply, owned
- /// by account 0.
- /// * A new "acceptance" token account that holds 0 tokens, owned by the
- /// program. Tokens transfers to this address are irrevocable and
- /// permanent.
- /// * A new feature id account that has been funded and allocated (as
- /// described in `solana_program::feature`)
- ///
- /// On successful execution of the instruction, the feature proposer is
- /// expected to distribute the tokens in the distributor token account
- /// out to all participating parties.
- ///
- /// Based on the provided acceptance criteria, if
- /// `AcceptanceCriteria::tokens_required` tokens are transferred into
- /// the acceptance token account before `AcceptanceCriteria::deadline`
- /// then the proposal is eligible to be accepted.
- ///
- /// The `FeatureProposalInstruction::Tally` instruction must be executed, by
- /// any party, to complete the feature acceptance process.
- ///
- /// Accounts expected by this instruction:
- ///
- /// 0. `[writeable,signer]` Funding account (must be a system account)
- /// 1. `[writeable,signer]` Unallocated feature proposal account to create
- /// 2. `[writeable]` Token mint address from `get_mint_address`
- /// 3. `[writeable]` Distributor token account address from
- /// `get_distributor_token_address`
- /// 4. `[writeable]` Acceptance token account address from
- /// `get_acceptance_token_address`
- /// 5. `[writeable]` Feature id account address from
- /// `get_feature_id_address`
- /// 6. `[]` System program
- /// 7. `[]` SPL Token program
- /// 8. `[]` Rent sysvar
- Propose {
- /// Total number of tokens to mint for this proposal
- #[allow(dead_code)] // not dead code..
- tokens_to_mint: u64,
-
- /// Criteria for how this proposal may be activated
- #[allow(dead_code)] // not dead code..
- acceptance_criteria: AcceptanceCriteria,
- },
-
- /// `Tally` is a permission-less instruction to check the acceptance
- /// criteria for the feature proposal, which may result in:
- /// * No action
- /// * Feature proposal acceptance
- /// * Feature proposal expiration
- ///
- /// Accounts expected by this instruction:
- ///
- /// 0. `[writeable]` Feature proposal account
- /// 1. `[]` Acceptance token account address from
- /// `get_acceptance_token_address`
- /// 2. `[writeable]` Derived feature id account address from
- /// `get_feature_id_address`
- /// 3. `[]` System program
- /// 4. `[]` Clock sysvar
- Tally,
-}
-
-impl Sealed for FeatureProposalInstruction {}
-impl Pack for FeatureProposalInstruction {
- const LEN: usize = 25; // see `test_get_packed_len()` for justification of "18"
-
- fn pack_into_slice(&self, dst: &mut [u8]) {
- let data = self.pack_into_vec();
- dst[..data.len()].copy_from_slice(&data);
- }
-
- fn unpack_from_slice(src: &[u8]) -> Result {
- let mut mut_src: &[u8] = src;
- Self::deserialize(&mut mut_src).map_err(|err| {
- msg!(
- "Error: failed to deserialize feature proposal instruction: {}",
- err
- );
- ProgramError::InvalidInstructionData
- })
- }
-}
-
-impl FeatureProposalInstruction {
- fn pack_into_vec(&self) -> Vec {
- borsh::to_vec(self).expect("try_to_vec")
- }
-}
-
-/// Create a `FeatureProposalInstruction::Propose` instruction
-pub fn propose(
- funding_address: &Pubkey,
- feature_proposal_address: &Pubkey,
- tokens_to_mint: u64,
- acceptance_criteria: AcceptanceCriteria,
-) -> Instruction {
- let mint_address = get_mint_address(feature_proposal_address);
- let distributor_token_address = get_distributor_token_address(feature_proposal_address);
- let acceptance_token_address = get_acceptance_token_address(feature_proposal_address);
- let feature_id_address = get_feature_id_address(feature_proposal_address);
-
- Instruction {
- program_id: id(),
- accounts: vec![
- AccountMeta::new(*funding_address, true),
- AccountMeta::new(*feature_proposal_address, true),
- AccountMeta::new(mint_address, false),
- AccountMeta::new(distributor_token_address, false),
- AccountMeta::new(acceptance_token_address, false),
- AccountMeta::new(feature_id_address, false),
- AccountMeta::new_readonly(solana_program::system_program::id(), false),
- AccountMeta::new_readonly(spl_token::id(), false),
- AccountMeta::new_readonly(sysvar::rent::id(), false),
- ],
- data: FeatureProposalInstruction::Propose {
- tokens_to_mint,
- acceptance_criteria,
- }
- .pack_into_vec(),
- }
-}
-
-/// Create a `FeatureProposalInstruction::Tally` instruction
-pub fn tally(feature_proposal_address: &Pubkey) -> Instruction {
- let acceptance_token_address = get_acceptance_token_address(feature_proposal_address);
- let feature_id_address = get_feature_id_address(feature_proposal_address);
-
- Instruction {
- program_id: id(),
- accounts: vec![
- AccountMeta::new(*feature_proposal_address, false),
- AccountMeta::new_readonly(acceptance_token_address, false),
- AccountMeta::new(feature_id_address, false),
- AccountMeta::new_readonly(solana_program::system_program::id(), false),
- AccountMeta::new_readonly(sysvar::clock::id(), false),
- ],
- data: FeatureProposalInstruction::Tally.pack_into_vec(),
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_get_packed_len() {
- assert_eq!(
- FeatureProposalInstruction::get_packed_len(),
- solana_program::borsh1::get_packed_len::()
- )
- }
-
- #[test]
- fn test_serialize_bytes() {
- assert_eq!(
- borsh::to_vec(&FeatureProposalInstruction::Tally).unwrap(),
- vec![1]
- );
-
- assert_eq!(
- borsh::to_vec(&FeatureProposalInstruction::Propose {
- tokens_to_mint: 42,
- acceptance_criteria: AcceptanceCriteria {
- tokens_required: 0xdeadbeefdeadbeef,
- deadline: -1,
- }
- })
- .unwrap(),
- vec![
- 0, 42, 0, 0, 0, 0, 0, 0, 0, 239, 190, 173, 222, 239, 190, 173, 222, 255, 255, 255,
- 255, 255, 255, 255, 255
- ]
- );
- }
-
- #[test]
- fn test_serialize_large_slice() {
- let mut dst = vec![0xff; 4];
- FeatureProposalInstruction::Tally.pack_into_slice(&mut dst);
-
- // Extra bytes (0xff) ignored
- assert_eq!(dst, vec![1, 0xff, 0xff, 0xff]);
- }
-
- #[test]
- fn state_deserialize_invalid() {
- assert_eq!(
- FeatureProposalInstruction::unpack_from_slice(&[1]),
- Ok(FeatureProposalInstruction::Tally),
- );
-
- // Extra bytes (0xff) ignored...
- assert_eq!(
- FeatureProposalInstruction::unpack_from_slice(&[1, 0xff, 0xff, 0xff]),
- Ok(FeatureProposalInstruction::Tally),
- );
-
- assert_eq!(
- FeatureProposalInstruction::unpack_from_slice(&[2]),
- Err(ProgramError::InvalidInstructionData),
- );
- }
-}
diff --git a/feature-proposal/program/src/lib.rs b/feature-proposal/program/src/lib.rs
deleted file mode 100644
index 52b44bb0bc4..00000000000
--- a/feature-proposal/program/src/lib.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-//! Feature Proposal program
-#![deny(missing_docs)]
-#![forbid(unsafe_code)]
-
-mod entrypoint;
-pub mod instruction;
-pub mod processor;
-pub mod state;
-
-// Export current SDK types for downstream users building with a different SDK
-// version
-pub use solana_program;
-use solana_program::{program_pack::Pack, pubkey::Pubkey};
-
-solana_program::declare_id!("Feat1YXHhH6t1juaWF74WLcfv4XoNocjXA6sPWHNgAse");
-
-pub(crate) fn get_mint_address_with_seed(feature_proposal_address: &Pubkey) -> (Pubkey, u8) {
- Pubkey::find_program_address(&[&feature_proposal_address.to_bytes(), br"mint"], &id())
-}
-
-pub(crate) fn get_distributor_token_address_with_seed(
- feature_proposal_address: &Pubkey,
-) -> (Pubkey, u8) {
- Pubkey::find_program_address(
- &[&feature_proposal_address.to_bytes(), br"distributor"],
- &id(),
- )
-}
-
-pub(crate) fn get_acceptance_token_address_with_seed(
- feature_proposal_address: &Pubkey,
-) -> (Pubkey, u8) {
- Pubkey::find_program_address(
- &[&feature_proposal_address.to_bytes(), br"acceptance"],
- &id(),
- )
-}
-
-pub(crate) fn get_feature_id_address_with_seed(feature_proposal_address: &Pubkey) -> (Pubkey, u8) {
- Pubkey::find_program_address(
- &[&feature_proposal_address.to_bytes(), br"feature-id"],
- &id(),
- )
-}
-
-/// Derive the SPL Token mint address associated with a feature proposal
-pub fn get_mint_address(feature_proposal_address: &Pubkey) -> Pubkey {
- get_mint_address_with_seed(feature_proposal_address).0
-}
-
-/// Derive the SPL Token token address associated with a feature proposal that
-/// receives the initial minted tokens
-pub fn get_distributor_token_address(feature_proposal_address: &Pubkey) -> Pubkey {
- get_distributor_token_address_with_seed(feature_proposal_address).0
-}
-
-/// Derive the SPL Token token address associated with a feature proposal that
-/// users send their tokens to accept the proposal
-pub fn get_acceptance_token_address(feature_proposal_address: &Pubkey) -> Pubkey {
- get_acceptance_token_address_with_seed(feature_proposal_address).0
-}
-
-/// Derive the feature id address associated with the feature proposal
-pub fn get_feature_id_address(feature_proposal_address: &Pubkey) -> Pubkey {
- get_feature_id_address_with_seed(feature_proposal_address).0
-}
-
-/// Convert the UI representation of a token amount (using the decimals field
-/// defined in its mint) to the raw amount
-pub fn ui_amount_to_amount(ui_amount: f64) -> u64 {
- (ui_amount * 10_usize.pow(spl_token::native_mint::DECIMALS as u32) as f64) as u64
-}
-
-/// Convert a raw amount to its UI representation (using the decimals field
-/// defined in its mint)
-pub fn amount_to_ui_amount(amount: u64) -> f64 {
- amount as f64 / 10_usize.pow(spl_token::native_mint::DECIMALS as u32) as f64
-}
diff --git a/feature-proposal/program/src/processor.rs b/feature-proposal/program/src/processor.rs
deleted file mode 100644
index 6aa00a610f8..00000000000
--- a/feature-proposal/program/src/processor.rs
+++ /dev/null
@@ -1,371 +0,0 @@
-//! Program state processor
-
-use {
- crate::{instruction::*, state::*, *},
- solana_program::{
- account_info::{next_account_info, AccountInfo},
- clock::Clock,
- entrypoint::ProgramResult,
- feature::{self, Feature},
- msg,
- program::{invoke, invoke_signed},
- program_error::ProgramError,
- pubkey::Pubkey,
- rent::Rent,
- system_instruction,
- sysvar::Sysvar,
- },
-};
-
-/// Instruction processor
-pub fn process_instruction(
- program_id: &Pubkey,
- accounts: &[AccountInfo],
- input: &[u8],
-) -> ProgramResult {
- let instruction = FeatureProposalInstruction::unpack_from_slice(input)?;
- let account_info_iter = &mut accounts.iter();
-
- match instruction {
- FeatureProposalInstruction::Propose {
- tokens_to_mint,
- acceptance_criteria,
- } => {
- msg!("FeatureProposalInstruction::Propose");
-
- let funder_info = next_account_info(account_info_iter)?;
- let feature_proposal_info = next_account_info(account_info_iter)?;
- let mint_info = next_account_info(account_info_iter)?;
- let distributor_token_info = next_account_info(account_info_iter)?;
- let acceptance_token_info = next_account_info(account_info_iter)?;
- let feature_id_info = next_account_info(account_info_iter)?;
- let system_program_info = next_account_info(account_info_iter)?;
- let spl_token_program_info = next_account_info(account_info_iter)?;
- let rent_sysvar_info = next_account_info(account_info_iter)?;
- let rent = &Rent::from_account_info(rent_sysvar_info)?;
-
- let (mint_address, mint_bump_seed) =
- get_mint_address_with_seed(feature_proposal_info.key);
- if mint_address != *mint_info.key {
- msg!("Error: mint address derivation mismatch");
- return Err(ProgramError::InvalidArgument);
- }
-
- let (distributor_token_address, distributor_token_bump_seed) =
- get_distributor_token_address_with_seed(feature_proposal_info.key);
- if distributor_token_address != *distributor_token_info.key {
- msg!("Error: distributor token address derivation mismatch");
- return Err(ProgramError::InvalidArgument);
- }
-
- let (acceptance_token_address, acceptance_token_bump_seed) =
- get_acceptance_token_address_with_seed(feature_proposal_info.key);
- if acceptance_token_address != *acceptance_token_info.key {
- msg!("Error: acceptance token address derivation mismatch");
- return Err(ProgramError::InvalidArgument);
- }
-
- let (feature_id_address, feature_id_bump_seed) =
- get_feature_id_address_with_seed(feature_proposal_info.key);
- if feature_id_address != *feature_id_info.key {
- msg!("Error: feature-id address derivation mismatch");
- return Err(ProgramError::InvalidArgument);
- }
-
- let mint_signer_seeds: &[&[_]] = &[
- &feature_proposal_info.key.to_bytes(),
- br"mint",
- &[mint_bump_seed],
- ];
-
- let distributor_token_signer_seeds: &[&[_]] = &[
- &feature_proposal_info.key.to_bytes(),
- br"distributor",
- &[distributor_token_bump_seed],
- ];
-
- let acceptance_token_signer_seeds: &[&[_]] = &[
- &feature_proposal_info.key.to_bytes(),
- br"acceptance",
- &[acceptance_token_bump_seed],
- ];
-
- let feature_id_signer_seeds: &[&[_]] = &[
- &feature_proposal_info.key.to_bytes(),
- br"feature-id",
- &[feature_id_bump_seed],
- ];
-
- msg!("Creating feature proposal account");
- invoke(
- &system_instruction::create_account(
- funder_info.key,
- feature_proposal_info.key,
- 1.max(rent.minimum_balance(FeatureProposal::get_packed_len())),
- FeatureProposal::get_packed_len() as u64,
- program_id,
- ),
- &[
- funder_info.clone(),
- feature_proposal_info.clone(),
- system_program_info.clone(),
- ],
- )?;
- FeatureProposal::Pending(acceptance_criteria)
- .pack_into_slice(&mut feature_proposal_info.data.borrow_mut());
-
- msg!("Creating mint");
- invoke_signed(
- &system_instruction::create_account(
- funder_info.key,
- mint_info.key,
- 1.max(rent.minimum_balance(spl_token::state::Mint::get_packed_len())),
- spl_token::state::Mint::get_packed_len() as u64,
- &spl_token::id(),
- ),
- &[
- funder_info.clone(),
- mint_info.clone(),
- system_program_info.clone(),
- ],
- &[mint_signer_seeds],
- )?;
-
- msg!("Initializing mint");
- invoke(
- &spl_token::instruction::initialize_mint(
- &spl_token::id(),
- mint_info.key,
- mint_info.key,
- None,
- spl_token::native_mint::DECIMALS,
- )?,
- &[
- mint_info.clone(),
- spl_token_program_info.clone(),
- rent_sysvar_info.clone(),
- ],
- )?;
-
- msg!("Creating distributor token account");
- invoke_signed(
- &system_instruction::create_account(
- funder_info.key,
- distributor_token_info.key,
- 1.max(rent.minimum_balance(spl_token::state::Account::get_packed_len())),
- spl_token::state::Account::get_packed_len() as u64,
- &spl_token::id(),
- ),
- &[
- funder_info.clone(),
- distributor_token_info.clone(),
- system_program_info.clone(),
- ],
- &[distributor_token_signer_seeds],
- )?;
-
- msg!("Initializing distributor token account");
- invoke(
- &spl_token::instruction::initialize_account(
- &spl_token::id(),
- distributor_token_info.key,
- mint_info.key,
- feature_proposal_info.key,
- )?,
- &[
- distributor_token_info.clone(),
- spl_token_program_info.clone(),
- rent_sysvar_info.clone(),
- feature_proposal_info.clone(),
- mint_info.clone(),
- ],
- )?;
-
- msg!("Creating acceptance token account");
- invoke_signed(
- &system_instruction::create_account(
- funder_info.key,
- acceptance_token_info.key,
- 1.max(rent.minimum_balance(spl_token::state::Account::get_packed_len())),
- spl_token::state::Account::get_packed_len() as u64,
- &spl_token::id(),
- ),
- &[
- funder_info.clone(),
- acceptance_token_info.clone(),
- system_program_info.clone(),
- ],
- &[acceptance_token_signer_seeds],
- )?;
-
- msg!("Initializing acceptance token account");
- invoke(
- &spl_token::instruction::initialize_account(
- &spl_token::id(),
- acceptance_token_info.key,
- mint_info.key,
- feature_proposal_info.key,
- )?,
- &[
- acceptance_token_info.clone(),
- spl_token_program_info.clone(),
- rent_sysvar_info.clone(),
- feature_proposal_info.clone(),
- mint_info.clone(),
- ],
- )?;
- invoke(
- &spl_token::instruction::set_authority(
- &spl_token::id(),
- acceptance_token_info.key,
- Some(feature_proposal_info.key),
- spl_token::instruction::AuthorityType::CloseAccount,
- feature_proposal_info.key,
- &[],
- )?,
- &[
- spl_token_program_info.clone(),
- acceptance_token_info.clone(),
- feature_proposal_info.clone(),
- ],
- )?;
- invoke(
- &spl_token::instruction::set_authority(
- &spl_token::id(),
- acceptance_token_info.key,
- Some(program_id),
- spl_token::instruction::AuthorityType::AccountOwner,
- feature_proposal_info.key,
- &[],
- )?,
- &[
- spl_token_program_info.clone(),
- acceptance_token_info.clone(),
- feature_proposal_info.clone(),
- ],
- )?;
-
- // Mint `tokens_to_mint` tokens into `distributor_token_account` owned by
- // `feature_proposal`
- msg!("Minting {} tokens", tokens_to_mint);
- invoke_signed(
- &spl_token::instruction::mint_to(
- &spl_token::id(),
- mint_info.key,
- distributor_token_info.key,
- mint_info.key,
- &[],
- tokens_to_mint,
- )?,
- &[
- mint_info.clone(),
- distributor_token_info.clone(),
- spl_token_program_info.clone(),
- ],
- &[mint_signer_seeds],
- )?;
-
- // Fully fund the feature id account so the `Tally` instruction will not require
- // any lamports from the caller
- msg!("Funding feature id account");
- invoke(
- &system_instruction::transfer(
- funder_info.key,
- feature_id_info.key,
- 1.max(rent.minimum_balance(Feature::size_of())),
- ),
- &[
- funder_info.clone(),
- feature_id_info.clone(),
- system_program_info.clone(),
- ],
- )?;
-
- msg!("Allocating feature id account");
- invoke_signed(
- &system_instruction::allocate(feature_id_info.key, Feature::size_of() as u64),
- &[feature_id_info.clone(), system_program_info.clone()],
- &[feature_id_signer_seeds],
- )?;
- }
-
- FeatureProposalInstruction::Tally => {
- msg!("FeatureProposalInstruction::Tally");
-
- let feature_proposal_info = next_account_info(account_info_iter)?;
- let feature_proposal_state =
- FeatureProposal::unpack_from_slice(&feature_proposal_info.data.borrow())?;
-
- match feature_proposal_state {
- FeatureProposal::Pending(acceptance_criteria) => {
- let acceptance_token_info = next_account_info(account_info_iter)?;
- let feature_id_info = next_account_info(account_info_iter)?;
- let system_program_info = next_account_info(account_info_iter)?;
- let clock_sysvar_info = next_account_info(account_info_iter)?;
- let clock = &Clock::from_account_info(clock_sysvar_info)?;
-
- // Re-derive the acceptance token and feature id program addresses to confirm
- // the caller provided the correct addresses
- let acceptance_token_address =
- get_acceptance_token_address(feature_proposal_info.key);
- if acceptance_token_address != *acceptance_token_info.key {
- msg!("Error: acceptance token address derivation mismatch");
- return Err(ProgramError::InvalidArgument);
- }
-
- let (feature_id_address, feature_id_bump_seed) =
- get_feature_id_address_with_seed(feature_proposal_info.key);
- if feature_id_address != *feature_id_info.key {
- msg!("Error: feature-id address derivation mismatch");
- return Err(ProgramError::InvalidArgument);
- }
-
- let feature_id_signer_seeds: &[&[_]] = &[
- &feature_proposal_info.key.to_bytes(),
- br"feature-id",
- &[feature_id_bump_seed],
- ];
-
- if clock.unix_timestamp >= acceptance_criteria.deadline {
- msg!("Feature proposal expired");
- FeatureProposal::Expired
- .pack_into_slice(&mut feature_proposal_info.data.borrow_mut());
- return Ok(());
- }
-
- msg!("Unpacking acceptance token account");
- let acceptance_token =
- spl_token::state::Account::unpack(&acceptance_token_info.data.borrow())?;
-
- msg!(
- "Feature proposal has received {} tokens, and {} tokens required for acceptance",
- acceptance_token.amount, acceptance_criteria.tokens_required
- );
- if acceptance_token.amount < acceptance_criteria.tokens_required {
- msg!("Activation threshold has not been reached");
- return Ok(());
- }
-
- msg!("Assigning feature id account");
- invoke_signed(
- &system_instruction::assign(feature_id_info.key, &feature::id()),
- &[feature_id_info.clone(), system_program_info.clone()],
- &[feature_id_signer_seeds],
- )?;
-
- msg!("Feature proposal accepted");
- FeatureProposal::Accepted {
- tokens_upon_acceptance: acceptance_token.amount,
- }
- .pack_into_slice(&mut feature_proposal_info.data.borrow_mut());
- }
- _ => {
- msg!("Error: feature proposal account not in the pending state");
- return Err(ProgramError::InvalidAccountData);
- }
- }
- }
- }
-
- Ok(())
-}
diff --git a/feature-proposal/program/src/state.rs b/feature-proposal/program/src/state.rs
deleted file mode 100644
index 81d86f2da7a..00000000000
--- a/feature-proposal/program/src/state.rs
+++ /dev/null
@@ -1,117 +0,0 @@
-//! Program state
-use {
- borsh::{BorshDeserialize, BorshSchema, BorshSerialize},
- solana_program::{
- clock::UnixTimestamp,
- msg,
- program_error::ProgramError,
- program_pack::{Pack, Sealed},
- },
-};
-
-/// Criteria for accepting a feature proposal
-#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, BorshSchema, PartialEq)]
-pub struct AcceptanceCriteria {
- /// The balance of the feature proposal's token account must be greater than
- /// this amount, and tallied before the deadline for the feature to be
- /// accepted.
- pub tokens_required: u64,
-
- /// If the required tokens are not tallied by this deadline then the
- /// proposal will expire.
- pub deadline: UnixTimestamp,
-}
-
-/// Contents of a Feature Proposal account
-#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, BorshSchema, PartialEq)]
-pub enum FeatureProposal {
- /// Default account state after creating it
- Uninitialized,
- /// Feature proposal is now pending
- Pending(AcceptanceCriteria),
- /// Feature proposal was accepted and the feature is now active
- Accepted {
- /// The balance of the feature proposal's token account at the time of
- /// activation.
- #[allow(dead_code)] // not dead code..
- tokens_upon_acceptance: u64,
- },
- /// Feature proposal was not accepted before the deadline
- Expired,
-}
-impl Sealed for FeatureProposal {}
-
-impl Pack for FeatureProposal {
- const LEN: usize = 17; // see `test_get_packed_len()` for justification of "18"
-
- fn pack_into_slice(&self, dst: &mut [u8]) {
- let data = borsh::to_vec(self).unwrap();
- dst[..data.len()].copy_from_slice(&data);
- }
-
- fn unpack_from_slice(src: &[u8]) -> Result {
- let mut mut_src: &[u8] = src;
- Self::deserialize(&mut mut_src).map_err(|err| {
- msg!(
- "Error: failed to deserialize feature proposal account: {}",
- err
- );
- ProgramError::InvalidAccountData
- })
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_get_packed_len() {
- assert_eq!(
- FeatureProposal::get_packed_len(),
- solana_program::borsh1::get_packed_len::()
- );
- }
-
- #[test]
- fn test_serialize_bytes() {
- assert_eq!(borsh::to_vec(&FeatureProposal::Expired).unwrap(), vec![3]);
-
- assert_eq!(
- borsh::to_vec(&FeatureProposal::Pending(AcceptanceCriteria {
- tokens_required: 0xdeadbeefdeadbeef,
- deadline: -1,
- }))
- .unwrap(),
- vec![1, 239, 190, 173, 222, 239, 190, 173, 222, 255, 255, 255, 255, 255, 255, 255, 255],
- );
- }
-
- #[test]
- fn test_serialize_large_slice() {
- let mut dst = vec![0xff; 4];
- FeatureProposal::Expired.pack_into_slice(&mut dst);
-
- // Extra bytes (0xff) ignored
- assert_eq!(dst, vec![3, 0xff, 0xff, 0xff]);
- }
-
- #[test]
- fn state_deserialize_invalid() {
- assert_eq!(
- FeatureProposal::unpack_from_slice(&[3]),
- Ok(FeatureProposal::Expired),
- );
-
- // Extra bytes (0xff) ignored...
- assert_eq!(
- FeatureProposal::unpack_from_slice(&[3, 0xff, 0xff, 0xff]),
- Ok(FeatureProposal::Expired),
- );
-
- assert_eq!(
- FeatureProposal::unpack_from_slice(&[4]),
- Err(ProgramError::InvalidAccountData),
- );
- }
-}
diff --git a/feature-proposal/program/tests/functional.rs b/feature-proposal/program/tests/functional.rs
deleted file mode 100644
index 149b68b9b8e..00000000000
--- a/feature-proposal/program/tests/functional.rs
+++ /dev/null
@@ -1,206 +0,0 @@
-// Mark this test as BPF-only due to current `ProgramTest` limitations when
-// CPIing into the system program
-#![cfg(feature = "test-sbf")]
-
-use {
- solana_program::{
- feature::{self, Feature},
- program_option::COption,
- system_program,
- },
- solana_program_test::*,
- solana_sdk::{
- signature::{Keypair, Signer},
- transaction::Transaction,
- },
- spl_feature_proposal::{instruction::*, state::*, *},
-};
-
-fn program_test() -> ProgramTest {
- ProgramTest::new(
- "spl_feature_proposal",
- id(),
- processor!(processor::process_instruction),
- )
-}
-
-#[tokio::test]
-async fn test_basic() {
- let feature_proposal = Keypair::new();
-
- let (mut banks_client, payer, recent_blockhash) = program_test().start().await;
-
- let feature_id_address = get_feature_id_address(&feature_proposal.pubkey());
- let mint_address = get_mint_address(&feature_proposal.pubkey());
- let distributor_token_address = get_distributor_token_address(&feature_proposal.pubkey());
- let acceptance_token_address = get_acceptance_token_address(&feature_proposal.pubkey());
-
- // Create a new feature proposal
- let mut transaction = Transaction::new_with_payer(
- &[propose(
- &payer.pubkey(),
- &feature_proposal.pubkey(),
- 42,
- AcceptanceCriteria {
- tokens_required: 42,
- deadline: i64::MAX,
- },
- )],
- Some(&payer.pubkey()),
- );
- transaction.sign(&[&payer, &feature_proposal], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- // Confirm feature id account is now funded and allocated, but not assigned
- let feature_id_account = banks_client
- .get_account(feature_id_address)
- .await
- .expect("success")
- .expect("some account");
- assert_eq!(feature_id_account.owner, system_program::id());
- assert_eq!(feature_id_account.data.len(), Feature::size_of());
-
- // Confirm mint account state
- let mint = banks_client
- .get_packed_account_data::(mint_address)
- .await
- .unwrap();
- assert_eq!(mint.supply, 42);
- assert_eq!(mint.decimals, 9);
- assert!(mint.freeze_authority.is_none());
- assert_eq!(mint.mint_authority, COption::Some(mint_address));
-
- // Confirm distributor token account state
- let distributor_token = banks_client
- .get_packed_account_data::(distributor_token_address)
- .await
- .unwrap();
- assert_eq!(distributor_token.amount, 42);
- assert_eq!(distributor_token.mint, mint_address);
- assert_eq!(distributor_token.owner, feature_proposal.pubkey());
- assert!(distributor_token.close_authority.is_none());
-
- // Confirm acceptance token account state
- let acceptance_token = banks_client
- .get_packed_account_data::(acceptance_token_address)
- .await
- .unwrap();
- assert_eq!(acceptance_token.amount, 0);
- assert_eq!(acceptance_token.mint, mint_address);
- assert_eq!(acceptance_token.owner, id());
- assert_eq!(
- acceptance_token.close_authority,
- COption::Some(feature_proposal.pubkey())
- );
-
- // Tally #1: Does nothing because the acceptance criteria has not been met
- let mut transaction =
- Transaction::new_with_payer(&[tally(&feature_proposal.pubkey())], Some(&payer.pubkey()));
- transaction.sign(&[&payer], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- // Confirm feature id account is not yet assigned
- let feature_id_account = banks_client
- .get_account(feature_id_address)
- .await
- .expect("success")
- .expect("some account");
- assert_eq!(feature_id_account.owner, system_program::id());
-
- assert!(matches!(
- banks_client
- .get_packed_account_data::(feature_proposal.pubkey())
- .await,
- Ok(FeatureProposal::Pending(_))
- ));
-
- // Transfer tokens to the acceptance account
- let mut transaction = Transaction::new_with_payer(
- &[spl_token::instruction::transfer(
- &spl_token::id(),
- &distributor_token_address,
- &acceptance_token_address,
- &feature_proposal.pubkey(),
- &[],
- 42,
- )
- .unwrap()],
- Some(&payer.pubkey()),
- );
- transaction.sign(&[&payer, &feature_proposal], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- // Fetch a new blockhash to avoid the second Tally transaction having the same
- // signature as the first Tally transaction
- let recent_blockhash = banks_client
- .get_new_latest_blockhash(&recent_blockhash)
- .await
- .unwrap();
-
- // Tally #2: the acceptance criteria is now met
- let mut transaction =
- Transaction::new_with_payer(&[tally(&feature_proposal.pubkey())], Some(&payer.pubkey()));
- transaction.sign(&[&payer], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- // Confirm feature id account is now assigned
- let feature_id_account = banks_client
- .get_account(feature_id_address)
- .await
- .expect("success")
- .expect("some account");
- assert_eq!(feature_id_account.owner, feature::id());
-
- // Confirm feature proposal account state
- assert!(matches!(
- banks_client
- .get_packed_account_data::(feature_proposal.pubkey())
- .await,
- Ok(FeatureProposal::Accepted {
- tokens_upon_acceptance: 42
- })
- ));
-}
-
-#[tokio::test]
-async fn test_expired() {
- let feature_proposal = Keypair::new();
-
- let (banks_client, payer, recent_blockhash) = program_test().start().await;
-
- // Create a new feature proposal
- let mut transaction = Transaction::new_with_payer(
- &[propose(
- &payer.pubkey(),
- &feature_proposal.pubkey(),
- 42,
- AcceptanceCriteria {
- tokens_required: 42,
- deadline: 0, // <=== Already expired
- },
- )],
- Some(&payer.pubkey()),
- );
- transaction.sign(&[&payer, &feature_proposal], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- assert!(matches!(
- banks_client
- .get_packed_account_data::(feature_proposal.pubkey())
- .await,
- Ok(FeatureProposal::Pending(_))
- ));
-
- // Tally will cause the proposal to expire
- let mut transaction =
- Transaction::new_with_payer(&[tally(&feature_proposal.pubkey())], Some(&payer.pubkey()));
- transaction.sign(&[&payer], recent_blockhash);
- banks_client.process_transaction(transaction).await.unwrap();
-
- assert!(matches!(
- banks_client
- .get_packed_account_data::(feature_proposal.pubkey())
- .await,
- Ok(FeatureProposal::Expired)
- ));
-}
diff --git a/governance/addin-mock/program/Cargo.toml b/governance/addin-mock/program/Cargo.toml
index 589aa85ffd6..575cd75f2c8 100644
--- a/governance/addin-mock/program/Cargo.toml
+++ b/governance/addin-mock/program/Cargo.toml
@@ -20,7 +20,7 @@ num-traits = "0.2"
serde = "1.0.217"
serde_derive = "1.0.103"
solana-program = "2.1.0"
-spl-token = { version = "7.0", path = "../../../token/program", features = [
+spl-token = { version = "7.0", features = [
"no-entrypoint",
] }
spl-governance-addin-api = { version = "0.1.4", path = "../../addin-api" }
diff --git a/governance/chat/program/Cargo.toml b/governance/chat/program/Cargo.toml
index 5e3b36e5858..a6315129bf8 100644
--- a/governance/chat/program/Cargo.toml
+++ b/governance/chat/program/Cargo.toml
@@ -20,7 +20,7 @@ num-traits = "0.2"
serde = "1.0.217"
serde_derive = "1.0.103"
solana-program = "2.1.0"
-spl-token = { version = "7.0", path = "../../../token/program", features = [
+spl-token = { version = "7.0", features = [
"no-entrypoint",
] }
spl-governance = { version = "4.0.0", path = "../../program", features = [
diff --git a/governance/program/Cargo.toml b/governance/program/Cargo.toml
index e85f57e81a3..fd553380c3d 100644
--- a/governance/program/Cargo.toml
+++ b/governance/program/Cargo.toml
@@ -20,7 +20,7 @@ num-traits = "0.2"
serde = "1.0.217"
serde_derive = "1.0.103"
solana-program = "2.1.0"
-spl-token = { version = "7.0", path = "../../token/program", features = [
+spl-token = { version = "7.0", features = [
"no-entrypoint",
] }
spl-governance-tools = { version = "0.1.4", path = "../tools" }
diff --git a/governance/test-sdk/Cargo.toml b/governance/test-sdk/Cargo.toml
index af15d1fdaaf..dd27a6fcf46 100644
--- a/governance/test-sdk/Cargo.toml
+++ b/governance/test-sdk/Cargo.toml
@@ -19,7 +19,7 @@ serde_derive = "1.0.103"
solana-program = "2.1.0"
solana-program-test = "2.1.0"
solana-sdk = "2.1.0"
-spl-token = { version = "7.0", path = "../../token/program", features = [
+spl-token = { version = "7.0", features = [
"no-entrypoint",
] }
thiserror = "2.0"
diff --git a/governance/tools/Cargo.toml b/governance/tools/Cargo.toml
index bf8cdedef14..766bab14b7c 100644
--- a/governance/tools/Cargo.toml
+++ b/governance/tools/Cargo.toml
@@ -16,7 +16,7 @@ num-traits = "0.2"
serde = "1.0.217"
serde_derive = "1.0.103"
solana-program = "2.1.0"
-spl-token = { version = "7.0", path = "../../token/program", features = [
+spl-token = { version = "7.0", features = [
"no-entrypoint",
] }
thiserror = "2.0"
diff --git a/instruction-padding/README.md b/instruction-padding/README.md
new file mode 100644
index 00000000000..fd71f7e7125
--- /dev/null
+++ b/instruction-padding/README.md
@@ -0,0 +1,2 @@
+NOTE: The instruction-padding program and clients are now maintained at
+[solana-program/instruction-padding](https://github.com/solana-program/instruction-padding).
diff --git a/instruction-padding/program/Cargo.toml b/instruction-padding/program/Cargo.toml
deleted file mode 100644
index b30412155f9..00000000000
--- a/instruction-padding/program/Cargo.toml
+++ /dev/null
@@ -1,34 +0,0 @@
-[package]
-name = "spl-instruction-padding"
-version = "0.3.0"
-description = "Solana Program Library Instruction Padding Program"
-authors = ["Solana Labs Maintainers "]
-repository = "https://github.com/solana-labs/solana-program-library"
-license = "Apache-2.0"
-homepage = "https://solana.com/"
-edition = "2021"
-
-[features]
-no-entrypoint = []
-test-sbf = []
-
-[dependencies]
-num_enum = "0.7.3"
-solana-account-info = "2.1.0"
-solana-cpi = "2.1.0"
-solana-instruction = { version = "2.1.0", features = ["std"] }
-solana-program-entrypoint = "2.1.0"
-solana-program-error = "2.1.0"
-solana-pubkey = "2.1.0"
-
-[dev-dependencies]
-solana-program = "2.1.0"
-solana-program-test = "2.1.0"
-solana-sdk = "2.1.0"
-static_assertions = "1.1.0"
-
-[lib]
-crate-type = ["cdylib", "lib"]
-
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu"]
diff --git a/instruction-padding/program/README.md b/instruction-padding/program/README.md
deleted file mode 100644
index 5fe411f9c4c..00000000000
--- a/instruction-padding/program/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# Instruction Pad Program
-
-A program for padding instructions with additional data or accounts, to be used
-for testing larger transactions, either more instruction data, or more accounts.
-
-The main use-case is with solana-bench-tps, where we can see the impact of larger
-transactions through TPS numbers. With that data, we can develop a fair fee model
-for large transactions.
-
-It operates with two instructions: no-op and wrap.
-
-* No-op: simply an instruction with as much data and as many accounts as desired,
-of which none will be used for processing.
-* Wrap: before the padding data and accounts, accepts a real instruction and
-required accounts, and performs a CPI into the program specified by the instruction
-
-Both of these modes add the general overhead of calling a BPF program, and
-the wrap mode adds the CPI overhead.
-
-Because of the overhead, it's best to use the instruction padding program with
-all large transaction tests, and comparing TPS numbers between:
-
-* using the program with no padding
-* using the program with data and account padding
-
-## Audit
-
-The repository [README](https://github.com/solana-labs/solana-program-library#audits)
-contains information about program audits.
diff --git a/instruction-padding/program/src/entrypoint.rs b/instruction-padding/program/src/entrypoint.rs
deleted file mode 100644
index d5e799e5937..00000000000
--- a/instruction-padding/program/src/entrypoint.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//! Program entrypoint
-
-#![cfg(not(feature = "no-entrypoint"))]
-
-use {
- solana_account_info::AccountInfo, solana_program_error::ProgramResult, solana_pubkey::Pubkey,
-};
-
-solana_program_entrypoint::entrypoint!(process_instruction);
-fn process_instruction(
- program_id: &Pubkey,
- accounts: &[AccountInfo],
- instruction_data: &[u8],
-) -> ProgramResult {
- crate::processor::process(program_id, accounts, instruction_data)
-}
diff --git a/instruction-padding/program/src/instruction.rs b/instruction-padding/program/src/instruction.rs
deleted file mode 100644
index 68c50b8aeb4..00000000000
--- a/instruction-padding/program/src/instruction.rs
+++ /dev/null
@@ -1,169 +0,0 @@
-//! Instruction creators for large instructions
-
-use {
- num_enum::{IntoPrimitive, TryFromPrimitive},
- solana_instruction::{AccountMeta, Instruction},
- solana_program_error::ProgramError,
- solana_pubkey::Pubkey,
- std::{convert::TryInto, mem::size_of},
-};
-
-const MAX_CPI_ACCOUNT_INFOS: usize = 128;
-const MAX_CPI_INSTRUCTION_DATA_LEN: u64 = 10 * 1024;
-
-#[cfg(test)]
-static_assertions::const_assert_eq!(
- MAX_CPI_ACCOUNT_INFOS,
- solana_program::syscalls::MAX_CPI_ACCOUNT_INFOS
-);
-#[cfg(test)]
-static_assertions::const_assert_eq!(
- MAX_CPI_INSTRUCTION_DATA_LEN,
- solana_program::syscalls::MAX_CPI_INSTRUCTION_DATA_LEN
-);
-
-/// Instructions supported by the padding program, which takes in additional
-/// account data or accounts and does nothing with them. It's meant for testing
-/// larger transactions with bench-tps.
-#[derive(Clone, Copy, Debug, TryFromPrimitive, IntoPrimitive)]
-#[repr(u8)]
-pub enum PadInstruction {
- /// Does no work, but accepts a large amount of data and accounts
- Noop,
- /// Wraps the provided instruction, calling the provided program via CPI
- ///
- /// Accounts expected by this instruction:
- ///
- /// * All accounts required for the inner instruction
- /// * The program invoked by the inner instruction
- /// * Additional padding accounts
- ///
- /// Data expected by this instruction:
- /// * WrapData
- Wrap,
-}
-
-/// Data wrapping any inner instruction
-pub struct WrapData<'a> {
- /// Number of accounts required by the inner instruction
- pub num_accounts: u32,
- /// the size of the inner instruction data
- pub instruction_size: u32,
- /// actual inner instruction data
- pub instruction_data: &'a [u8],
- // additional padding bytes come after, not captured in this struct
-}
-
-const U32_BYTES: usize = 4;
-fn unpack_u32(input: &[u8]) -> Result<(u32, &[u8]), ProgramError> {
- let value = input
- .get(..U32_BYTES)
- .and_then(|slice| slice.try_into().ok())
- .map(u32::from_le_bytes)
- .ok_or(ProgramError::InvalidInstructionData)?;
- Ok((value, &input[U32_BYTES..]))
-}
-
-impl<'a> WrapData<'a> {
- /// Unpacks instruction data
- pub fn unpack(data: &'a [u8]) -> Result {
- let (num_accounts, rest) = unpack_u32(data)?;
- let (instruction_size, rest) = unpack_u32(rest)?;
-
- let (instruction_data, _rest) = rest.split_at(instruction_size as usize);
- Ok(Self {
- num_accounts,
- instruction_size,
- instruction_data,
- })
- }
-}
-
-pub fn noop(
- program_id: Pubkey,
- padding_accounts: Vec,
- padding_data: u32,
-) -> Result {
- let total_data_size = size_of::().saturating_add(padding_data as usize);
- // crude, but can find a potential issue right away
- if total_data_size > MAX_CPI_INSTRUCTION_DATA_LEN as usize {
- return Err(ProgramError::InvalidInstructionData);
- }
- let mut data = Vec::with_capacity(total_data_size);
- data.push(PadInstruction::Noop.into());
- for i in 0..padding_data {
- data.push(i.checked_rem(u8::MAX as u32).unwrap() as u8);
- }
-
- let num_accounts = padding_accounts.len().saturating_add(1);
- if num_accounts > MAX_CPI_ACCOUNT_INFOS {
- return Err(ProgramError::InvalidAccountData);
- }
- let mut accounts = Vec::with_capacity(num_accounts);
- accounts.extend(padding_accounts);
-
- Ok(Instruction {
- program_id,
- accounts,
- data,
- })
-}
-
-pub fn wrap_instruction(
- program_id: Pubkey,
- instruction: Instruction,
- padding_accounts: Vec,
- padding_data: u32,
-) -> Result {
- let total_data_size = size_of::()
- .saturating_add(size_of::())
- .saturating_add(size_of::())
- .saturating_add(instruction.data.len())
- .saturating_add(padding_data as usize);
- // crude, but can find a potential issue right away
- if total_data_size > MAX_CPI_INSTRUCTION_DATA_LEN as usize {
- return Err(ProgramError::InvalidInstructionData);
- }
- let mut data = Vec::with_capacity(total_data_size);
- data.push(PadInstruction::Wrap.into());
- let num_accounts: u32 = instruction
- .accounts
- .len()
- .try_into()
- .map_err(|_| ProgramError::InvalidInstructionData)?;
- data.extend(num_accounts.to_le_bytes().iter());
-
- let data_size: u32 = instruction
- .data
- .len()
- .try_into()
- .map_err(|_| ProgramError::InvalidInstructionData)?;
- data.extend(data_size.to_le_bytes().iter());
- data.extend(instruction.data);
- for i in 0..padding_data {
- data.push(i.checked_rem(u8::MAX as u32).unwrap() as u8);
- }
-
- // The format for account data goes:
- // * accounts required for the CPI
- // * program account to call into
- // * additional accounts may be included as padding or to test loading / locks
- let num_accounts = instruction
- .accounts
- .len()
- .saturating_add(1)
- .saturating_add(padding_accounts.len());
- if num_accounts > MAX_CPI_ACCOUNT_INFOS {
- return Err(ProgramError::InvalidAccountData);
- }
- let mut accounts = Vec::with_capacity(num_accounts);
- accounts.extend(instruction.accounts);
- accounts.push(AccountMeta::new_readonly(instruction.program_id, false));
- accounts.extend(padding_accounts);
-
- Ok(Instruction {
- program_id,
- accounts,
- data,
- })
-}
diff --git a/instruction-padding/program/src/lib.rs b/instruction-padding/program/src/lib.rs
deleted file mode 100644
index fc69c9d8a66..00000000000
--- a/instruction-padding/program/src/lib.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-mod entrypoint;
-pub mod instruction;
-pub mod processor;
-
-pub use {
- solana_account_info, solana_cpi, solana_instruction, solana_program_entrypoint,
- solana_program_error, solana_pubkey,
-};
-solana_pubkey::declare_id!("iXpADd6AW1k5FaaXum5qHbSqyd7TtoN6AD7suVa83MF");
diff --git a/instruction-padding/program/src/processor.rs b/instruction-padding/program/src/processor.rs
deleted file mode 100644
index 37439bd317d..00000000000
--- a/instruction-padding/program/src/processor.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-use {
- crate::instruction::{PadInstruction, WrapData},
- solana_account_info::AccountInfo,
- solana_cpi::invoke,
- solana_instruction::{AccountMeta, Instruction},
- solana_program_error::{ProgramError, ProgramResult},
- solana_pubkey::Pubkey,
- std::convert::TryInto,
-};
-
-pub fn process(
- _program_id: &Pubkey,
- account_infos: &[AccountInfo],
- instruction_data: &[u8],
-) -> ProgramResult {
- let (tag, rest) = instruction_data
- .split_first()
- .ok_or(ProgramError::InvalidInstructionData)?;
- match (*tag)
- .try_into()
- .map_err(|_| ProgramError::InvalidInstructionData)?
- {
- PadInstruction::Noop => Ok(()),
- PadInstruction::Wrap => {
- let WrapData {
- num_accounts,
- instruction_size,
- instruction_data,
- } = WrapData::unpack(rest)?;
- let mut data = Vec::with_capacity(instruction_size as usize);
- data.extend_from_slice(instruction_data);
-
- let program_id = *account_infos[num_accounts as usize].key;
-
- let accounts = account_infos
- .iter()
- .take(num_accounts as usize)
- .map(|a| AccountMeta {
- pubkey: *a.key,
- is_signer: a.is_signer,
- is_writable: a.is_writable,
- })
- .collect::>();
-
- let instruction = Instruction {
- program_id,
- accounts,
- data,
- };
-
- invoke(&instruction, &account_infos[..num_accounts as usize])
- }
- }
-}
diff --git a/instruction-padding/program/tests/noop.rs b/instruction-padding/program/tests/noop.rs
deleted file mode 100644
index beaba6074bb..00000000000
--- a/instruction-padding/program/tests/noop.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-#![cfg(feature = "test-sbf")]
-
-use {
- solana_program_test::{processor, tokio, ProgramTest},
- solana_sdk::{
- instruction::AccountMeta, pubkey::Pubkey, signature::Signer, transaction::Transaction,
- },
- spl_instruction_padding::{instruction::noop, processor::process},
-};
-
-#[tokio::test]
-async fn success_with_noop() {
- let program_id = Pubkey::new_unique();
- let program_test = ProgramTest::new("spl_instruction_padding", program_id, processor!(process));
-
- let context = program_test.start_with_context().await;
-
- let padding_accounts = vec![
- AccountMeta::new_readonly(Pubkey::new_unique(), false),
- AccountMeta::new_readonly(Pubkey::new_unique(), false),
- AccountMeta::new_readonly(Pubkey::new_unique(), false),
- ];
-
- let padding_data = 800;
-
- let transaction = Transaction::new_signed_with_payer(
- &[noop(program_id, padding_accounts, padding_data).unwrap()],
- Some(&context.payer.pubkey()),
- &[&context.payer],
- context.last_blockhash,
- );
-
- context
- .banks_client
- .process_transaction(transaction)
- .await
- .unwrap();
-}
diff --git a/instruction-padding/program/tests/system.rs b/instruction-padding/program/tests/system.rs
deleted file mode 100644
index 335af0bc306..00000000000
--- a/instruction-padding/program/tests/system.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-#![cfg(feature = "test-sbf")]
-
-use {
- solana_program_test::{processor, tokio, ProgramTest},
- solana_sdk::{
- instruction::AccountMeta, native_token::LAMPORTS_PER_SOL, pubkey::Pubkey,
- signature::Signer, system_instruction, transaction::Transaction,
- },
- spl_instruction_padding::{instruction::wrap_instruction, processor::process},
-};
-
-#[tokio::test]
-async fn success_with_padded_transfer_data() {
- let program_id = Pubkey::new_unique();
- let program_test = ProgramTest::new("spl_instruction_padding", program_id, processor!(process));
-
- let context = program_test.start_with_context().await;
- let to = Pubkey::new_unique();
-
- let transfer_amount = LAMPORTS_PER_SOL;
- let transfer_instruction =
- system_instruction::transfer(&context.payer.pubkey(), &to, transfer_amount);
-
- let padding_accounts = vec![
- AccountMeta::new_readonly(Pubkey::new_unique(), false),
- AccountMeta::new_readonly(Pubkey::new_unique(), false),
- AccountMeta::new_readonly(Pubkey::new_unique(), false),
- ];
-
- let padding_data = 800;
-
- let transaction = Transaction::new_signed_with_payer(
- &[wrap_instruction(
- program_id,
- transfer_instruction,
- padding_accounts,
- padding_data,
- )
- .unwrap()],
- Some(&context.payer.pubkey()),
- &[&context.payer],
- context.last_blockhash,
- );
-
- context
- .banks_client
- .process_transaction(transaction)
- .await
- .unwrap();
-
- // make sure the transfer went through
- assert_eq!(
- transfer_amount,
- context
- .banks_client
- .get_account(to)
- .await
- .unwrap()
- .unwrap()
- .lamports
- );
-}
diff --git a/libraries/README.md b/libraries/README.md
new file mode 100644
index 00000000000..7f619ec7993
--- /dev/null
+++ b/libraries/README.md
@@ -0,0 +1,13 @@
+NOTE: The actively maintained libraries now live at
+[solana-program/libraries](https://github.com/solana-program/libraries).
+
+The other repo includes:
+
+* discriminator
+* pod
+* program-error
+* tlv-account-resolution
+* type-length-value
+* type-length-value-derive-test
+
+Unmaintained libraries still live here and can still be forked.
diff --git a/libraries/discriminator/Cargo.toml b/libraries/discriminator/Cargo.toml
deleted file mode 100644
index fae99bbeea3..00000000000
--- a/libraries/discriminator/Cargo.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-[package]
-name = "spl-discriminator"
-version = "0.4.0"
-description = "Solana Program Library 8-Byte Discriminator Management"
-authors = ["Solana Labs Maintainers "]
-repository = "https://github.com/solana-labs/solana-program-library"
-license = "Apache-2.0"
-edition = "2021"
-
-[features]
-borsh = ["dep:borsh"]
-
-[dependencies]
-borsh = { version = "1", optional = true }
-bytemuck = { version = "1.21.0", features = ["derive"] }
-solana-program-error = "2.1.0"
-solana-sha256-hasher = "2.1.0"
-spl-discriminator-derive = { version = "0.2.0", path = "./derive" }
-
-[lib]
-crate-type = ["cdylib", "lib"]
-
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu"]
diff --git a/libraries/discriminator/README.md b/libraries/discriminator/README.md
deleted file mode 100644
index 8d31cc70667..00000000000
--- a/libraries/discriminator/README.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# SPL Discriminator
-
-This library allows for easy management of 8-byte discriminators.
-
-### The `ArrayDiscriminator` Struct
-
-With this crate, you can leverage the `ArrayDiscriminator` type to manage an 8-byte discriminator for generic purposes.
-
-```rust
-let my_discriminator = ArrayDiscriminator::new([8, 5, 1, 56, 10, 53, 9, 198]);
-```
-
-The `new(..)` function is also a **constant function**, so you can use `ArrayDiscriminator` in constants as well.
-
-```rust
-const MY_DISCRIMINATOR: ArrayDiscriminator = ArrayDiscriminator::new([8, 5, 1, 56, 10, 53, 9, 198]);
-```
-
-The `ArrayDiscriminator` struct also offers another constant function `as_slice(&self)`, so you can use `as_slice()` in constants as well.
-
-```rust
-const MY_DISCRIMINATOR_SLICE: &[u8] = MY_DISCRIMINATOR.as_slice();
-```
-
-### The `SplDiscriminate` Trait
-
-A trait, `SplDiscriminate` is also available, which will give you the `ArrayDiscriminator` constant type and also a slice representation of the discriminator. This can be particularly handy with match statements.
-
-```rust
-/// A trait for managing 8-byte discriminators in a slab of bytes
-pub trait SplDiscriminate {
- /// The 8-byte discriminator as a `[u8; 8]`
- const SPL_DISCRIMINATOR: ArrayDiscriminator;
- /// The 8-byte discriminator as a slice (`&[u8]`)
- const SPL_DISCRIMINATOR_SLICE: &'static [u8] = Self::SPL_DISCRIMINATOR.as_slice();
-}
-```
-
-### The `SplDiscriminate` Derive Macro
-
-The `SplDiscriminate` derive macro is a particularly useful tool for those who wish to derive their 8-byte discriminator from a particular string literal. Typically, you would have to run a hash function against the string literal, then copy the first 8 bytes, and then hard-code those bytes into a statement like the one above.
-
-Instead, you can simply annotate a struct or enum with `SplDiscriminate` and provide a **hash input** via the `discriminator_hash_input` attribute, and the macro will automatically derive the 8-byte discriminator for you!
-
-```rust
-#[derive(SplDiscriminate)] // Implements `SplDiscriminate` for your struct/enum using your declared string literal hash_input
-#[discriminator_hash_input("some_discriminator_hash_input")]
-pub struct MyInstruction1 {
- arg1: String,
- arg2: u8,
-}
-
-let my_discriminator: ArrayDiscriminator = MyInstruction1::SPL_DISCRIMINATOR;
-let my_discriminator_slice: &[u8] = MyInstruction1::SPL_DISCRIMINATOR_SLICE;
-```
-
-Note: the 8-byte discriminator derived using the macro is always the **first 8 bytes** of the resulting hashed bytes.
diff --git a/libraries/discriminator/derive/Cargo.toml b/libraries/discriminator/derive/Cargo.toml
deleted file mode 100644
index 32ce6085708..00000000000
--- a/libraries/discriminator/derive/Cargo.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-name = "spl-discriminator-derive"
-version = "0.2.0"
-description = "Derive macro library for the `spl-discriminator` library"
-authors = ["Solana Labs Maintainers "]
-repository = "https://github.com/solana-labs/solana-program-library"
-license = "Apache-2.0"
-edition = "2021"
-
-[dependencies]
-quote = "1.0"
-spl-discriminator-syn = { version = "0.2.0", path = "../syn" }
-syn = { version = "2.0", features = ["full"] }
-
-[lib]
-proc-macro = true
-
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu"]
diff --git a/libraries/discriminator/derive/src/lib.rs b/libraries/discriminator/derive/src/lib.rs
deleted file mode 100644
index 6080b80b226..00000000000
--- a/libraries/discriminator/derive/src/lib.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//! Derive macro library for the `spl-discriminator` library
-
-#![deny(missing_docs)]
-#![cfg_attr(not(test), forbid(unsafe_code))]
-
-extern crate proc_macro;
-
-use {
- proc_macro::TokenStream, quote::ToTokens, spl_discriminator_syn::SplDiscriminateBuilder,
- syn::parse_macro_input,
-};
-
-/// Derive macro library to implement the `SplDiscriminate` trait
-/// on an enum or struct
-#[proc_macro_derive(SplDiscriminate, attributes(discriminator_hash_input))]
-pub fn spl_discriminator(input: TokenStream) -> TokenStream {
- parse_macro_input!(input as SplDiscriminateBuilder)
- .to_token_stream()
- .into()
-}
diff --git a/libraries/discriminator/src/discriminator.rs b/libraries/discriminator/src/discriminator.rs
deleted file mode 100644
index aef70065c5e..00000000000
--- a/libraries/discriminator/src/discriminator.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-//! The traits and types used to create a discriminator for a type
-
-use {
- bytemuck::{Pod, Zeroable},
- solana_program_error::ProgramError,
- solana_sha256_hasher::hashv,
-};
-
-/// A trait for managing 8-byte discriminators in a slab of bytes
-pub trait SplDiscriminate {
- /// The 8-byte discriminator as a `[u8; 8]`
- const SPL_DISCRIMINATOR: ArrayDiscriminator;
- /// The 8-byte discriminator as a slice (`&[u8]`)
- const SPL_DISCRIMINATOR_SLICE: &'static [u8] = Self::SPL_DISCRIMINATOR.as_slice();
-}
-
-/// Array Discriminator type
-#[cfg_attr(
- feature = "borsh",
- derive(borsh::BorshSerialize, borsh::BorshDeserialize)
-)]
-#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
-#[repr(transparent)]
-pub struct ArrayDiscriminator([u8; ArrayDiscriminator::LENGTH]);
-impl ArrayDiscriminator {
- /// Size for discriminator in account data
- pub const LENGTH: usize = 8;
- /// Uninitialized variant of a discriminator
- pub const UNINITIALIZED: Self = Self::new([0; Self::LENGTH]);
- /// Creates a discriminator from an array
- pub const fn new(value: [u8; Self::LENGTH]) -> Self {
- Self(value)
- }
- /// Get the array as a const slice
- pub const fn as_slice(&self) -> &[u8] {
- self.0.as_slice()
- }
- /// Creates a new `ArrayDiscriminator` from some hash input string literal
- pub fn new_with_hash_input(hash_input: &str) -> Self {
- let hash_bytes = hashv(&[hash_input.as_bytes()]).to_bytes();
- let mut discriminator_bytes = [0u8; 8];
- discriminator_bytes.copy_from_slice(&hash_bytes[..8]);
- Self(discriminator_bytes)
- }
-}
-impl AsRef<[u8]> for ArrayDiscriminator {
- fn as_ref(&self) -> &[u8] {
- &self.0[..]
- }
-}
-impl AsRef<[u8; ArrayDiscriminator::LENGTH]> for ArrayDiscriminator {
- fn as_ref(&self) -> &[u8; ArrayDiscriminator::LENGTH] {
- &self.0
- }
-}
-impl From for ArrayDiscriminator {
- fn from(from: u64) -> Self {
- Self(from.to_le_bytes())
- }
-}
-impl From<[u8; Self::LENGTH]> for ArrayDiscriminator {
- fn from(from: [u8; Self::LENGTH]) -> Self {
- Self(from)
- }
-}
-impl TryFrom<&[u8]> for ArrayDiscriminator {
- type Error = ProgramError;
- fn try_from(a: &[u8]) -> Result {
- <[u8; Self::LENGTH]>::try_from(a)
- .map(Self::from)
- .map_err(|_| ProgramError::InvalidAccountData)
- }
-}
-impl From for [u8; 8] {
- fn from(from: ArrayDiscriminator) -> Self {
- from.0
- }
-}
-impl From for u64 {
- fn from(from: ArrayDiscriminator) -> Self {
- u64::from_le_bytes(from.0)
- }
-}
diff --git a/libraries/discriminator/src/lib.rs b/libraries/discriminator/src/lib.rs
deleted file mode 100644
index 5f7ddc2989f..00000000000
--- a/libraries/discriminator/src/lib.rs
+++ /dev/null
@@ -1,144 +0,0 @@
-//! Crate defining a discriminator type, which creates a set of bytes
-//! meant to be unique for instructions or struct types
-
-#![deny(missing_docs)]
-#![cfg_attr(not(test), forbid(unsafe_code))]
-
-extern crate self as spl_discriminator;
-
-/// Exports the discriminator module
-pub mod discriminator;
-
-// Export for downstream
-pub use {
- discriminator::{ArrayDiscriminator, SplDiscriminate},
- spl_discriminator_derive::SplDiscriminate,
-};
-
-#[cfg(test)]
-mod tests {
- use {super::*, crate::discriminator::ArrayDiscriminator};
-
- #[allow(dead_code)]
- #[derive(SplDiscriminate)]
- #[discriminator_hash_input("my_first_instruction")]
- pub struct MyInstruction1 {
- arg1: String,
- arg2: u8,
- }
-
- #[allow(dead_code)]
- #[derive(SplDiscriminate)]
- #[discriminator_hash_input("global:my_second_instruction")]
- pub enum MyInstruction2 {
- One,
- Two,
- Three,
- }
-
- #[allow(dead_code)]
- #[derive(SplDiscriminate)]
- #[discriminator_hash_input("global:my_instruction_with_lifetime")]
- pub struct MyInstruction3<'a> {
- data: &'a [u8],
- }
-
- #[allow(dead_code)]
- #[derive(SplDiscriminate)]
- #[discriminator_hash_input("global:my_instruction_with_one_generic")]
- pub struct MyInstruction4 {
- data: T,
- }
-
- #[allow(dead_code)]
- #[derive(SplDiscriminate)]
- #[discriminator_hash_input("global:my_instruction_with_one_generic_and_lifetime")]
- pub struct MyInstruction5<'b, T> {
- data: &'b [T],
- }
-
- #[allow(dead_code)]
- #[derive(SplDiscriminate)]
- #[discriminator_hash_input("global:my_instruction_with_multiple_generics_and_lifetime")]
- pub struct MyInstruction6<'c, U, V> {
- data1: &'c [U],
- data2: &'c [V],
- }
-
- #[allow(dead_code)]
- #[derive(SplDiscriminate)]
- #[discriminator_hash_input(
- "global:my_instruction_with_multiple_generics_and_lifetime_and_where"
- )]
- pub struct MyInstruction7<'c, U, V>
- where
- U: Clone + Copy,
- V: Clone + Copy,
- {
- data1: &'c [U],
- data2: &'c [V],
- }
-
- fn assert_discriminator(
- hash_input: &str,
- ) {
- let discriminator = build_discriminator(hash_input);
- assert_eq!(
- T::SPL_DISCRIMINATOR,
- discriminator,
- "Discriminator mismatch: case: {}",
- hash_input
- );
- assert_eq!(
- T::SPL_DISCRIMINATOR_SLICE,
- discriminator.as_slice(),
- "Discriminator mismatch: case: {}",
- hash_input
- );
- }
-
- fn build_discriminator(hash_input: &str) -> ArrayDiscriminator {
- let preimage = solana_sha256_hasher::hashv(&[hash_input.as_bytes()]);
- let mut bytes = [0u8; 8];
- bytes.copy_from_slice(&preimage.to_bytes()[..8]);
- ArrayDiscriminator::new(bytes)
- }
-
- #[test]
- fn test_discrminators() {
- let runtime_discrim = ArrayDiscriminator::new_with_hash_input("my_runtime_hash_input");
- assert_eq!(
- runtime_discrim,
- build_discriminator("my_runtime_hash_input"),
- );
-
- assert_discriminator::("my_first_instruction");
- assert_discriminator::("global:my_second_instruction");
- assert_discriminator::>("global:my_instruction_with_lifetime");
- assert_discriminator::>("global:my_instruction_with_one_generic");
- assert_discriminator::>(
- "global:my_instruction_with_one_generic_and_lifetime",
- );
- assert_discriminator::>(
- "global:my_instruction_with_multiple_generics_and_lifetime",
- );
- assert_discriminator::>(
- "global:my_instruction_with_multiple_generics_and_lifetime_and_where",
- );
- }
-}
-
-#[cfg(all(test, feature = "borsh"))]
-mod borsh_test {
- use {super::*, borsh::BorshDeserialize};
-
- #[test]
- fn borsh_test() {
- let my_discrim = ArrayDiscriminator::new_with_hash_input("my_discrim");
- let mut buffer = [0u8; 8];
- borsh::to_writer(&mut buffer[..], &my_discrim).unwrap();
- let my_discrim_again = ArrayDiscriminator::try_from_slice(&buffer).unwrap();
- assert_eq!(my_discrim, my_discrim_again);
- assert_eq!(buffer, <[u8; 8]>::from(my_discrim));
- }
-}
diff --git a/libraries/discriminator/syn/Cargo.toml b/libraries/discriminator/syn/Cargo.toml
deleted file mode 100644
index 5bd4f59ca95..00000000000
--- a/libraries/discriminator/syn/Cargo.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[package]
-name = "spl-discriminator-syn"
-version = "0.2.0"
-description = "Token parsing and generating library for the `spl-discriminator` library"
-authors = ["Solana Labs Maintainers "]
-repository = "https://github.com/solana-labs/solana-program-library"
-license = "Apache-2.0"
-edition = "2021"
-
-[dependencies]
-proc-macro2 = "1.0"
-quote = "1.0"
-sha2 = "0.10"
-syn = { version = "2.0", features = ["full"] }
-thiserror = "1.0"
-
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu"]
diff --git a/libraries/discriminator/syn/src/error.rs b/libraries/discriminator/syn/src/error.rs
deleted file mode 100644
index 5dd4c30d3c2..00000000000
--- a/libraries/discriminator/syn/src/error.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//! Error types for the `hash_input` parser
-
-/// Error types for the `hash_input` parser
-#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
-pub enum SplDiscriminateError {
- /// Discriminator hash_input attribute not provided
- #[error("Discriminator `hash_input` attribute not provided")]
- HashInputAttributeNotProvided,
- /// Error parsing discriminator hash_input attribute
- #[error("Error parsing discriminator `hash_input` attribute")]
- HashInputAttributeParseError,
-}
diff --git a/libraries/discriminator/syn/src/lib.rs b/libraries/discriminator/syn/src/lib.rs
deleted file mode 100644
index db555916573..00000000000
--- a/libraries/discriminator/syn/src/lib.rs
+++ /dev/null
@@ -1,108 +0,0 @@
-//! Token parsing and generating library for the `spl-discriminator` library
-
-#![deny(missing_docs)]
-#![cfg_attr(not(test), forbid(unsafe_code))]
-
-mod error;
-pub mod parser;
-
-use {
- crate::{error::SplDiscriminateError, parser::parse_hash_input},
- proc_macro2::{Span, TokenStream},
- quote::{quote, ToTokens},
- sha2::{Digest, Sha256},
- syn::{parse::Parse, Generics, Ident, Item, ItemEnum, ItemStruct, LitByteStr, WhereClause},
-};
-
-/// "Builder" struct to implement the `SplDiscriminate` trait
-/// on an enum or struct
-pub struct SplDiscriminateBuilder {
- /// The struct/enum identifier
- pub ident: Ident,
- /// The item's generic arguments (if any)
- pub generics: Generics,
- /// The item's where clause for generics (if any)
- pub where_clause: Option,
- /// The TLV hash_input
- pub hash_input: String,
-}
-
-impl TryFrom for SplDiscriminateBuilder {
- type Error = SplDiscriminateError;
-
- fn try_from(item_enum: ItemEnum) -> Result {
- let ident = item_enum.ident;
- let where_clause = item_enum.generics.where_clause.clone();
- let generics = item_enum.generics;
- let hash_input = parse_hash_input(&item_enum.attrs)?;
- Ok(Self {
- ident,
- generics,
- where_clause,
- hash_input,
- })
- }
-}
-
-impl TryFrom for SplDiscriminateBuilder {
- type Error = SplDiscriminateError;
-
- fn try_from(item_struct: ItemStruct) -> Result {
- let ident = item_struct.ident;
- let where_clause = item_struct.generics.where_clause.clone();
- let generics = item_struct.generics;
- let hash_input = parse_hash_input(&item_struct.attrs)?;
- Ok(Self {
- ident,
- generics,
- where_clause,
- hash_input,
- })
- }
-}
-
-impl Parse for SplDiscriminateBuilder {
- fn parse(input: syn::parse::ParseStream) -> syn::Result {
- let item = Item::parse(input)?;
- match item {
- Item::Enum(item_enum) => item_enum.try_into(),
- Item::Struct(item_struct) => item_struct.try_into(),
- _ => {
- return Err(syn::Error::new(
- Span::call_site(),
- "Only enums and structs are supported",
- ))
- }
- }
- .map_err(|e| syn::Error::new(input.span(), format!("Failed to parse item: {}", e)))
- }
-}
-
-impl ToTokens for SplDiscriminateBuilder {
- fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
- tokens.extend::(self.into());
- }
-}
-
-impl From<&SplDiscriminateBuilder> for TokenStream {
- fn from(builder: &SplDiscriminateBuilder) -> Self {
- let ident = &builder.ident;
- let generics = &builder.generics;
- let where_clause = &builder.where_clause;
- let bytes = get_discriminator_bytes(&builder.hash_input);
- quote! {
- impl #generics spl_discriminator::discriminator::SplDiscriminate for #ident #generics #where_clause {
- const SPL_DISCRIMINATOR: spl_discriminator::discriminator::ArrayDiscriminator
- = spl_discriminator::discriminator::ArrayDiscriminator::new(*#bytes);
- }
- }
- }
-}
-
-/// Returns the bytes for the TLV hash_input discriminator
-fn get_discriminator_bytes(hash_input: &str) -> LitByteStr {
- LitByteStr::new(
- &Sha256::digest(hash_input.as_bytes())[..8],
- Span::call_site(),
- )
-}
diff --git a/libraries/discriminator/syn/src/parser.rs b/libraries/discriminator/syn/src/parser.rs
deleted file mode 100644
index 1d70c3ab304..00000000000
--- a/libraries/discriminator/syn/src/parser.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-//! Parser for the `syn` crate to parse the
-//! `#[discriminator_hash_input("...")]` attribute
-
-use {
- crate::error::SplDiscriminateError,
- syn::{
- parse::{Parse, ParseStream},
- token::Comma,
- Attribute, LitStr,
- },
-};
-
-/// Struct used for `syn` parsing of the hash_input attribute
-/// #[discriminator_hash_input("...")]
-struct HashInputValueParser {
- value: LitStr,
- _comma: Option,
-}
-
-impl Parse for HashInputValueParser {
- fn parse(input: ParseStream) -> syn::Result {
- let value: LitStr = input.parse()?;
- let _comma: Option = input.parse().unwrap_or(None);
- Ok(HashInputValueParser { value, _comma })
- }
-}
-
-/// Parses the hash_input from the `#[discriminator_hash_input("...")]`
-/// attribute
-pub fn parse_hash_input(attrs: &[Attribute]) -> Result {
- match attrs
- .iter()
- .find(|a| a.path().is_ident("discriminator_hash_input"))
- {
- Some(attr) => {
- let parsed_args = attr
- .parse_args::()
- .map_err(|_| SplDiscriminateError::HashInputAttributeParseError)?;
- Ok(parsed_args.value.value())
- }
- None => Err(SplDiscriminateError::HashInputAttributeNotProvided),
- }
-}
diff --git a/libraries/math-example/tests/instruction_count.rs b/libraries/math-example/tests/instruction_count.rs
index 93025ad86cd..a7dbd26aad2 100644
--- a/libraries/math-example/tests/instruction_count.rs
+++ b/libraries/math-example/tests/instruction_count.rs
@@ -10,7 +10,7 @@ use {
#[tokio::test]
async fn test_precise_sqrt_u64_max() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
// This is way too big! It's possible to dial down the numbers to get to
// something reasonable, but the better option is to do everything in u64
@@ -28,7 +28,7 @@ async fn test_precise_sqrt_u64_max() {
#[tokio::test]
async fn test_precise_sqrt_u32_max() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
pc.set_compute_max_units(170_000);
@@ -44,7 +44,7 @@ async fn test_precise_sqrt_u32_max() {
#[tokio::test]
async fn test_sqrt_u64() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
// Dial down the BPF compute budget to detect if the operation gets bloated in
// the future
@@ -60,7 +60,7 @@ async fn test_sqrt_u64() {
#[tokio::test]
async fn test_sqrt_u128() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
// Dial down the BPF compute budget to detect if the operation gets bloated in
// the future
@@ -78,7 +78,7 @@ async fn test_sqrt_u128() {
#[tokio::test]
async fn test_sqrt_u128_max() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
pc.set_compute_max_units(7_000);
@@ -92,7 +92,7 @@ async fn test_sqrt_u128_max() {
#[tokio::test]
async fn test_u64_multiply() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
pc.set_compute_max_units(1350);
@@ -106,7 +106,7 @@ async fn test_u64_multiply() {
#[tokio::test]
async fn test_u64_divide() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
pc.set_compute_max_units(1650);
@@ -120,7 +120,7 @@ async fn test_u64_divide() {
#[tokio::test]
async fn test_f32_multiply() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
pc.set_compute_max_units(1600);
@@ -136,7 +136,7 @@ async fn test_f32_multiply() {
#[tokio::test]
async fn test_f32_divide() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
pc.set_compute_max_units(1650);
@@ -152,7 +152,7 @@ async fn test_f32_divide() {
#[tokio::test]
async fn test_f32_exponentiate() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
pc.set_compute_max_units(1400);
@@ -168,7 +168,7 @@ async fn test_f32_exponentiate() {
#[tokio::test]
async fn test_f32_natural_log() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
pc.set_compute_max_units(3500);
@@ -184,7 +184,7 @@ async fn test_f32_natural_log() {
#[tokio::test]
async fn test_f32_normal_cdf() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
// Dial down the BPF compute budget to detect if the operation gets bloated in
// the future
@@ -200,7 +200,7 @@ async fn test_f32_normal_cdf() {
#[tokio::test]
async fn test_f64_pow() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
pc.set_compute_max_units(30_000);
@@ -216,7 +216,7 @@ async fn test_f64_pow() {
#[tokio::test]
async fn test_u128_multiply() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
pc.set_compute_max_units(10000);
@@ -232,7 +232,7 @@ async fn test_u128_multiply() {
#[tokio::test]
async fn test_u128_divide() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
pc.set_compute_max_units(10000);
@@ -248,7 +248,7 @@ async fn test_u128_divide() {
#[tokio::test]
async fn test_f64_multiply() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
pc.set_compute_max_units(10000);
@@ -264,7 +264,7 @@ async fn test_f64_multiply() {
#[tokio::test]
async fn test_f64_divide() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
pc.set_compute_max_units(10000);
@@ -280,7 +280,7 @@ async fn test_f64_divide() {
#[tokio::test]
async fn test_noop() {
- let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
+ let mut pc = ProgramTest::new("spl_math_example", id(), processor!(process_instruction));
pc.set_compute_max_units(1200);
diff --git a/libraries/pod/Cargo.toml b/libraries/pod/Cargo.toml
deleted file mode 100644
index ccfc8ba3b63..00000000000
--- a/libraries/pod/Cargo.toml
+++ /dev/null
@@ -1,37 +0,0 @@
-[package]
-name = "spl-pod"
-version = "0.5.0"
-description = "Solana Program Library Plain Old Data (Pod)"
-authors = ["Solana Labs Maintainers "]
-repository = "https://github.com/solana-labs/solana-program-library"
-license = "Apache-2.0"
-edition = "2021"
-
-[features]
-serde-traits = ["dep:serde"]
-borsh = ["dep:borsh"]
-
-[dependencies]
-borsh = { version = "1.5.3", optional = true }
-bytemuck = { version = "1.21.0" }
-bytemuck_derive = { version = "1.8.1" }
-num-derive = "0.4"
-num-traits = "0.2"
-serde = { version = "1.0.217", optional = true }
-solana-decode-error = "2.1.0"
-solana-msg = "2.1.0"
-solana-program-error = "2.1.0"
-solana-program-option = "2.1.0"
-solana-pubkey = "2.1.0"
-solana-zk-sdk = "2.1.0"
-thiserror = "2.0"
-
-[dev-dependencies]
-serde_json = "1.0.135"
-base64 = { version = "0.22.1" }
-
-[lib]
-crate-type = ["cdylib", "lib"]
-
-[package.metadata.docs.rs]
-targets = ["x86_64-unknown-linux-gnu"]
diff --git a/libraries/pod/README.md b/libraries/pod/README.md
deleted file mode 100644
index 984718b5cbf..00000000000
--- a/libraries/pod/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Pod
-
-This library contains types shared by SPL libraries that implement the `Pod` trait from `bytemuck` and utils for working with these types.
diff --git a/libraries/pod/src/bytemuck.rs b/libraries/pod/src/bytemuck.rs
deleted file mode 100644
index f0039e351ed..00000000000
--- a/libraries/pod/src/bytemuck.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-//! wrappers for bytemuck functions
-
-use {bytemuck::Pod, solana_program_error::ProgramError};
-
-/// On-chain size of a `Pod` type
-pub const fn pod_get_packed_len() -> usize {
- std::mem::size_of::()
-}
-
-/// Convert a `Pod` into a slice of bytes (zero copy)
-pub fn pod_bytes_of(t: &T) -> &[u8] {
- bytemuck::bytes_of(t)
-}
-
-/// Convert a slice of bytes into a `Pod` (zero copy)
-pub fn pod_from_bytes(bytes: &[u8]) -> Result<&T, ProgramError> {
- bytemuck::try_from_bytes(bytes).map_err(|_| ProgramError::InvalidArgument)
-}
-
-/// Maybe convert a slice of bytes into a `Pod` (zero copy)
-///
-/// Returns `None` if the slice is empty, or else `Err` if input length is not
-/// equal to `pod_get_packed_len::()`.
-/// This function exists primarily because `Option` is not a `Pod`.
-pub fn pod_maybe_from_bytes(bytes: &[u8]) -> Result