diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 62f20a827..baaaa7ba9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: uses: actions/checkout@v3.1.0 with: submodules: recursive - - uses: dtolnay/rust-toolchain@1.72.0 + - uses: dtolnay/rust-toolchain@1.74.0 - name: Build run: cargo build --verbose --release - name: Run tests @@ -38,7 +38,7 @@ jobs: uses: actions/checkout@v3.1.0 with: submodules: recursive - - uses: dtolnay/rust-toolchain@1.72.0 + - uses: dtolnay/rust-toolchain@1.74.0 - name: Build run: cargo build --verbose --release - name: Run tests @@ -65,7 +65,7 @@ jobs: run: unzip c:\llvm.zip -d c:/ - name: Add LLVM to Path run: echo "c:\llvm16.0\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 - - uses: dtolnay/rust-toolchain@1.72.0 + - uses: dtolnay/rust-toolchain@1.74.0 with: components: clippy - name: Build @@ -88,7 +88,7 @@ jobs: uses: actions/checkout@v3 with: submodules: recursive - - uses: dtolnay/rust-toolchain@1.72.0 + - uses: dtolnay/rust-toolchain@1.74.0 - name: Get LLVM run: curl -sSL --output llvm16.0-mac-arm.tar.xz https://github.com/hyperledger/solang-llvm/releases/download/llvm16-0/llvm16.0-mac-arm.tar.xz - name: Extract LLVM @@ -118,7 +118,7 @@ jobs: uses: actions/checkout@v3 with: submodules: recursive - - uses: dtolnay/rust-toolchain@1.72.0 + - uses: dtolnay/rust-toolchain@1.74.0 - name: Get LLVM run: wget -q -O llvm16.0-mac-intel.tar.xz https://github.com/hyperledger/solang-llvm/releases/download/llvm16-0/llvm16.0-mac-intel.tar.xz - name: Extract LLVM diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 835fddbd4..d803c5bed 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -63,7 +63,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@master with: - toolchain: 1.72.0 + toolchain: 1.74.0 components: | llvm-tools clippy @@ -117,7 +117,7 @@ jobs: uses: actions/checkout@v3 with: submodules: recursive - - uses: dtolnay/rust-toolchain@1.72.0 + - uses: dtolnay/rust-toolchain@1.74.0 - name: Build run: cargo build --verbose - name: Run tests @@ -144,7 +144,7 @@ jobs: # Use C:\ as D:\ might run out of space - name: "Use C: for rust temporary files" run: echo "CARGO_TARGET_DIR=C:\target" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append - - uses: dtolnay/rust-toolchain@1.72.0 + - uses: dtolnay/rust-toolchain@1.74.0 with: components: clippy # We run clippy on Linux in the lint job above, but this does not check #[cfg(windows)] items @@ -170,7 +170,7 @@ jobs: uses: actions/checkout@v3 with: submodules: recursive - - uses: dtolnay/rust-toolchain@1.72.0 + - uses: dtolnay/rust-toolchain@1.74.0 - name: Get LLVM run: curl -sSL --output llvm16.0-mac-arm.tar.xz https://github.com/hyperledger/solang-llvm/releases/download/llvm16-0/llvm16.0-mac-arm.tar.xz - name: Extract LLVM @@ -196,7 +196,7 @@ jobs: uses: actions/checkout@v3 with: submodules: recursive - - uses: dtolnay/rust-toolchain@1.72.0 + - uses: dtolnay/rust-toolchain@1.74.0 - name: Get LLVM run: wget -q -O llvm16.0-mac-intel.tar.xz https://github.com/hyperledger/solang-llvm/releases/download/llvm16-0/llvm16.0-mac-intel.tar.xz - name: Extract LLVM @@ -258,7 +258,7 @@ jobs: - uses: actions/setup-node@v3 with: node-version: '16' - - uses: dtolnay/rust-toolchain@1.72.0 + - uses: dtolnay/rust-toolchain@1.74.0 - name: Setup yarn run: npm install -g yarn - uses: actions/download-artifact@v3 @@ -309,7 +309,7 @@ jobs: - uses: actions/setup-node@v3 with: node-version: '16' - - uses: dtolnay/rust-toolchain@1.72.0 + - uses: dtolnay/rust-toolchain@1.74.0 - uses: actions/download-artifact@v3 with: name: solang-linux-x86-64 @@ -348,7 +348,7 @@ jobs: # We can't run substrate node as a github actions service, since it requires # command line arguments. See https://github.com/actions/runner/pull/1152 - name: Start substrate contracts node - run: echo id=$(docker run -d -p 9944:9944 ghcr.io/hyperledger/solang-substrate-ci:ad6da01 substrate-contracts-node --dev --rpc-external -lwarn,runtime::contracts=trace) >> $GITHUB_OUTPUT + run: echo id=$(docker run -d -p 9944:9944 ghcr.io/hyperledger/solang-substrate-ci:62a8a6c substrate-contracts-node --dev --rpc-external -lwarn,runtime::contracts=trace) >> $GITHUB_OUTPUT id: substrate - uses: actions/download-artifact@v3 with: @@ -390,7 +390,7 @@ jobs: # We can't run substrate node as a github actions service, since it requires # command line arguments. See https://github.com/actions/runner/pull/1152 - name: Start substrate - run: echo id=$(docker run -d -p 9944:9944 ghcr.io/hyperledger/solang-substrate-ci:ad6da01 substrate-contracts-node --dev --rpc-external -lwarn,runtime::contracts=trace) >> $GITHUB_OUTPUT + run: echo id=$(docker run -d -p 9944:9944 ghcr.io/hyperledger/solang-substrate-ci:62a8a6c substrate-contracts-node --dev --rpc-external -lwarn,runtime::contracts=trace) >> $GITHUB_OUTPUT id: substrate - uses: actions/download-artifact@v3 with: @@ -486,7 +486,7 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@master with: - toolchain: 1.72.0 + toolchain: 1.74.0 components: llvm-tools - name: Install cargo-llvm-cov uses: taiki-e/install-action@cargo-llvm-cov diff --git a/Cargo.toml b/Cargo.toml index fa5f36474..5c537a235 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ license = "Apache-2.0" build = "build.rs" description = "Solang Solidity Compiler" keywords = [ "solidity", "compiler", "solana", "polkadot", "substrate" ] -rust-version = "1.72.0" +rust-version = "1.74.0" edition = "2021" exclude = [ "/.*", "/docs", "/examples", "/solana-library", "/tests", "/integration", "/vscode", "/testdata" ] @@ -21,8 +21,8 @@ rand = "0.8" num-bigint = { version = "0.4", features = ["rand"]} num-traits = "0.2" num-integer = "0.1" -clap = {version = "4.1", features = ["derive"]} -clap_complete = "4.1" +clap = {version = "4.5", features = ["derive"]} +clap_complete = "4.5" hex = "0.4" tiny-keccak = { version = "2.0", features = ["keccak"] } serde_json = "1.0" @@ -31,9 +31,9 @@ serde_derive = { version = "1.0" } inkwell = { version = "0.4.0", features = ["target-webassembly", "no-libffi-linking", "llvm16-0"], optional = true } blake2-rfc = "0.2.18" handlebars = "5.1" -contract-metadata = "3.2" +contract-metadata = "4.0.2" semver = { version = "1.0", features = ["serde"] } -tempfile = "3.9" +tempfile = "3.10" libc = { version = "0.2", optional = true } tower-lsp = { version = "0.20", optional = true } tokio = { version = "1.27", features = ["rt", "io-std", "macros"], optional = true } @@ -54,15 +54,15 @@ anchor-syn = { version = "0.29.0", features = ["idl-build"] } convert_case = "0.6" parse-display = "0.9" parity-scale-codec = "3.6" -ink_env = "4.3.0" -ink_metadata = "4.3.0" +ink_env = "5.0.0" +ink_metadata = "5.0.0" scale-info = "2.10" petgraph = "0.6" -wasmparser = "0.121.0" -wasm-encoder = "0.41" +wasmparser = "0.202.0" +wasm-encoder = "0.202" toml = "0.8" -wasm-opt = { version = "0.113.0", optional = true } -contract-build = { version = "3.2", optional = true } +wasm-opt = { version = "0.116.0", default-features = false, optional = true } +contract-build = { version = "4.0.2", optional = true } primitive-types = { version = "0.12", features = ["codec"] } normalize-path = "0.2.1" bitflags = "2.4" @@ -90,7 +90,7 @@ borsh = "1.1" borsh-derive = "1.1" rayon = "1" walkdir = "2.4" -ink_primitives = "4.3.0" +ink_primitives = "5.0.0" wasm_host_attr = { path = "tests/wasm_host_attr" } num-bigint = { version = "0.4", features = ["rand", "serde"]} diff --git a/Dockerfile b/Dockerfile index c921ab908..00df95197 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ COPY . src WORKDIR /src/stdlib/ RUN make -RUN rustup default 1.72.0 +RUN rustup default 1.74.0 WORKDIR /src RUN cargo build --release diff --git a/MAINTAINERS.md b/MAINTAINERS.md index fc893d940..e609393f4 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -6,3 +6,4 @@ | Sean Young | [@seanyoung](https://github.com/seanyoung) | seanyoung#0481 | | Lucas Steuernagel | [@LucasSte](https://github.com/LucasSte) | LucasSte#2331 | | Cyrill Leutwiler | [@xermicus](https://github.com/xermicus) | kägifret#8095 | +| Salaheldin Soliman| [@salaheldinsoliman](https://github.com/salaheldinsoliman) | salaheldinsoliman | diff --git a/docs/aqd.rst b/docs/aqd.rst index 071390fa0..b04d9ce78 100644 --- a/docs/aqd.rst +++ b/docs/aqd.rst @@ -265,7 +265,7 @@ Solang Aqd simplifies this process by accepting these parameters as command-line Additionally, it ensures the submitted transaction aligns with the expected values in the Interface Description Language (IDL). .. note:: - If unsure, you can always check the expected arguements and accounts for a specific function by using the ``show`` subcommand. + If unsure, you can always check the expected arguments and accounts for a specific function by using the ``show`` subcommand. Options specific to the ``call`` subcommand: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/code_gen_options.rst b/docs/code_gen_options.rst index 84f5276df..82ddc76d9 100644 --- a/docs/code_gen_options.rst +++ b/docs/code_gen_options.rst @@ -59,7 +59,7 @@ Dead Storage pass Loading from contract storage, or storing to contract storage is expensive. This optimization removes any redundant load from and store to contract storage. If the same variable is read twice, then the value from -the first load is re-used. Similarly, if there is are two successive stores to the same variable, the first +the first load is re-used. Similarly, if there are two successive stores to the same variable, the first one is removed as it is redundant. For example: .. include:: ./examples/dead_storage_elimination.sol diff --git a/docs/installing.rst b/docs/installing.rst index 7261a0089..750caba93 100644 --- a/docs/installing.rst +++ b/docs/installing.rst @@ -89,7 +89,7 @@ Option 5: Build Solang from source In order to build Solang from source, you will need: -* Rust version 1.72.0 or higher +* Rust version 1.74.0 or higher * A C++ compiler with support for C++17 * A build of LLVM based on the Solana LLVM tree. There are a few LLVM patches required that are not upstream yet. diff --git a/docs/language/events.rst b/docs/language/events.rst index 55edb5fc7..38115eef7 100644 --- a/docs/language/events.rst +++ b/docs/language/events.rst @@ -32,9 +32,9 @@ syntax. be passed for Solana's ``sol_log_data`` system call, regardless if the ``indexed`` keyword is present or not. This behavior follows what Solana's Anchor framework does. -In Polkadot, the topic fields are always the hash of the value of the field. Ethereum only hashes fields -which do not fit in the 32 bytes. Since a cryptographic hash is used, it is only possible to compare the topic against a -known value. +In Polkadot, field topics are culculated the same as in `ink! v5.0 `_: +Topic fields are either the encoded value of the field or its blake2b256 hash +if the encoded value length exceeds 32 bytes. An event can be declared in a contract, or outside. @@ -49,8 +49,10 @@ make it clearer which exact event is being emitted. .. include:: ../examples/event_positional_fields.sol :code: solidity -In the transaction log, the first topic of an event is the keccak256 hash of the signature of the -event. The signature is the event name, followed by the fields types in a comma separated list in parentheses. So -the first topic for the second UserModified event would be the keccak256 hash of ``UserModified(address,uint64)``. +In the transaction log, the topic of an event is the blake2b256 hash of the signature of the +event. The signature is the event name, followed by the fields types in a comma separated list in parentheses, +like event signatures in `Ethereum Solidity `_. So +the first topic for the second UserModified event would be the blake2b256 hash of ``UserModified(address,uint64)``. You can leave this topic out by declaring the event ``anonymous``. This makes the event slightly smaller (32 bytes less) and makes it possible to have 4 ``indexed`` fields rather than 3. + diff --git a/docs/language/using.rst b/docs/language/using.rst index 0cb57efe3..38d68d067 100644 --- a/docs/language/using.rst +++ b/docs/language/using.rst @@ -21,7 +21,7 @@ The ``using`` declaration can be done on file scope. In this case, the type must be specified in place of ``*``. The first argument must match the type that is be used in the ``using`` declaration. -If a user-defined type is used, the the ``global`` keyword can be used. This +If a user-defined type is used, the ``global`` keyword can be used. This means the ``using`` binding can be used in any file, even when the type is imported. diff --git a/docs/testing.rst b/docs/testing.rst index 84536266f..9e604b14e 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -11,11 +11,11 @@ Solidity parser and semantics tests In the `tests `_ directory, there are a lot of tests which call `fn parse_and_resolve()`. This function parses Solidity, and returns the *namespace*: all the resolved contracts, types, functions, etc (as much as could be resolved), -and all the compiler diagnositics, i.e. compiler warnings and errors. These tests check that +and all the compiler diagnostics, i.e. compiler warnings and errors. These tests check that the compiler parser and semantic analysis work correctly. -Note that Solidity can import other soldity files using the ``import`` statement. There are further -tests which create a file cache with filenames and and their contents, to ensure that imports +Note that Solidity can import other solidity files using the ``import`` statement. There are further +tests which create a file cache with filenames and their contents, to ensure that imports work as expected. diff --git a/integration/anchor/tests/call_anchor.spec.ts b/integration/anchor/tests/call_anchor.spec.ts index af8d30277..ff9e558b4 100644 --- a/integration/anchor/tests/call_anchor.spec.ts +++ b/integration/anchor/tests/call_anchor.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { AnchorProvider, Program } from '@coral-xyz/anchor'; import { diff --git a/integration/polkadot/UniswapV2ERC20.spec.ts b/integration/polkadot/UniswapV2ERC20.spec.ts index ae98bc298..e95f1a75c 100644 --- a/integration/polkadot/UniswapV2ERC20.spec.ts +++ b/integration/polkadot/UniswapV2ERC20.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, daveKeypair, query } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/UniswapV2Factory.spec.ts b/integration/polkadot/UniswapV2Factory.spec.ts index 3de5ce411..f1549282b 100644 --- a/integration/polkadot/UniswapV2Factory.spec.ts +++ b/integration/polkadot/UniswapV2Factory.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, daveKeypair, query } from './index'; import { ContractPromise } from '@polkadot/api-contract'; @@ -58,7 +60,7 @@ describe('UniswapV2Factory', () => { let events: DecodedEvent[] = res0.contractEvents; expect(events.length).toEqual(1) - expect(events[0].event.identifier).toBe('PairCreated') + expect(events[0].event.identifier).toBe('UniswapV2Factory::PairCreated') expect(events[0].args[0].toString()).toBe(TEST_ADDRESSES[0]) expect(events[0].args[1].toString()).toBe(TEST_ADDRESSES[1]) expect(events[0].args[3].eq(1)).toBeTruthy(); diff --git a/integration/polkadot/UniswapV2Pair.spec.ts b/integration/polkadot/UniswapV2Pair.spec.ts index e648baeaa..69906b6c9 100644 --- a/integration/polkadot/UniswapV2Pair.spec.ts +++ b/integration/polkadot/UniswapV2Pair.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, query, createConnection, deploy, transaction, aliceKeypair, daveKeypair } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/array_struct_mapping_storage.spec.ts b/integration/polkadot/array_struct_mapping_storage.spec.ts index cd0f23f66..b67457a1a 100644 --- a/integration/polkadot/array_struct_mapping_storage.spec.ts +++ b/integration/polkadot/array_struct_mapping_storage.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, aliceKeypair, transaction, query } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/arrays.spec.ts b/integration/polkadot/arrays.spec.ts index af516acc5..8b70e1a9c 100644 --- a/integration/polkadot/arrays.spec.ts +++ b/integration/polkadot/arrays.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import crypto from 'crypto'; import { createConnection, deploy, transaction, aliceKeypair, weight, query, } from './index'; diff --git a/integration/polkadot/asserts.spec.ts b/integration/polkadot/asserts.spec.ts index 83f300587..ec3bc437b 100644 --- a/integration/polkadot/asserts.spec.ts +++ b/integration/polkadot/asserts.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, query, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; @@ -42,8 +44,8 @@ describe('Deploy asserts contract and test', () => { throw new Error("should not succeed"); }, (res) => res); - // Error 25 is ContractReverted - expect(res2.dispatchError.toHuman()).toEqual({ "Module": { "error": "0x19000000", "index": "8" } }); + // Error 26 is ContractReverted + expect(res2.dispatchError.toHuman()).toEqual({ "Module": { "error": "0x1a000000", "index": "8" } }); let res3 = await query(conn, alice, contract, "var"); diff --git a/integration/polkadot/balances.spec.ts b/integration/polkadot/balances.spec.ts index c7b9e2be9..6e8ea3ac5 100644 --- a/integration/polkadot/balances.spec.ts +++ b/integration/polkadot/balances.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, daveKeypair, query } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/build.sh b/integration/polkadot/build.sh index 107478dfe..52b548a27 100755 --- a/integration/polkadot/build.sh +++ b/integration/polkadot/build.sh @@ -1,4 +1,6 @@ #!/bin/bash +# SPDX-License-Identifier: Apache-2.0 + set -e dup_contracts=$(grep -r '^contract .* {' | grep -v node_modules | awk '{ print $2 }' | sort | uniq -d) diff --git a/integration/polkadot/builtins.spec.ts b/integration/polkadot/builtins.spec.ts index 661c98390..a73e2dc4d 100644 --- a/integration/polkadot/builtins.spec.ts +++ b/integration/polkadot/builtins.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { createConnection, deploy, transaction, aliceKeypair, query, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/builtins2.spec.ts b/integration/polkadot/builtins2.spec.ts index 4c9cb9dd4..30ac09bdd 100644 --- a/integration/polkadot/builtins2.spec.ts +++ b/integration/polkadot/builtins2.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { createConnection, deploy, aliceKeypair, weight, query } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/call_flags.spec.ts b/integration/polkadot/call_flags.spec.ts index 33fed0ad0..3a2c2d289 100644 --- a/integration/polkadot/call_flags.spec.ts +++ b/integration/polkadot/call_flags.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { createConnection, deploy, aliceKeypair, query, debug_buffer, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; @@ -54,9 +56,9 @@ describe('Deploy the CallFlags contract and tests for various call flag combinat const flags = [CallFlags.TAIL_CALL]; const answer = await query(conn, alice, contract, "echo", [contract.address, foo, voyager, flags]); const { index, error } = answer.result.asErr.asModule; - // Module 8 error 0x15 is ReentranceDenied in the contracts pallet + // Module 8 error 0x16 is ReentranceDenied in the contracts pallet expect(index.toJSON()).toStrictEqual(8); - expect(error.toJSON()).toStrictEqual("0x15000000"); + expect(error.toJSON()).toStrictEqual("0x16000000"); }); it('fails with the input forwarding flag', async function () { diff --git a/integration/polkadot/caller_is_root.spec.ts b/integration/polkadot/caller_is_root.spec.ts index 814f22852..ea42afb1b 100644 --- a/integration/polkadot/caller_is_root.spec.ts +++ b/integration/polkadot/caller_is_root.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { createConnection, deploy, aliceKeypair, query, weight, transaction } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/chain_extension.spec.ts b/integration/polkadot/chain_extension.spec.ts index c19ae11de..542fea043 100644 --- a/integration/polkadot/chain_extension.spec.ts +++ b/integration/polkadot/chain_extension.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { createConnection, deploy, aliceKeypair, query, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/constructor_dispatch.spec.ts b/integration/polkadot/constructor_dispatch.spec.ts index 6851731ec..332820cf4 100644 --- a/integration/polkadot/constructor_dispatch.spec.ts +++ b/integration/polkadot/constructor_dispatch.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import { createConnection, deploy, aliceKeypair, query, debug_buffer, weight, transaction, daveKeypair, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; import { ApiPromise } from '@polkadot/api'; diff --git a/integration/polkadot/create_contract.spec.ts b/integration/polkadot/create_contract.spec.ts index 67603f497..009352e88 100644 --- a/integration/polkadot/create_contract.spec.ts +++ b/integration/polkadot/create_contract.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, query, debug_buffer, dry_run, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/debug_buffer_format.spec.ts b/integration/polkadot/debug_buffer_format.spec.ts index f336de3d0..0f5878a61 100644 --- a/integration/polkadot/debug_buffer_format.spec.ts +++ b/integration/polkadot/debug_buffer_format.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import { createConnection, deploy, aliceKeypair, debug_buffer } from "./index"; import expect from 'expect'; import { ContractPromise } from "@polkadot/api-contract"; diff --git a/integration/polkadot/delegate_call.spec.ts b/integration/polkadot/delegate_call.spec.ts index d03125611..94c6be58c 100644 --- a/integration/polkadot/delegate_call.spec.ts +++ b/integration/polkadot/delegate_call.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, daveKeypair, debug_buffer, query, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/destruct.spec.ts b/integration/polkadot/destruct.spec.ts index b1e956e07..0e6f4b717 100644 --- a/integration/polkadot/destruct.spec.ts +++ b/integration/polkadot/destruct.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, daveKeypair, query } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/events.sol b/integration/polkadot/events.sol index 4bf7bff50..d0689ed7b 100644 --- a/integration/polkadot/events.sol +++ b/integration/polkadot/events.sol @@ -10,6 +10,8 @@ contract Events { event ThisEventTopicShouldGetHashed(address indexed caller); event Event(bool indexed something); + event Empty(); + function emit_event() public { emit foo1(254, "hello there"); @@ -18,5 +20,7 @@ contract Events { emit ThisEventTopicShouldGetHashed(msg.sender); emit Event(true); + + emit Empty(); } } diff --git a/integration/polkadot/events.spec.ts b/integration/polkadot/events.spec.ts index 0bbac7165..d0d19af37 100644 --- a/integration/polkadot/events.spec.ts +++ b/integration/polkadot/events.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; @@ -27,64 +29,46 @@ describe('Deploy events contract and test event data, docs and topics', () => { let res0: any = await transaction(tx, alice); let events: DecodedEvent[] = res0.contractEvents; - expect(events.length).toEqual(4); + expect(events.length).toEqual(5); - expect(events[0].event.identifier).toBe("foo1"); + expect(events[0].event.identifier).toBe("Events::foo1"); expect(events[0].event.docs).toEqual(["Ladida tada"]); expect(events[0].args.map(a => a.toJSON())).toEqual([254, "hello there"]); - expect(events[1].event.identifier).toBe("foo2"); + expect(events[1].event.identifier).toBe("Events::foo2"); expect(events[1].event.docs).toEqual(["Event Foo2\n\nJust a test\n\nAuthor: them is me"]); expect(events[1].args.map(a => a.toJSON())).toEqual(["0x7fffffffffffffff", "minor", deploy_contract.address.toString()]); - expect(events[2].event.identifier).toBe("ThisEventTopicShouldGetHashed"); + expect(events[2].event.identifier).toBe("Events::ThisEventTopicShouldGetHashed"); expect(events[2].args.map(a => a.toJSON())).toEqual([alice.address]); - // In ink! the 3rd event does look like this: - // - // #[ink(event)] - // pub struct ThisEventTopicShouldGetHashed { - // #[ink(topic)] - // caller: AccountId, - // } - // - // It yields the following event topics: - // - // topics: [ - // 0x5dde952854d38c37cff349bfc574a48a831de385b82457a5c25d9d39c220f3a7 - // 0xa5af79de4a26a64813f980ffbb64ac0d7c278f67b17721423daed26ec5d3fe51 - // ] - // - // So we expect our solidity contract to produce the exact same topics: - - let hashed_event_topics = await conn.query.system.eventTopics("0x5dde952854d38c37cff349bfc574a48a831de385b82457a5c25d9d39c220f3a7"); - expect(hashed_event_topics.length).toBe(1); - let hashed_topics = await conn.query.system.eventTopics("0xa5af79de4a26a64813f980ffbb64ac0d7c278f67b17721423daed26ec5d3fe51"); - expect(hashed_topics.length).toBe(1); - - expect(events[3].event.identifier).toBe("Event"); + // Expect the 3rd event to yield the following event topics: + // - blake2x256 sum of its signature: 'ThisEventTopicShouldGetHashed(address)' + // - Address of the caller + + let field_topic = await conn.query.system.eventTopics(alice.addressRaw); + expect(field_topic.length).toBe(1); + + let event_topic = await conn.query.system.eventTopics("0x95c29b3e1b835071ab157a22d89cfc81d176add91127a1ee8766abf406a2cbc3"); + expect(event_topic.length).toBe(1); + + expect(events[3].event.identifier).toBe("Events::Event"); expect(events[3].args.map(a => a.toJSON())).toEqual([true]); - // In ink! the 4th event does look like this: - // - // #[ink(event)] - // pub struct Event { - // #[ink(topic)] - // something: bool, - // } - // - // It yields the following event topics: - // - // topics: [ - // 0x004576656e74733a3a4576656e74000000000000000000000000000000000000 - // 0x604576656e74733a3a4576656e743a3a736f6d657468696e6701000000000000 - // ] - // - // So we expect our solidity contract to produce the exact same topics: - - let unhashed_event_topics = await conn.query.system.eventTopics("0x004576656e74733a3a4576656e74000000000000000000000000000000000000"); - expect(unhashed_event_topics.length).toBe(1); - let unhashed_topics = await conn.query.system.eventTopics("0x604576656e74733a3a4576656e743a3a736f6d657468696e6701000000000000"); - expect(unhashed_topics.length).toBe(1); + // The 4th event yields the following event topics: + // - blake2x256 sum of its signature: 'Event(bool)' + // - unhashed data (because encoded length is <= 32 bytes) of 'true' + + field_topic = await conn.query.system.eventTopics("0x0100000000000000000000000000000000000000000000000000000000000000"); + expect(field_topic.length).toBe(1); + event_topic = await conn.query.system.eventTopics("0xc2bc7a077121efada8bc6a0af16c1e886406e8c2d1716979cb1b92098d8b49bc"); + expect(event_topic.length).toBe(1); + + // The 5th event yields no data and the following event topic: + // - blake2x256 sum of its signature: 'Empty()' + + event_topic = await conn.query.system.eventTopics("0x2c54a2a9a9aa474af5d6e2bb2e5a35b84051acaf95b233f98f96860d36f2b81b"); + expect(event_topic.length).toBe(1); + expect(events[4].args.map(a => a.toJSON())).toEqual([]); }); }); diff --git a/integration/polkadot/external_call.spec.ts b/integration/polkadot/external_call.spec.ts index 4e4a2100a..c010b414a 100644 --- a/integration/polkadot/external_call.spec.ts +++ b/integration/polkadot/external_call.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, query, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/flipper.spec.ts b/integration/polkadot/flipper.spec.ts index 38fc2f791..fca1fb43d 100644 --- a/integration/polkadot/flipper.spec.ts +++ b/integration/polkadot/flipper.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, query, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/index.ts b/integration/polkadot/index.ts index e75acb877..d02ee613f 100644 --- a/integration/polkadot/index.ts +++ b/integration/polkadot/index.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import '@polkadot/api-augment'; import fs, { PathLike } from 'fs'; import { ApiPromise, WsProvider, Keyring } from '@polkadot/api'; diff --git a/integration/polkadot/ink/caller/Cargo.toml b/integration/polkadot/ink/caller/Cargo.toml index 9b1dde822..5f891f046 100755 --- a/integration/polkadot/ink/caller/Cargo.toml +++ b/integration/polkadot/ink/caller/Cargo.toml @@ -5,10 +5,7 @@ authors = ["Cyrill Leutwiler "] edition = "2021" [dependencies] -ink = { version = "4.3.0", default-features = false } - -scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } -scale-info = { version = "2.10", default-features = false, features = ["derive"], optional = true } +ink = { version = "5.0.0", default-features = false } [lib] path = "lib.rs" @@ -17,8 +14,6 @@ path = "lib.rs" default = ["std"] std = [ "ink/std", - "scale/std", - "scale-info/std", ] [workspace] diff --git a/integration/polkadot/ink/caller/lib.rs b/integration/polkadot/ink/caller/lib.rs index 0586643e7..10675e646 100755 --- a/integration/polkadot/ink/caller/lib.rs +++ b/integration/polkadot/ink/caller/lib.rs @@ -5,7 +5,7 @@ #[ink::contract] mod caller { use ink::env::{ - call::{build_call, Call, ExecutionInput, Selector}, + call::{build_call, ExecutionInput, Selector}, DefaultEnvironment, }; @@ -31,7 +31,8 @@ mod caller { transfer_value: Option, ) -> u32 { build_call::() - .call_type(Call::new(callee).gas_limit(max_gas.unwrap_or_default())) + .call_v1(callee) + .gas_limit(max_gas.unwrap_or(u64::MAX)) .transferred_value(transfer_value.unwrap_or_default()) .exec_input(ExecutionInput::new(Selector::new(selector)).push_arg(arg)) .returns::() // FIXME: This should be Result to respect LanguageError diff --git a/integration/polkadot/ink_cross_calls.spec.ts b/integration/polkadot/ink_cross_calls.spec.ts index 8ce0486fa..a7c6159da 100644 --- a/integration/polkadot/ink_cross_calls.spec.ts +++ b/integration/polkadot/ink_cross_calls.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, query, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/is_contract.spec.ts b/integration/polkadot/is_contract.spec.ts index 6d18a41a3..fec01014d 100644 --- a/integration/polkadot/is_contract.spec.ts +++ b/integration/polkadot/is_contract.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { createConnection, deploy, aliceKeypair, query, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/issue666.spec.ts b/integration/polkadot/issue666.spec.ts index ff23ed68e..5292728e2 100644 --- a/integration/polkadot/issue666.spec.ts +++ b/integration/polkadot/issue666.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/msg_sender.spec.ts b/integration/polkadot/msg_sender.spec.ts index 36d2351f8..c064a9f63 100644 --- a/integration/polkadot/msg_sender.spec.ts +++ b/integration/polkadot/msg_sender.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from "expect"; import { aliceKeypair, createConnection, deploy, weight, transaction, query } from "./index"; import { ContractPromise } from "@polkadot/api-contract"; @@ -45,7 +47,7 @@ describe('Deploy mytoken contract and test', () => { expect(events.length).toEqual(1); - expect(events[0].event.identifier).toBe("Debugging"); + expect(events[0].event.identifier).toBe("mytokenEvent::Debugging"); expect(events[0].args.map(a => a.toJSON())).toEqual([alice.address]); }); }); \ No newline at end of file diff --git a/integration/polkadot/overloading.spec.ts b/integration/polkadot/overloading.spec.ts index b812ca16f..58e9ee7c1 100644 --- a/integration/polkadot/overloading.spec.ts +++ b/integration/polkadot/overloading.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { createConnection, deploy, transaction, aliceKeypair, query, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/package.json b/integration/polkadot/package.json index 6da3cd1d3..d05c2597f 100644 --- a/integration/polkadot/package.json +++ b/integration/polkadot/package.json @@ -6,7 +6,7 @@ "scripts": { "test": "tsc; ts-mocha -t 20000 --exit *.spec.ts", "build": "./build.sh", - "build-ink": "docker run --rm -v $(pwd)/ink/caller:/opt/contract ghcr.io/hyperledger/solang-substrate-ci:ad6da01 cargo contract build --release --manifest-path /opt/contract/Cargo.toml" + "build-ink": "docker run --rm -v $(pwd)/ink/caller:/opt/contract ghcr.io/hyperledger/solang-substrate-ci:62a8a6c cargo contract build --release --manifest-path /opt/contract/Cargo.toml" }, "contributors": [ { @@ -30,10 +30,10 @@ "typescript": "^4.7" }, "dependencies": { - "@polkadot/api": "^10.11", - "@polkadot/api-contract": "^10.11", + "@polkadot/api": "^10.12", + "@polkadot/api-contract": "^10.12", "@polkadot/keyring": "^12.6", - "@polkadot/types": "^10.11", + "@polkadot/types": "^10.12", "@polkadot/util-crypto": "^12.6", "websnark": "git+https://github.com/tornadocash/websnark.git#4c0af6a8b65aabea3c09f377f63c44e7a58afa6d", "snarkjs": "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5", diff --git a/integration/polkadot/primitives.spec.ts b/integration/polkadot/primitives.spec.ts index 398b0bba8..e8c7e461b 100644 --- a/integration/polkadot/primitives.spec.ts +++ b/integration/polkadot/primitives.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { createConnection, deploy, aliceKeypair, daveKeypair, query, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/release_version.spec.ts b/integration/polkadot/release_version.spec.ts index e56ccbbe1..e3f4d0063 100644 --- a/integration/polkadot/release_version.spec.ts +++ b/integration/polkadot/release_version.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import { createConnection, deploy, aliceKeypair, debug_buffer } from "./index"; import expect from 'expect'; import { ContractPromise } from "@polkadot/api-contract"; diff --git a/integration/polkadot/runtime_errors.spec.ts b/integration/polkadot/runtime_errors.spec.ts index 5bdae1961..bf75d927a 100644 --- a/integration/polkadot/runtime_errors.spec.ts +++ b/integration/polkadot/runtime_errors.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import { createConnection, deploy, aliceKeypair, debug_buffer } from "./index"; import expect from 'expect'; import { ContractPromise } from "@polkadot/api-contract"; diff --git a/integration/polkadot/set_code_hash.spec.ts b/integration/polkadot/set_code_hash.spec.ts index a588405af..e1fccbe91 100644 --- a/integration/polkadot/set_code_hash.spec.ts +++ b/integration/polkadot/set_code_hash.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { createConnection, deploy, aliceKeypair, query, debug_buffer, weight, transaction, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/store.spec.ts b/integration/polkadot/store.spec.ts index 2e3f5365b..6988035c1 100644 --- a/integration/polkadot/store.spec.ts +++ b/integration/polkadot/store.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/structs.spec.ts b/integration/polkadot/structs.spec.ts index 8d005004c..afdf96d89 100644 --- a/integration/polkadot/structs.spec.ts +++ b/integration/polkadot/structs.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { createConnection, deploy, transaction, aliceKeypair, weight, query, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/tornado.spec.ts b/integration/polkadot/tornado.spec.ts index c3bf0e816..84028501e 100644 --- a/integration/polkadot/tornado.spec.ts +++ b/integration/polkadot/tornado.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + // Tests against the tornado cash core contracts. // The tornado contracts used here contain minor mechanical changes to work fine on Polkadot. // The ZK-SNARK setup is the same as ETH Tornado on mainnet. diff --git a/integration/polkadot/try_catch.spec.ts b/integration/polkadot/try_catch.spec.ts index f110a1528..03fbaafc6 100644 --- a/integration/polkadot/try_catch.spec.ts +++ b/integration/polkadot/try_catch.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { createConnection, deploy, aliceKeypair, query, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; diff --git a/integration/polkadot/upgradeable_proxy.spec.ts b/integration/polkadot/upgradeable_proxy.spec.ts index fcff47a2a..e3f918986 100644 --- a/integration/polkadot/upgradeable_proxy.spec.ts +++ b/integration/polkadot/upgradeable_proxy.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { weight, createConnection, deploy, transaction, aliceKeypair, query, } from './index'; import { ContractPromise } from '@polkadot/api-contract'; @@ -19,8 +21,9 @@ describe('Deploy the upgradable proxy and implementations; expect the upgrade me let result: any = await transaction(proxy.tx.upgradeToAndCall({ gasLimit }, ...params), aliceKeypair()); let events: DecodedEvent[] = result.contractEvents; + console.log(events); expect(events.length).toEqual(1); - expect(events[0].event.identifier).toBe("Upgraded"); + expect(events[0].event.identifier).toBe("UpgradeableProxy::Upgraded"); expect(events[0].args.map(a => a.toJSON())[0]).toEqual(params[0].toJSON()); } diff --git a/integration/solana/simple.spec.ts b/integration/solana/simple.spec.ts index 906736b28..ed31ad2ca 100644 --- a/integration/solana/simple.spec.ts +++ b/integration/solana/simple.spec.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import expect from 'expect'; import { loadContractAndCallConstructor } from './setup'; import crypto from 'crypto'; diff --git a/integration/subxt-tests/Cargo.toml b/integration/subxt-tests/Cargo.toml index 5e312fd2b..62e955a00 100644 --- a/integration/subxt-tests/Cargo.toml +++ b/integration/subxt-tests/Cargo.toml @@ -20,8 +20,8 @@ serde_json = "1.0.96" sp-keyring = "24.0.0" subxt = { version = "0.31.0", features = ["substrate-compat"] } tokio = {version = "1.28.2", features = ["rt-multi-thread", "macros", "time"]} -contract-metadata = "3.0.1" -contract-transcode = "3.0.1" +contract-metadata = "4.0.2" +contract-transcode = "4.0.2" [workspace] members = [] diff --git a/integration/subxt-tests/src/cases/asserts.rs b/integration/subxt-tests/src/cases/asserts.rs index 71b24e758..9dcdcc249 100644 --- a/integration/subxt-tests/src/cases/asserts.rs +++ b/integration/subxt-tests/src/cases/asserts.rs @@ -59,7 +59,7 @@ async fn case() -> anyhow::Result<()> { .unwrap_err(); assert!(res .to_string() - .contains("ModuleError { index: 8, error: [25, 0, 0, 0] }")); + .contains("ModuleError { index: 8, error: [26, 0, 0, 0] }")); // state should not change after failed operation let rv = contract diff --git a/integration/subxt-tests/src/cases/events.rs b/integration/subxt-tests/src/cases/events.rs index 4af8d9281..d7a14e178 100644 --- a/integration/subxt-tests/src/cases/events.rs +++ b/integration/subxt-tests/src/cases/events.rs @@ -25,16 +25,13 @@ async fn case() -> anyhow::Result<()> { }) .await?; - assert_eq!(rs.len(), 4); + assert_eq!(rs.len(), 5); // TODO: currently event decoding is different than ink, as we can see in contract-transcode. let e1 = &rs[0]; let e1_buffer = &mut e1.data.as_slice(); - let topic = e1_buffer.read_byte()?; - assert_eq!(topic, 0); - // mimic the solidity struct type #[derive(Decode)] struct Foo1 { @@ -48,9 +45,6 @@ async fn case() -> anyhow::Result<()> { let e2 = &rs[1]; let e2_buffer = &mut e2.data.as_slice(); - let topic = e2_buffer.read_byte()?; - assert_eq!(topic, 1); - // mimic the solidity struct type #[derive(Decode)] struct Foo2 { diff --git a/integration/subxt-tests/src/cases/msg_sender.rs b/integration/subxt-tests/src/cases/msg_sender.rs index 835b635a5..159617f84 100644 --- a/integration/subxt-tests/src/cases/msg_sender.rs +++ b/integration/subxt-tests/src/cases/msg_sender.rs @@ -87,10 +87,6 @@ async fn case() -> anyhow::Result<()> { let mut evt_buffer = evt.data.as_slice(); - let topic_id = evt_buffer.read_byte()?; - - assert_eq!(topic_id, 0); - let addr = ::decode(&mut evt_buffer)?; assert_eq!(addr, sp_keyring::AccountKeyring::Alice.to_account_id()); diff --git a/solang-parser/src/lexer.rs b/solang-parser/src/lexer.rs index c8f50eb7b..73700cd7c 100644 --- a/solang-parser/src/lexer.rs +++ b/solang-parser/src/lexer.rs @@ -190,9 +190,9 @@ impl<'input> fmt::Display for Token<'input> { Token::StringLiteral(true, s) => write!(f, "unicode\"{s}\""), Token::HexLiteral(hex) => write!(f, "{hex}"), Token::AddressLiteral(address) => write!(f, "{address}"), - Token::Number(integer, exp) if exp.is_empty() => write!(f, "{integer}"), + Token::Number(integer, "") => write!(f, "{integer}"), Token::Number(integer, exp) => write!(f, "{integer}e{exp}"), - Token::RationalNumber(integer, fraction, exp) if exp.is_empty() => { + Token::RationalNumber(integer, fraction, "") => { write!(f, "{integer}.{fraction}") } Token::RationalNumber(integer, fraction, exp) => { diff --git a/src/abi/polkadot.rs b/src/abi/polkadot.rs index b1b575b6e..30eb6bf8f 100644 --- a/src/abi/polkadot.rs +++ b/src/abi/polkadot.rs @@ -3,6 +3,7 @@ use contract_metadata::{ CodeHash, Compiler, Contract, ContractMetadata, Language, Source, SourceCompiler, SourceLanguage, SourceWasm, }; +use ink_env::hash::{Blake2x256, CryptoHash}; use ink_metadata::{ layout::{FieldLayout, Layout, LayoutKey, LeafLayout, RootLayout, StructLayout}, ConstructorSpec, ContractSpec, EnvironmentSpec, EventParamSpec, EventSpec, InkProject, @@ -21,6 +22,7 @@ use semver::Version; use solang_parser::pt; use crate::{ + codegen::polkadot::SCRATCH_SIZE, codegen::revert::{SolidityError, ERROR_SELECTOR, PANIC_SELECTOR}, sema::{ ast::{self, ArrayLength, EventDecl, Function}, @@ -285,7 +287,7 @@ fn type_to_storage_layout( } /// Generate `InkProject` from `ast::Type` and `ast::Namespace` -pub fn gen_project(contract_no: usize, ns: &ast::Namespace) -> InkProject { +pub fn gen_project<'a>(contract_no: usize, ns: &'a ast::Namespace) -> InkProject { let mut registry = PortableRegistryBuilder::new(); // This is only used by off-chain tooling. At the moment there is no such tooling available yet. @@ -302,6 +304,7 @@ pub fn gen_project(contract_no: usize, ns: &ast::Namespace) -> InkProject { let root = RootLayout::new( layout_key, type_to_storage_layout(ty, layout_key, ®istry), + ty.into(), ); Some(FieldLayout::new(var.name.clone(), root)) } else { @@ -341,7 +344,7 @@ pub fn gen_project(contract_no: usize, ns: &ast::Namespace) -> InkProject { .payable(payable) .args(args) .docs(vec![render(&f.tags).as_str()]) - .returns(ReturnTypeSpec::new(None)) + .returns(ReturnTypeSpec::new(TypeSpec::default())) .done() }; @@ -407,7 +410,7 @@ pub fn gen_project(contract_no: usize, ns: &ast::Namespace) -> InkProject { Some(TypeSpec::new(ty.into(), path)) } }; - let ret_type = ReturnTypeSpec::new(ret_spec); + let ret_type = ReturnTypeSpec::new(ret_spec.unwrap_or_default()); let args = f .params .iter() @@ -445,7 +448,8 @@ pub fn gen_project(contract_no: usize, ns: &ast::Namespace) -> InkProject { .map(message_spec) .collect::>>(); - let mut event_spec = |e: &EventDecl| -> EventSpec { + // ink! v5 ABI wants declared events to be unique; collect the signature into a HashMap + let mut event_spec = |e: &'a EventDecl| -> (&'a str, EventSpec) { let args = e .fields .iter() @@ -460,19 +464,29 @@ pub fn gen_project(contract_no: usize, ns: &ast::Namespace) -> InkProject { .done() }) .collect::>(); - EventSpec::new(e.id.name.clone()) + let topic = (!e.anonymous).then(|| { + let mut buf = [0; 32]; + ::hash(e.signature.as_bytes(), &mut buf); + buf + }); + let event = EventSpec::new(e.id.name.clone()) .args(args) .docs(vec![render(&e.tags).as_str()]) - .done() + .signature_topic(topic) + .module_path(ns.contracts[contract_no].id.name.as_str()) + .done(); + let signature = e.signature.as_str(); + + (signature, event) }; let events = ns.contracts[contract_no] .emits_events .iter() - .map(|event_no| { - let event = &ns.events[*event_no]; - event_spec(event) - }) + .map(|event_no| event_spec(&ns.events[*event_no])) + .collect::>>() + .drain() + .map(|(_, spec)| spec) .collect::>>(); let environment: EnvironmentSpec = EnvironmentSpec::new() @@ -510,6 +524,7 @@ pub fn gen_project(contract_no: usize, ns: &ast::Namespace) -> InkProject { primitive_to_ty(&ast::Type::Uint(64), &mut registry).into(), path!("Timestamp"), )) + .static_buffer_size(SCRATCH_SIZE as usize) .done(); let mut error_definitions = vec![ @@ -591,5 +606,5 @@ pub fn metadata( let project_json = serde_json::to_value(gen_project(contract_no, ns)).unwrap(); let abi = serde_json::from_value(project_json).unwrap(); - serde_json::to_value(ContractMetadata::new(source, contract, None, abi)).unwrap() + serde_json::to_value(ContractMetadata::new(source, contract, None, None, abi)).unwrap() } diff --git a/src/bin/idl/mod.rs b/src/bin/idl/mod.rs index bb6e980e0..d2e81eb91 100644 --- a/src/bin/idl/mod.rs +++ b/src/bin/idl/mod.rs @@ -386,7 +386,7 @@ fn program_id(idl: &Idl) -> Option<&String> { /// There are many keywords in Solidity which are not keywords in Rust, so they may /// occur as field name, function name, etc. Rename those fields by prepending /// underscores until unique -fn rename_keywords(name_map: &mut Vec<(String, String)>) { +fn rename_keywords(name_map: &mut [(String, String)]) { for i in 0..name_map.len() { let name = &name_map[i].0; diff --git a/src/codegen/events/polkadot.rs b/src/codegen/events/polkadot.rs index 9ae1ba6c3..967124e82 100644 --- a/src/codegen/events/polkadot.rs +++ b/src/codegen/events/polkadot.rs @@ -1,6 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -use std::collections::VecDeque; use std::vec; use crate::codegen::cfg::{ControlFlowGraph, Instr}; @@ -11,11 +10,12 @@ use crate::codegen::vartable::Vartable; use crate::codegen::{Builtin, Expression, Options}; use crate::sema::ast::{self, Function, Namespace, RetrieveType, Type}; use ink_env::hash::{Blake2x256, CryptoHash}; -use parity_scale_codec::Encode; use solang_parser::pt; -/// This struct implements the trait 'EventEmitter' in order to handle the emission of events -/// for Polkadot +/// Implements [EventEmitter] to handle the emission of events on Polkadot. +/// Data and topic encoding follow [ink! v5.0][0]. +/// +/// [0]: https://use.ink/basics/events/#topics pub(super) struct PolkadotEventEmitter<'a> { /// Arguments passed to the event pub(super) args: &'a [ast::Expression], @@ -24,23 +24,10 @@ pub(super) struct PolkadotEventEmitter<'a> { } impl EventEmitter for PolkadotEventEmitter<'_> { - fn selector(&self, emitting_contract_no: usize) -> Vec { - let event = &self.ns.events[self.event_no]; - // For freestanding events the name of the emitting contract is used - let contract_name = &self.ns.contracts[event.contract.unwrap_or(emitting_contract_no)] - .id - .name; - - // First byte is 0 because there is no prefix for the event topic - let encoded = format!("\0{}::{}", contract_name, &event.id); - - // Takes a scale-encoded topic and makes it into a topic hash. + fn selector(&self, _emitting_contract_no: usize) -> Vec { + let signature = self.ns.events[self.event_no].signature.as_bytes(); let mut buf = [0; 32]; - if encoded.len() <= 32 { - buf[..encoded.len()].copy_from_slice(encoded.as_bytes()); - } else { - ::hash(encoded.as_bytes(), &mut buf); - }; + ::hash(signature, &mut buf); buf.into() } @@ -54,53 +41,24 @@ impl EventEmitter for PolkadotEventEmitter<'_> { ) { let loc = pt::Loc::Builtin; let event = &self.ns.events[self.event_no]; - // For freestanding events the name of the emitting contract is used - let contract_name = &self.ns.contracts[event.contract.unwrap_or(contract_no)] - .id - .name; let hash_len = Box::new(Expression::NumberLiteral { loc, ty: Type::Uint(32), value: 32.into(), }); - let id = self.ns.contracts[contract_no] - .emits_events - .iter() - .position(|e| *e == self.event_no) - .expect("contract emits this event"); - let mut data = vec![Expression::NumberLiteral { - loc, - ty: Type::Uint(8), - value: id.into(), - }]; - let mut topics = vec![]; + let (mut data, mut topics) = (Vec::new(), Vec::new()); // Events that are not anonymous always have themselves as a topic. // This is static and can be calculated at compile time. if !event.anonymous { - let topic_hash = self.selector(contract_no); - - // First byte is 0 because there is no prefix for the event topic topics.push(Expression::AllocDynamicBytes { loc, ty: Type::Slice(Type::Uint(8).into()), size: hash_len.clone(), - initializer: Some(topic_hash), + initializer: self.selector(contract_no).into(), }); }; - // Topic prefixes are static and can be calculated at compile time. - let mut topic_prefixes: VecDeque> = event - .fields - .iter() - .filter(|field| field.indexed) - .map(|field| { - format!("{}::{}::{}", contract_name, &event.id, &field.name_as_str()) - .into_bytes() - .encode() - }) - .collect(); - for (ast_exp, field) in self.args.iter().zip(event.fields.iter()) { let value_exp = expression(ast_exp, cfg, contract_no, Some(func), self.ns, vartab, opt); let value_var = vartab.temp_anonymous(&value_exp.ty()); @@ -123,25 +81,7 @@ impl EventEmitter for PolkadotEventEmitter<'_> { continue; } - let encoded = abi_encode(&loc, vec![value], self.ns, vartab, cfg, false).0; - let first_prefix = topic_prefixes.pop_front().unwrap(); - let prefix = Expression::AllocDynamicBytes { - loc, - ty: Type::Slice(Type::Bytes(1).into()), - size: Expression::NumberLiteral { - loc, - ty: Type::Uint(32), - value: first_prefix.len().into(), - } - .into(), - initializer: Some(first_prefix), - }; - let concatenated = Expression::Builtin { - loc, - kind: Builtin::Concat, - tys: vec![Type::DynamicBytes], - args: vec![prefix, encoded], - }; + let (value_encoded, size) = abi_encode(&loc, vec![value], self.ns, vartab, cfg, false); vartab.new_dirty_tracker(); let var_buffer = vartab.temp_anonymous(&Type::DynamicBytes); @@ -150,7 +90,7 @@ impl EventEmitter for PolkadotEventEmitter<'_> { Instr::Set { loc, res: var_buffer, - expr: concatenated, + expr: value_encoded, }, ); let buffer = Expression::Variable { @@ -158,25 +98,19 @@ impl EventEmitter for PolkadotEventEmitter<'_> { ty: Type::DynamicBytes, var_no: var_buffer, }; - let compare = Expression::More { + + let hash_topic_block = cfg.new_basic_block("hash_topic".into()); + let done_block = cfg.new_basic_block("done".into()); + let size_is_greater_than_hash_length = Expression::More { loc, signed: false, - left: Expression::Builtin { - loc, - tys: vec![Type::Uint(32)], - kind: Builtin::ArrayLength, - args: vec![buffer.clone()], - } - .into(), + left: size.clone().into(), right: hash_len.clone(), }; - - let hash_topic_block = cfg.new_basic_block("hash_topic".into()); - let done_block = cfg.new_basic_block("done".into()); cfg.add( vartab, Instr::BranchCond { - cond: compare, + cond: size_is_greater_than_hash_length, true_block: hash_topic_block, false_block: done_block, }, @@ -209,12 +143,31 @@ impl EventEmitter for PolkadotEventEmitter<'_> { topics.push(buffer); } - let data = abi_encode(&loc, data, self.ns, vartab, cfg, false).0; + let data = self + .args + .iter() + .map(|e| expression(e, cfg, contract_no, Some(func), self.ns, vartab, opt)) + .collect::>(); + let encoded_data = data + .is_empty() + .then(|| Expression::AllocDynamicBytes { + loc, + ty: Type::DynamicBytes, + size: Expression::NumberLiteral { + loc, + ty: Type::Uint(32), + value: 0.into(), + } + .into(), + initializer: Vec::new().into(), + }) + .unwrap_or_else(|| abi_encode(&loc, data, self.ns, vartab, cfg, false).0); + cfg.add( vartab, Instr::EmitEvent { event_no: self.event_no, - data, + data: encoded_data, topics, }, ); diff --git a/src/codegen/polkadot.rs b/src/codegen/polkadot.rs index 12ad13873..511eec0c9 100644 --- a/src/codegen/polkadot.rs +++ b/src/codegen/polkadot.rs @@ -14,6 +14,9 @@ use crate::{ sema::ast::{Namespace, Type}, }; +// When using the seal api, we use our own scratch buffer. +pub const SCRATCH_SIZE: u32 = 32 * 1024; + /// Helper to handle error cases from external function and constructor calls. pub(crate) struct RetCodeCheck { pub success: usize, diff --git a/src/emit/polkadot/mod.rs b/src/emit/polkadot/mod.rs index 7be53f978..4078efadf 100644 --- a/src/emit/polkadot/mod.rs +++ b/src/emit/polkadot/mod.rs @@ -2,6 +2,7 @@ use std::ffi::CString; +use crate::codegen::polkadot::SCRATCH_SIZE; use crate::codegen::{Options, STORAGE_INITIALIZER}; use crate::sema::ast::{Contract, Namespace}; use inkwell::context::Context; @@ -16,9 +17,6 @@ use crate::emit::{Binary, TargetRuntime}; mod storage; pub(super) mod target; -// When using the seal api, we use our own scratch buffer. -const SCRATCH_SIZE: u32 = 32 * 1024; - pub struct PolkadotTarget; impl PolkadotTarget { diff --git a/src/emit/polkadot/target.rs b/src/emit/polkadot/target.rs index 8e1d46f4b..9e9eacde0 100644 --- a/src/emit/polkadot/target.rs +++ b/src/emit/polkadot/target.rs @@ -1,10 +1,11 @@ // SPDX-License-Identifier: Apache-2.0 use crate::codegen::cfg::HashTy; +use crate::codegen::polkadot::SCRATCH_SIZE; use crate::codegen::revert::PanicCode; use crate::emit::binary::Binary; use crate::emit::expression::expression; -use crate::emit::polkadot::{PolkadotTarget, SCRATCH_SIZE}; +use crate::emit::polkadot::PolkadotTarget; use crate::emit::storage::StorageSlot; use crate::emit::{ContractArgs, TargetRuntime, Variable}; use crate::sema::ast; diff --git a/src/sema/contracts.rs b/src/sema/contracts.rs index 13515d5e1..647de2c55 100644 --- a/src/sema/contracts.rs +++ b/src/sema/contracts.rs @@ -1259,21 +1259,22 @@ fn compatible_visibility(left: &pt::Visibility, right: &pt::Visibility) -> bool } /// This function checks which function names must be mangled given a contract. -/// Mangling happens when there is more than one function with the same name in a give contract. +/// Mangling happens when there is more than one function with the same name in the given `contract_no`. fn mangle_function_names(contract_no: usize, ns: &mut Namespace) { let mut repeated_names: HashMap = HashMap::new(); for func_no in ns.contracts[contract_no].all_functions.keys() { - if !ns.functions[*func_no].is_public() - && (ns.functions[*func_no].ty != pt::FunctionTy::Function - || ns.functions[*func_no].ty != pt::FunctionTy::Constructor) - { + let function = &ns.functions[*func_no]; + + let not_callable = !function.is_public() + && (function.ty != pt::FunctionTy::Function + || function.ty != pt::FunctionTy::Constructor); + + if function.is_override.is_some() || not_callable { continue; } - if let Some(old_no) = - repeated_names.insert(ns.functions[*func_no].id.name.clone(), *func_no) - { + if let Some(old_no) = repeated_names.insert(function.id.name.clone(), *func_no) { ns.functions[old_no] .mangled_name_contracts .insert(contract_no); diff --git a/src/sema/expression/arithmetic.rs b/src/sema/expression/arithmetic.rs index 8150adc73..16883688a 100644 --- a/src/sema/expression/arithmetic.rs +++ b/src/sema/expression/arithmetic.rs @@ -227,12 +227,19 @@ pub(super) fn shift_left( let (right_length, _) = type_bits_and_sign(&right.ty(), &r.loc(), false, ns, diagnostics)?; let left_type = left.ty().deref_any().clone(); + let right_type = right.ty().deref_any().clone(); Ok(Expression::ShiftLeft { loc: *loc, ty: left_type.clone(), left: Box::new(left.cast(loc, &left_type, true, ns, diagnostics)?), - right: Box::new(cast_shift_arg(loc, right, right_length, &left_type, ns)), + right: Box::new(cast_shift_arg( + loc, + right.cast(loc, &right_type, true, ns, diagnostics)?, + right_length, + &left_type, + ns, + )), }) } @@ -252,6 +259,7 @@ pub(super) fn shift_right( check_var_usage_expression(ns, &left, &right, symtable); let left_type = left.ty().deref_any().clone(); + let right_type = right.ty().deref_any().clone(); // left hand side may be bytes/int/uint // right hand size may be int/uint let _ = type_bits_and_sign(&left_type, &l.loc(), true, ns, diagnostics)?; @@ -261,7 +269,13 @@ pub(super) fn shift_right( loc: *loc, ty: left_type.clone(), left: Box::new(left.cast(loc, &left_type, true, ns, diagnostics)?), - right: Box::new(cast_shift_arg(loc, right, right_length, &left_type, ns)), + right: Box::new(cast_shift_arg( + loc, + right.cast(loc, &right_type, true, ns, diagnostics)?, + right_length, + &left_type, + ns, + )), sign: left_type.is_signed_int(ns), }) } diff --git a/testdata/ink/mother.json b/testdata/ink/mother.json index ce4f35bc7..006529a8c 100644 --- a/testdata/ink/mother.json +++ b/testdata/ink/mother.json @@ -1,26 +1,27 @@ { "source": { - "hash": "0x05cc2edbb7547b2311d2a442aac3c183e055bf1f3faa96568b4a68e3ac5e17f0", - "language": "ink! 4.2.0", - "compiler": "rustc 1.69.0", + "hash": "0xd3f781649eacf23e57a65b0dd8f59142c92e6e2cd4656da874a594431d7399a9", + "language": "ink! 5.0.0", + "compiler": "rustc 1.73.0", "build_info": { "build_mode": "Debug", - "cargo_contract_version": "3.0.1", + "cargo_contract_version": "4.0.2", "rust_toolchain": "stable-x86_64-unknown-linux-gnu", "wasm_opt_settings": { "keep_debug_symbols": false, - "optimization_passes": "Zero" + "optimization_passes": "Z" } } }, "contract": { "name": "mother", - "version": "4.2.0", + "version": "5.0.0", "authors": [ "Parity Technologies " ], "description": "Mother of all contracts" }, + "image": null, "spec": { "constructors": [ { @@ -31,7 +32,7 @@ "displayName": [ "Auction" ], - "type": 13 + "type": 24 } } ], @@ -44,7 +45,7 @@ "ink_primitives", "ConstructorResult" ], - "type": 18 + "type": 29 }, "selector": "0x9bae9d5e" }, @@ -59,7 +60,7 @@ "ink_primitives", "ConstructorResult" ], - "type": 18 + "type": 29 }, "selector": "0x61ef7e3e" }, @@ -86,7 +87,7 @@ "ink_primitives", "ConstructorResult" ], - "type": 21 + "type": 31 }, "selector": "0x87a495f6" } @@ -115,7 +116,7 @@ "displayName": [ "ChainExtension" ], - "type": 27 + "type": 38 }, "hash": { "displayName": [ @@ -124,11 +125,12 @@ "type": 1 }, "maxEventTopics": 4, + "staticBufferSize": 16384, "timestamp": { "displayName": [ "Timestamp" ], - "type": 26 + "type": 37 } }, "events": [ @@ -142,14 +144,16 @@ "displayName": [ "Auction" ], - "type": 13 + "type": 24 } } ], "docs": [ "Event emitted when an auction being echoed." ], - "label": "AuctionEchoed" + "label": "AuctionEchoed", + "module_path": "mother::mother", + "signature_topic": "0x9f3c1597e0c1071a300ddb58b0474976b0d066c9a445c8a4677e5cebb5f8980a" } ], "lang_error": { @@ -157,7 +161,7 @@ "ink", "LangError" ], - "type": 20 + "type": 30 }, "messages": [ { @@ -168,7 +172,7 @@ "displayName": [ "Auction" ], - "type": 13 + "type": 24 } } ], @@ -184,7 +188,7 @@ "ink", "MessageResult" ], - "type": 24 + "type": 34 }, "selector": "0xbc7ac4cf" }, @@ -196,7 +200,7 @@ "displayName": [ "Option" ], - "type": 25 + "type": 35 } } ], @@ -212,7 +216,7 @@ "ink", "MessageResult" ], - "type": 21 + "type": 31 }, "selector": "0xe62a1df5" }, @@ -240,9 +244,37 @@ "ink", "MessageResult" ], - "type": 18 + "type": 29 }, "selector": "0x238582df" + }, + { + "args": [ + { + "label": "message", + "type": { + "displayName": [ + "String" + ], + "type": 0 + } + } + ], + "default": false, + "docs": [ + " Mutates the input string to return \"Hello, { name }\"" + ], + "label": "mut_hello_world", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 36 + }, + "selector": "0x23c47128" } ] }, @@ -411,20 +443,37 @@ "root": { "layout": { "leaf": { - "key": "0x013a6e2b", + "key": "0x2b6e3a01", "ty": 9 } }, - "root_key": "0x013a6e2b" + "root_key": "0x2b6e3a01", + "ty": 13 } }, "name": "balances" + }, + { + "layout": { + "root": { + "layout": { + "leaf": { + "key": "0x8482a36e", + "ty": 0 + } + }, + "root_key": "0x8482a36e", + "ty": 18 + } + }, + "name": "log" } ], "name": "Mother" } }, - "root_key": "0x00000000" + "root_key": "0x00000000", + "ty": 23 } }, "types": [ @@ -595,6 +644,258 @@ }, { "id": 13, + "type": { + "def": { + "composite": {} + }, + "params": [ + { + "name": "K", + "type": 8 + }, + { + "name": "V", + "type": 9 + }, + { + "name": "KeyType", + "type": 14 + } + ], + "path": [ + "ink_storage", + "lazy", + "mapping", + "Mapping" + ] + } + }, + { + "id": 14, + "type": { + "def": { + "composite": {} + }, + "params": [ + { + "name": "L", + "type": 15 + }, + { + "name": "R", + "type": 16 + } + ], + "path": [ + "ink_storage_traits", + "impls", + "ResolverKey" + ] + } + }, + { + "id": 15, + "type": { + "def": { + "composite": {} + }, + "path": [ + "ink_storage_traits", + "impls", + "AutoKey" + ] + } + }, + { + "id": 16, + "type": { + "def": { + "composite": {} + }, + "params": [ + { + "name": "ParentKey", + "type": 17 + } + ], + "path": [ + "ink_storage_traits", + "impls", + "ManualKey" + ] + } + }, + { + "id": 17, + "type": { + "def": { + "tuple": [] + } + } + }, + { + "id": 18, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "len", + "type": 21, + "typeName": "Lazy" + }, + { + "name": "elements", + "type": 22, + "typeName": "Mapping" + } + ] + } + }, + "params": [ + { + "name": "V", + "type": 0 + }, + { + "name": "KeyType", + "type": 19 + } + ], + "path": [ + "ink_storage", + "lazy", + "vec", + "StorageVec" + ] + } + }, + { + "id": 19, + "type": { + "def": { + "composite": {} + }, + "params": [ + { + "name": "L", + "type": 15 + }, + { + "name": "R", + "type": 20 + } + ], + "path": [ + "ink_storage_traits", + "impls", + "ResolverKey" + ] + } + }, + { + "id": 20, + "type": { + "def": { + "composite": {} + }, + "params": [ + { + "name": "ParentKey", + "type": 17 + } + ], + "path": [ + "ink_storage_traits", + "impls", + "ManualKey" + ] + } + }, + { + "id": 21, + "type": { + "def": { + "composite": {} + }, + "params": [ + { + "name": "V", + "type": 10 + }, + { + "name": "KeyType", + "type": 19 + } + ], + "path": [ + "ink_storage", + "lazy", + "Lazy" + ] + } + }, + { + "id": 22, + "type": { + "def": { + "composite": {} + }, + "params": [ + { + "name": "K", + "type": 10 + }, + { + "name": "V", + "type": 0 + }, + { + "name": "KeyType", + "type": 19 + } + ], + "path": [ + "ink_storage", + "lazy", + "mapping", + "Mapping" + ] + } + }, + { + "id": 23, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "auction", + "type": 24, + "typeName": ",>>::Type" + }, + { + "name": "balances", + "type": 13, + "typeName": " as::ink::storage::traits::\nAutoStorableHint<::ink::storage::traits::ManualKey<20606507u32, ()\n>,>>::Type" + }, + { + "name": "log", + "type": 18, + "typeName": " as::ink::storage::traits::AutoStorableHint<\n::ink::storage::traits::ManualKey<1856209540u32, ()>,>>::Type" + } + ] + } + }, + "path": [ + "mother", + "mother", + "Mother" + ] + } + }, + { + "id": 24, "type": { "def": { "composite": { @@ -611,17 +912,17 @@ }, { "name": "bids", - "type": 14, + "type": 25, "typeName": "Bids" }, { "name": "terms", - "type": 15, + "type": 26, "typeName": "[BlockNumber; 3]" }, { "name": "status", - "type": 16, + "type": 27, "typeName": "Status" }, { @@ -645,7 +946,7 @@ } }, { - "id": 14, + "id": 25, "type": { "def": { "composite": { @@ -665,7 +966,7 @@ } }, { - "id": 15, + "id": 26, "type": { "def": { "array": { @@ -676,7 +977,7 @@ } }, { - "id": 16, + "id": 27, "type": { "def": { "variant": { @@ -702,7 +1003,7 @@ { "fields": [ { - "type": 17, + "type": 28, "typeName": "Outline" } ], @@ -730,7 +1031,7 @@ } }, { - "id": 17, + "id": 28, "type": { "def": { "variant": { @@ -758,7 +1059,7 @@ } }, { - "id": 18, + "id": 29, "type": { "def": { "variant": { @@ -766,7 +1067,7 @@ { "fields": [ { - "type": 19 + "type": 17 } ], "index": 0, @@ -775,7 +1076,7 @@ { "fields": [ { - "type": 20 + "type": 30 } ], "index": 1, @@ -787,11 +1088,11 @@ "params": [ { "name": "T", - "type": 19 + "type": 17 }, { "name": "E", - "type": 20 + "type": 30 } ], "path": [ @@ -800,15 +1101,7 @@ } }, { - "id": 19, - "type": { - "def": { - "tuple": [] - } - } - }, - { - "id": 20, + "id": 30, "type": { "def": { "variant": { @@ -827,7 +1120,7 @@ } }, { - "id": 21, + "id": 31, "type": { "def": { "variant": { @@ -835,7 +1128,7 @@ { "fields": [ { - "type": 22 + "type": 32 } ], "index": 0, @@ -844,7 +1137,7 @@ { "fields": [ { - "type": 20 + "type": 30 } ], "index": 1, @@ -856,11 +1149,11 @@ "params": [ { "name": "T", - "type": 22 + "type": 32 }, { "name": "E", - "type": 20 + "type": 30 } ], "path": [ @@ -869,7 +1162,7 @@ } }, { - "id": 22, + "id": 32, "type": { "def": { "variant": { @@ -877,7 +1170,7 @@ { "fields": [ { - "type": 19 + "type": 17 } ], "index": 0, @@ -886,7 +1179,7 @@ { "fields": [ { - "type": 23 + "type": 33 } ], "index": 1, @@ -898,11 +1191,11 @@ "params": [ { "name": "T", - "type": 19 + "type": 17 }, { "name": "E", - "type": 23 + "type": 33 } ], "path": [ @@ -911,7 +1204,7 @@ } }, { - "id": 23, + "id": 33, "type": { "def": { "variant": { @@ -941,7 +1234,7 @@ } }, { - "id": 24, + "id": 34, "type": { "def": { "variant": { @@ -949,7 +1242,7 @@ { "fields": [ { - "type": 13 + "type": 24 } ], "index": 0, @@ -958,7 +1251,7 @@ { "fields": [ { - "type": 20 + "type": 30 } ], "index": 1, @@ -970,11 +1263,11 @@ "params": [ { "name": "T", - "type": 13 + "type": 24 }, { "name": "E", - "type": 20 + "type": 30 } ], "path": [ @@ -983,7 +1276,7 @@ } }, { - "id": 25, + "id": 35, "type": { "def": { "variant": { @@ -995,7 +1288,7 @@ { "fields": [ { - "type": 23 + "type": 33 } ], "index": 1, @@ -1007,7 +1300,7 @@ "params": [ { "name": "T", - "type": 23 + "type": 33 } ], "path": [ @@ -1016,7 +1309,49 @@ } }, { - "id": 26, + "id": 36, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 0 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 30 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 0 + }, + { + "name": "E", + "type": 30 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 37, "type": { "def": { "primitive": "u64" @@ -1024,7 +1359,7 @@ } }, { - "id": 27, + "id": 38, "type": { "def": { "variant": {} @@ -1037,5 +1372,5 @@ } } ], - "version": "4" + "version": 5 } \ No newline at end of file diff --git a/testdata/solang_import_resolution_tests/01_solang_remap_target/run.sh b/testdata/solang_import_resolution_tests/01_solang_remap_target/run.sh index 82a6adee9..e87279a38 100755 --- a/testdata/solang_import_resolution_tests/01_solang_remap_target/run.sh +++ b/testdata/solang_import_resolution_tests/01_solang_remap_target/run.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 + # shellcheck source=/dev/null source "../util.sh" diff --git a/testdata/solang_import_resolution_tests/02_solang_incorrect_direct_imports/run.sh b/testdata/solang_import_resolution_tests/02_solang_incorrect_direct_imports/run.sh index ee1c54df8..e02376476 100755 --- a/testdata/solang_import_resolution_tests/02_solang_incorrect_direct_imports/run.sh +++ b/testdata/solang_import_resolution_tests/02_solang_incorrect_direct_imports/run.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 + # shellcheck source=/dev/null source "../util.sh" diff --git a/testdata/solang_import_resolution_tests/03_ambiguous_imports_should_fail/run.sh b/testdata/solang_import_resolution_tests/03_ambiguous_imports_should_fail/run.sh index 1acc50275..92db8cc80 100755 --- a/testdata/solang_import_resolution_tests/03_ambiguous_imports_should_fail/run.sh +++ b/testdata/solang_import_resolution_tests/03_ambiguous_imports_should_fail/run.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 + # shellcheck source=/dev/null source "../util.sh" diff --git a/testdata/solang_import_resolution_tests/04_multiple_map_path_segments/run.sh b/testdata/solang_import_resolution_tests/04_multiple_map_path_segments/run.sh index ea58d7265..b9cee6869 100755 --- a/testdata/solang_import_resolution_tests/04_multiple_map_path_segments/run.sh +++ b/testdata/solang_import_resolution_tests/04_multiple_map_path_segments/run.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 + # shellcheck source=/dev/null source "../util.sh" diff --git a/testdata/solang_import_resolution_tests/05_import_path_order_should_not_matter/run.sh b/testdata/solang_import_resolution_tests/05_import_path_order_should_not_matter/run.sh index 9293665b8..a9e6cb318 100755 --- a/testdata/solang_import_resolution_tests/05_import_path_order_should_not_matter/run.sh +++ b/testdata/solang_import_resolution_tests/05_import_path_order_should_not_matter/run.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 + # shellcheck source=/dev/null source "../util.sh" diff --git a/testdata/solang_import_resolution_tests/06_redundant_remaps/run.sh b/testdata/solang_import_resolution_tests/06_redundant_remaps/run.sh index 964f19957..7e1e43142 100755 --- a/testdata/solang_import_resolution_tests/06_redundant_remaps/run.sh +++ b/testdata/solang_import_resolution_tests/06_redundant_remaps/run.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 + # shellcheck source=/dev/null source "../util.sh" diff --git a/testdata/solang_import_resolution_tests/run.sh b/testdata/solang_import_resolution_tests/run.sh index ec82d8b37..6353e5f98 100755 --- a/testdata/solang_import_resolution_tests/run.sh +++ b/testdata/solang_import_resolution_tests/run.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 + function print_test_set_banner { diff --git a/testdata/solang_import_resolution_tests/util.sh b/testdata/solang_import_resolution_tests/util.sh index 4ee7b4a89..2cdcd1149 100644 --- a/testdata/solang_import_resolution_tests/util.sh +++ b/testdata/solang_import_resolution_tests/util.sh @@ -1,4 +1,6 @@ #!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 + function run_solc { if [ -z ${SOLC+x} ]; then diff --git a/tests/codegen_testcases/solidity/common_subexpression_elimination.sol b/tests/codegen_testcases/solidity/common_subexpression_elimination.sol index 8e952d25b..c55dd479a 100644 --- a/tests/codegen_testcases/solidity/common_subexpression_elimination.sol +++ b/tests/codegen_testcases/solidity/common_subexpression_elimination.sol @@ -305,8 +305,8 @@ contract c1 { int p = a + get(a/(2*b), b); bool e = (ast == bst) || p < 2; - // CHECK: ty:bool %2.cse_temp = (strcmp (%ast) (%bst)) - // CHECK: branchcond %2.cse_temp, block2, block1 + // CHECK: ty:bool %3.cse_temp = (strcmp (%ast) (%bst)) + // CHECK: branchcond %3.cse_temp, block2, block1 bool e2 = e; // CHECK: branchcond (strcmp ((builtin Concat (%ast, %bst))) (%cst)), block3, block4 if (string.concat(ast, bst) == cst) { @@ -315,7 +315,7 @@ contract c1 { emit testEvent(a + get(a/(2*b) -p, b), p, string.concat(ast, bst)); } - // CHECK: branchcond %2.cse_temp, block21, block22 + // CHECK: branchcond %3.cse_temp, block21, block22 if (ast == bst) { ast = string.concat(ast, "b"); } diff --git a/tests/codegen_testcases/solidity/struct_member_shift.sol b/tests/codegen_testcases/solidity/struct_member_shift.sol new file mode 100644 index 000000000..5506b7abc --- /dev/null +++ b/tests/codegen_testcases/solidity/struct_member_shift.sol @@ -0,0 +1,29 @@ +// RUN: --target polkadot --emit cfg +contract c { + struct S { + uint256 a; + } + function test1(S memory s) public pure returns (uint256) { +// CHECK: ty:uint256 %b = (uint256 2 << (load (struct (arg #0) field 0))) + uint256 b = 2 << s.a; + return b; + } + + function test2(S memory s) public pure returns (uint256) { +// CHECK: ty:uint256 %b = ((load (struct (arg #0) field 0)) << uint256 2) + uint256 b = s.a << 2; + return b; + } + + function test3(S memory s) public pure returns (uint256) { +// CHECK: ty:uint256 %b = (uint256 2 >> (load (struct (arg #0) field 0))) + uint256 b = 2 >> s.a; + return b; + } + + function test4(S memory s) public pure returns (uint256) { +// CHECK: ty:uint256 %b = ((load (struct (arg #0) field 0)) >> uint256 2) + uint256 b = s.a >> 2; + return b; + } +} diff --git a/tests/polkadot_tests/abi.rs b/tests/polkadot_tests/abi.rs index a2147a2fe..b150b0d3a 100644 --- a/tests/polkadot_tests/abi.rs +++ b/tests/polkadot_tests/abi.rs @@ -6,7 +6,7 @@ use once_cell::sync::Lazy; use scale_info::{ form::PortableForm, Path, TypeDef, TypeDefComposite, TypeDefPrimitive, TypeDefVariant, }; -use std::sync::Mutex; +use std::{collections::HashSet, sync::Mutex}; macro_rules! path { ($( $segments:expr ),*) => { @@ -284,3 +284,57 @@ fn custom_errors_in_metadata() { _ => panic!("expected uint256 type"), } } + +#[test] +fn overriden_but_not_overloaded_function_not_mangled() { + let src = r#"abstract contract Base { + function test() public pure virtual returns (uint8) { + return 42; + } + } + + contract TestA is Base {} + + contract TestB is Base { + function test() public pure override returns (uint8) { + return 42; + } + }"#; + + for abi in build_wasm(src, false).iter().map(|(_, abi)| load_abi(abi)) { + assert_eq!(abi.spec().messages().len(), 1); + assert_eq!(abi.spec().messages().first().unwrap().label(), "test"); + } +} + +#[test] +fn overloaded_but_not_overridden_function_is_mangled() { + let src = r#"abstract contract Base { + function test() public pure virtual returns (uint8) { + return 42; + } + + } + + contract TestA is Base { + function test(uint8 foo) public pure returns (uint8) { + return foo; + } + }"#; + + let mut expected_function_names = HashSet::from(["test_", "test_uint8"]); + + for message_spec in build_wasm(src, false) + .first() + .map(|(_, abi)| load_abi(abi)) + .expect("there should be a contract") + .spec() + .messages() + { + expected_function_names + .take(message_spec.label().as_str()) + .unwrap_or_else(|| panic!("{} should be present", message_spec.label())); + } + + assert!(expected_function_names.is_empty()); +} diff --git a/tests/polkadot_tests/events.rs b/tests/polkadot_tests/events.rs index 3f2e8c910..c746eaff3 100644 --- a/tests/polkadot_tests/events.rs +++ b/tests/polkadot_tests/events.rs @@ -1,10 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::build_solidity; -use ink_env::{ - hash::{Blake2x256, CryptoHash}, - topics::PrefixedValue, -}; +use ink_env::hash::{Blake2x256, CryptoHash}; use ink_primitives::{AccountId, Hash}; use parity_scale_codec::Encode; use solang::{file_resolver::FileResolver, Target}; @@ -20,6 +17,12 @@ fn topic_hash(encoded: &[u8]) -> Hash { buf.into() } +fn event_topic(signature: &str) -> Hash { + let mut buf = [0; 32]; + ::hash(signature.as_bytes(), &mut buf); + buf.into() +} + #[test] fn anonymous() { let mut runtime = build_solidity( @@ -38,16 +41,15 @@ fn anonymous() { assert_eq!(runtime.events().len(), 1); let event = &runtime.events()[0]; assert_eq!(event.topics.len(), 0); - assert_eq!(event.data, (0u8, true).encode()); + assert_eq!(event.data, true.encode()); } #[test] fn emit() { #[derive(Encode)] - enum Event { - Foo(bool, u32, i64), - Bar(u32, u64, String), - } + struct Foo(bool, u32, i64); + #[derive(Encode)] + struct Bar(u32, u64, String); let mut runtime = build_solidity( r#" @@ -67,30 +69,20 @@ fn emit() { assert_eq!(runtime.events().len(), 2); let event = &runtime.events()[0]; assert_eq!(event.topics.len(), 2); - assert_eq!(event.topics[0], topic_hash(b"\0a::foo")); - let topic = PrefixedValue { - prefix: b"a::foo::i", - value: &1i64, - } - .encode(); - assert_eq!(event.topics[1], topic_hash(&topic[..])); - assert_eq!(event.data, Event::Foo(true, 102, 1).encode()); + assert_eq!(event.topics[0], event_topic("foo(bool,uint32,int64)")); + assert_eq!(event.topics[1], topic_hash(&1i64.encode()[..])); + assert_eq!(event.data, Foo(true, 102, 1).encode()); let event = &runtime.events()[1]; assert_eq!(event.topics.len(), 2); println!("topic hash: {:?}", event.topics[0]); println!("topic hash: {:?}", event.topics[0]); - assert_eq!(event.topics[0], topic_hash(b"\0a::bar")); - let topic = PrefixedValue { - prefix: b"a::bar::s", - value: &String::from("foobar"), - } - .encode(); - assert_eq!(event.topics[1], topic_hash(&topic[..])); + assert_eq!(event.topics[0], event_topic("bar(uint32,uint64,string)")); assert_eq!( - event.data, - Event::Bar(0xdeadcafe, 102, "foobar".into()).encode() + event.topics[1], + topic_hash(&"foobar".to_string().encode()[..]) ); + assert_eq!(event.data, Bar(0xdeadcafe, 102, "foobar".into()).encode()); } #[test] @@ -216,16 +208,7 @@ fn event_imported() { #[test] fn erc20_ink_example() { #[derive(Encode)] - enum Event { - Transfer(AccountId, AccountId, u128), - } - - #[derive(Encode)] - struct Transfer { - from: AccountId, - to: AccountId, - value: u128, - } + struct Transfer(AccountId, AccountId, u128); let mut runtime = build_solidity( r##" @@ -245,26 +228,19 @@ fn erc20_ink_example() { let from = AccountId::from([1; 32]); let to = AccountId::from([2; 32]); let value = 10; - runtime.function("emit_event", Transfer { from, to, value }.encode()); + runtime.function("emit_event", Transfer(from, to, value).encode()); assert_eq!(runtime.events().len(), 1); let event = &runtime.events()[0]; - assert_eq!(event.data, Event::Transfer(from, to, value).encode()); + assert_eq!(event.data, Transfer(from, to, value).encode()); assert_eq!(event.topics.len(), 3); - assert_eq!(event.topics[0], topic_hash(b"\0Erc20::Transfer")); - - let expected_topic = PrefixedValue { - prefix: b"Erc20::Transfer::from", - value: &from, - }; - assert_eq!(event.topics[1], topic_hash(&expected_topic.encode())); - - let expected_topic = PrefixedValue { - prefix: b"Erc20::Transfer::to", - value: &to, - }; - assert_eq!(event.topics[2], topic_hash(&expected_topic.encode())); + assert_eq!( + event.topics[0], + event_topic("Transfer(address,address,uint128)") + ); + assert_eq!(event.topics[1], topic_hash(&from.encode())); + assert_eq!(event.topics[2], topic_hash(&to.encode())); } #[test] @@ -287,13 +263,9 @@ fn freestanding() { assert_eq!(runtime.events().len(), 1); let event = &runtime.events()[0]; - assert_eq!(event.data, (0u8, true).encode()); - assert_eq!(event.topics[0], topic_hash(b"\0a::A")); - let expected_topic = PrefixedValue { - prefix: b"a::A::b", - value: &true, - }; - assert_eq!(event.topics[1], topic_hash(&expected_topic.encode())); + assert_eq!(event.data, true.encode()); + assert_eq!(event.topics[0], event_topic("A(bool)")); + assert_eq!(event.topics[1], topic_hash(&true.encode())); } #[test] @@ -308,11 +280,7 @@ fn different_contract() { assert_eq!(runtime.events().len(), 1); let event = &runtime.events()[0]; - assert_eq!(event.data, (0u8, true).encode()); - assert_eq!(event.topics[0], topic_hash(b"\0A::X")); - let expected_topic = PrefixedValue { - prefix: b"A::X::foo", - value: &true, - }; - assert_eq!(event.topics[1], topic_hash(&expected_topic.encode())); + assert_eq!(event.data, true.encode()); + assert_eq!(event.topics[0], event_topic("X(bool)")); + assert_eq!(event.topics[1], topic_hash(&true.encode())); } diff --git a/vscode/src/client/extension.ts b/vscode/src/client/extension.ts index c723760a6..bc470aaba 100644 --- a/vscode/src/client/extension.ts +++ b/vscode/src/client/extension.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + // The module 'vscode' contains the VS Code extensibility API // Import the module and reference it with the alias vscode in your code below import * as vscode from 'vscode'; diff --git a/vscode/src/server/server.ts b/vscode/src/server/server.ts index a1d81cbf1..8ea6d8b50 100644 --- a/vscode/src/server/server.ts +++ b/vscode/src/server/server.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import { createConnection, InitializeResult, DefinitionRequest } from 'vscode-languageserver'; import * as rpc from 'vscode-jsonrpc'; diff --git a/vscode/src/test/runTest.ts b/vscode/src/test/runTest.ts index 014c3a28f..c8d3f9fd2 100644 --- a/vscode/src/test/runTest.ts +++ b/vscode/src/test/runTest.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import * as path from 'path'; import { runTests } from '@vscode/test-electron'; diff --git a/vscode/src/test/suite/extension.test.ts b/vscode/src/test/suite/extension.test.ts index d7357b06f..9a891c71b 100644 --- a/vscode/src/test/suite/extension.test.ts +++ b/vscode/src/test/suite/extension.test.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import * as assert from 'assert'; import * as vscode from 'vscode'; diff --git a/vscode/src/test/suite/helper.ts b/vscode/src/test/suite/helper.ts index a5cef66df..c94347004 100644 --- a/vscode/src/test/suite/helper.ts +++ b/vscode/src/test/suite/helper.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import * as vscode from 'vscode'; import * as path from 'path'; diff --git a/vscode/src/test/suite/index.ts b/vscode/src/test/suite/index.ts index 2cc239093..25eb58cc3 100644 --- a/vscode/src/test/suite/index.ts +++ b/vscode/src/test/suite/index.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import * as path from 'path'; import * as Mocha from 'mocha'; import * as glob from 'glob'; diff --git a/vscode/src/utils/download.ts b/vscode/src/utils/download.ts index 19d13ace0..ccbd4e50e 100644 --- a/vscode/src/utils/download.ts +++ b/vscode/src/utils/download.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import * as vscode from 'vscode'; import * as path from 'path'; import * as crypto from 'crypto'; diff --git a/vscode/src/utils/downloadFile.ts b/vscode/src/utils/downloadFile.ts index 1874c22a4..de8cddff9 100644 --- a/vscode/src/utils/downloadFile.ts +++ b/vscode/src/utils/downloadFile.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import fetch from 'node-fetch'; import { PathLike, createWriteStream } from 'fs'; import * as stream from 'stream'; diff --git a/vscode/src/utils/downloadWithRetryDialog.ts b/vscode/src/utils/downloadWithRetryDialog.ts index 9e8d8ba2a..e5c758674 100644 --- a/vscode/src/utils/downloadWithRetryDialog.ts +++ b/vscode/src/utils/downloadWithRetryDialog.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import * as vscode from 'vscode'; export default async function downloadWithRetryDialog(downloadFunc: () => Promise): Promise { diff --git a/vscode/src/utils/executableVersion.ts b/vscode/src/utils/executableVersion.ts index 4cd8c14fb..b814dd389 100644 --- a/vscode/src/utils/executableVersion.ts +++ b/vscode/src/utils/executableVersion.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import { spawnSync } from 'child_process'; export default function executableVersion(path: string): string | undefined { diff --git a/vscode/src/utils/expandPathResolving.ts b/vscode/src/utils/expandPathResolving.ts index d28a22d3b..fb50ef4ef 100644 --- a/vscode/src/utils/expandPathResolving.ts +++ b/vscode/src/utils/expandPathResolving.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import { homedir } from 'os'; export default function expandPathResolving(path: string): string { diff --git a/vscode/src/utils/fetchLatestRelease.ts b/vscode/src/utils/fetchLatestRelease.ts index c85883fbe..8df10155f 100644 --- a/vscode/src/utils/fetchLatestRelease.ts +++ b/vscode/src/utils/fetchLatestRelease.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import fetch from 'node-fetch'; export default async function fetchLatestRelease() { diff --git a/vscode/src/utils/getPlatform.ts b/vscode/src/utils/getPlatform.ts index ac32b5267..0bd6d2604 100644 --- a/vscode/src/utils/getPlatform.ts +++ b/vscode/src/utils/getPlatform.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + export default function getPlatform(): string | undefined { switch (`${process.arch} ${process.platform}`) { case 'x64 win32': diff --git a/vscode/src/utils/getServer.ts b/vscode/src/utils/getServer.ts index 40245c88c..d239934ff 100644 --- a/vscode/src/utils/getServer.ts +++ b/vscode/src/utils/getServer.ts @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + import * as vscode from 'vscode'; import * as path from 'path'; import { promises as fs } from 'fs';