Compare commits

..

3 Commits

Author SHA1 Message Date
kvpanch f549a6b031 Infer full LLVM release version from git's tags (#437)
The helps to remove special casing from actions and will make future
LLVM updates smoother.
2025-12-22 16:23:29 -05:00
xermicus be6f734cfc Use the EVM call gas syscall variants (#436)
- Emit the `call_evm` and `delegate_call_evm` syscalls for contract
calls.
- The call gas is no longer ignored.

---------

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2025-12-18 17:01:24 +01:00
xermicus 25ee4eef5a dedicated safe integer truncation integration test (#435)
Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
2025-12-17 10:25:41 +01:00
34 changed files with 320 additions and 444 deletions
+47 -69
View File
@@ -20,27 +20,22 @@ runs:
shell: bash shell: bash
run: | run: |
if [ -z "${{ inputs.version }}" ]; then if [ -z "${{ inputs.version }}" ]; then
# Extract branch from .gitmodules (e.g., "release/18.x") # Get the full version from the LLVM submodule.
BRANCH=$(git config -f .gitmodules submodule.llvm.branch) git submodule update --init --recursive
if [ -n "$BRANCH" ]; then cd llvm
# Extract version from branch name (e.g., "18.x" from "release/18.x") # Try to get the most recent tag (e.g., "llvmorg-18.1.8")
VERSION_PREFIX=$(echo "$BRANCH" | sed 's|release/||' | sed 's|\.x$||') LLVM_TAG=$(git describe --tags --abbrev=0 2>/dev/null)
echo "Detected LLVM version prefix from submodule branch: $VERSION_PREFIX" if [ -n "$LLVM_TAG" ]; then
echo "Detected LLVM version from submodule: $LLVM_TAG"
# Special case: pin LLVM 18 to specific version 18.1.8 # Convert "llvmorg-x.y.z" to "llvm-x.y.z"
if [ "$VERSION_PREFIX" = "18" ]; then LLVM_VERSION=$(echo "$LLVM_TAG" | sed 's/^llvmorg-/llvm-/')
echo "Using pinned version for LLVM 18: llvm-18.1.8" echo "Detected LLVM version from submodule: $LLVM_VERSION"
echo "version_prefix=llvm-18.1.8" >> $GITHUB_OUTPUT echo "version_prefix=$LLVM_VERSION" >> $GITHUB_OUTPUT
elif [ "$VERSION_PREFIX" = "21" ]; then
echo "Using pinned version for LLVM 21: llvm-21.1.6"
echo "version_prefix=llvm-21.1.6" >> $GITHUB_OUTPUT
else
echo "version_prefix=llvm-$VERSION_PREFIX" >> $GITHUB_OUTPUT
fi
else else
echo "No branch found in .gitmodules, will use latest release" echo "Could not detect LLVM version from submodule, will use latest release"
echo "version_prefix=" >> $GITHUB_OUTPUT echo "version_prefix=" >> $GITHUB_OUTPUT
fi fi
cd ..
else else
echo "Using explicitly provided version: ${{ inputs.version }}" echo "Using explicitly provided version: ${{ inputs.version }}"
echo "version_prefix=${{ inputs.version }}" >> $GITHUB_OUTPUT echo "version_prefix=${{ inputs.version }}" >> $GITHUB_OUTPUT
@@ -56,15 +51,12 @@ runs:
result-encoding: string result-encoding: string
script: | script: |
let page = 1; let page = 1;
let allReleases = []; let releases = [];
let target = process.env.target let target = process.env.target
let versionPrefix = process.env.version_prefix let versionPrefix = process.env.version_prefix
// Fetch all releases from all pages do {
core.info('Fetching releases from revive repository...');
let hasMorePages = true;
while (hasMorePages) {
const res = await github.rest.repos.listReleases({ const res = await github.rest.repos.listReleases({
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
@@ -72,57 +64,43 @@ runs:
page, page,
}); });
if (res.data.length > 0) { releases = res.data
core.info(`Page ${page}: Fetched ${res.data.length} releases`); releases.sort((a, b) => {
allReleases.push(...res.data); return (a.published_at < b.published_at) ? 1 : ((a.published_at > b.published_at) ? -1 : 0);
page++; });
let llvmRelease;
if (versionPrefix) {
// Search for latest release matching the version prefix
llvmRelease = releases.find(release => {
return release.tag_name.startsWith(versionPrefix);
});
if (llvmRelease) {
core.info(`Found LLVM release matching prefix '${versionPrefix}': ${llvmRelease.tag_name}`);
}
} else { } else {
hasMorePages = false; // Find latest LLVM release
llvmRelease = releases.find(release => {
return release.tag_name.startsWith('llvm-');
});
if (llvmRelease) {
core.info(`Found latest LLVM version: ${llvmRelease.tag_name}`);
}
} }
}
core.info(`Total releases fetched: ${allReleases.length}`); if (llvmRelease){
let asset = llvmRelease.assets.find(asset =>{
// Sort all releases by publication date (newest first) return asset.name.includes(target);
allReleases.sort((a, b) => { });
return (a.published_at < b.published_at) ? 1 : ((a.published_at > b.published_at) ? -1 : 0); if (!asset){
}); core.setFailed(`Artifact for '${target}' not found in release ${llvmRelease.tag_name} (${llvmRelease.html_url})`);
process.exit();
// Debug: Print all LLVM releases }
const llvmReleases = allReleases.filter(r => r.tag_name.startsWith('llvm-')); return asset.browser_download_url;
core.info(`Found ${llvmReleases.length} LLVM releases in total:`);
llvmReleases.forEach(r => {
core.info(` - ${r.tag_name} (published: ${r.published_at})`);
});
// Find the appropriate LLVM release
let llvmRelease;
if (versionPrefix) {
// Search for latest release matching the version prefix
llvmRelease = llvmReleases.find(release => {
return release.tag_name.startsWith(versionPrefix);
});
if (llvmRelease) {
core.info(`Selected LLVM release matching prefix '${versionPrefix}': ${llvmRelease.tag_name}`);
} }
} else {
// Find latest LLVM release (first in sorted list)
llvmRelease = llvmReleases[0];
if (llvmRelease) {
core.info(`Selected latest LLVM version: ${llvmRelease.tag_name}`);
}
}
if (llvmRelease) { page++;
let asset = llvmRelease.assets.find(asset => { } while(releases.length > 0);
return asset.name.includes(target);
});
if (!asset) {
core.setFailed(`Artifact for '${target}' not found in release ${llvmRelease.tag_name} (${llvmRelease.html_url})`);
process.exit();
}
return asset.browser_download_url;
}
if (versionPrefix) { if (versionPrefix) {
core.setFailed(`No LLVM releases matching prefix '${versionPrefix}' found! Please check the version.`); core.setFailed(`No LLVM releases matching prefix '${versionPrefix}' found! Please check the version.`);
+1 -1
View File
@@ -85,7 +85,7 @@ jobs:
cat /etc/apt/sources.list cat /etc/apt/sources.list
sudo sed -i 's/jammy/noble/g' /etc/apt/sources.list sudo sed -i 's/jammy/noble/g' /etc/apt/sources.list
cat /etc/apt/sources.list cat /etc/apt/sources.list
sudo apt-get update && sudo apt-get install -y cmake ninja-build curl git libssl-dev pkg-config clang lld musl xz-utils libc6-dev gcc-multilib g++ build-essential linux-libc-dev sudo apt-get update && sudo apt-get install -y cmake ninja-build curl git libssl-dev pkg-config clang lld musl xz-utils libc6-dev gcc-multilib
- name: Install Dependencies - name: Install Dependencies
if: ${{ matrix.host == 'macos' }} if: ${{ matrix.host == 'macos' }}
+3 -3
View File
@@ -92,7 +92,7 @@ jobs:
if: ${{ matrix.type == 'native' }} if: ${{ matrix.type == 'native' }}
shell: bash shell: bash
run: | run: |
export LLVM_SYS_211_PREFIX=$PWD/llvm-${{ matrix.target }} export LLVM_SYS_181_PREFIX=$PWD/llvm-${{ matrix.target }}
make install-bin make install-bin
mv target/release/resolc resolc-${{ matrix.target }} || mv target/release/resolc.exe resolc-${{ matrix.target }}.exe mv target/release/resolc resolc-${{ matrix.target }} || mv target/release/resolc.exe resolc-${{ matrix.target }}.exe
@@ -103,7 +103,7 @@ jobs:
cd /opt/revive cd /opt/revive
chown -R root:root . chown -R root:root .
apt update && apt upgrade -y && apt install -y pkg-config apt update && apt upgrade -y && apt install -y pkg-config
export LLVM_SYS_211_PREFIX=/opt/revive/llvm-${{ matrix.target }} export LLVM_SYS_181_PREFIX=/opt/revive/llvm-${{ matrix.target }}
make install-bin make install-bin
mv target/${{ matrix.target }}/release/resolc resolc-${{ matrix.target }} mv target/${{ matrix.target }}/release/resolc resolc-${{ matrix.target }}
" "
@@ -163,7 +163,7 @@ jobs:
- name: Build - name: Build
run: | run: |
export LLVM_SYS_211_PREFIX=$PWD/llvm-x86_64-unknown-linux-gnu export LLVM_SYS_181_PREFIX=$PWD/llvm-x86_64-unknown-linux-gnu
export REVIVE_LLVM_TARGET_PREFIX=$PWD/llvm-wasm32-unknown-emscripten export REVIVE_LLVM_TARGET_PREFIX=$PWD/llvm-wasm32-unknown-emscripten
source emsdk/emsdk_env.sh source emsdk/emsdk_env.sh
make install-wasm make install-wasm
+1 -1
View File
@@ -47,7 +47,7 @@ jobs:
- name: Set LLVM Environment Variables - name: Set LLVM Environment Variables
run: | run: |
echo "LLVM_SYS_211_PREFIX=$(pwd)/llvm-x86_64-unknown-linux-gnu" >> $GITHUB_ENV echo "LLVM_SYS_181_PREFIX=$(pwd)/llvm-x86_64-unknown-linux-gnu" >> $GITHUB_ENV
echo "REVIVE_LLVM_TARGET_PREFIX=$(pwd)/llvm-wasm32-unknown-emscripten" >> $GITHUB_ENV echo "REVIVE_LLVM_TARGET_PREFIX=$(pwd)/llvm-wasm32-unknown-emscripten" >> $GITHUB_ENV
- name: Build Revive - name: Build Revive
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
- name: Set LLVM Environment Variables - name: Set LLVM Environment Variables
run: | run: |
echo "LLVM_SYS_211_PREFIX=$(pwd)/llvm-x86_64-unknown-linux-gnu" >> $GITHUB_ENV echo "LLVM_SYS_181_PREFIX=$(pwd)/llvm-x86_64-unknown-linux-gnu" >> $GITHUB_ENV
- name: Install Geth - name: Install Geth
run: | run: |
+1 -1
View File
@@ -1,4 +1,4 @@
[submodule "llvm"] [submodule "llvm"]
path = llvm path = llvm
url = https://github.com/llvm/llvm-project.git url = https://github.com/llvm/llvm-project.git
branch = release/21.x branch = release/18.x
+2
View File
@@ -16,10 +16,12 @@ Supported `polkadot-sdk` rev: `unstable2507`
- Standard JSON mode: Don't forward EVM bytecode related output selections to solc. - Standard JSON mode: Don't forward EVM bytecode related output selections to solc.
- The supported `polkadot-sdk` release is `unstable2507`. - The supported `polkadot-sdk` release is `unstable2507`.
- The `INVALID` opcode and OOB memory accesses now consume all remaining gas. - The `INVALID` opcode and OOB memory accesses now consume all remaining gas.
- Emit the `call_evm` and `delegate_call_evm` syscalls for contract calls.
### Fixed: ### Fixed:
- The missing `STOP` instruction at the end of `code` blocks. - The missing `STOP` instruction at the end of `code` blocks.
- The missing bounds check in the internal sbrk implementation. - The missing bounds check in the internal sbrk implementation.
- The call gas is no longer ignored.
## v0.5.0 ## v0.5.0
Generated
+10 -7
View File
@@ -4552,21 +4552,24 @@ checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590"
[[package]] [[package]]
name = "inkwell" name = "inkwell"
version = "0.7.1" version = "0.6.0"
source = "git+https://github.com/TheDan64/inkwell.git?branch=master#7abf48a2cf4fc3e338fbeb1780ac7507cbb13e98" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e67349bd7578d4afebbe15eaa642a80b884e8623db74b1716611b131feb1deef"
dependencies = [ dependencies = [
"either",
"inkwell_internals", "inkwell_internals",
"libc", "libc",
"llvm-sys", "llvm-sys",
"once_cell", "once_cell",
"serde", "serde",
"thiserror 2.0.17", "thiserror 1.0.69",
] ]
[[package]] [[package]]
name = "inkwell_internals" name = "inkwell_internals"
version = "0.12.0" version = "0.11.0"
source = "git+https://github.com/TheDan64/inkwell.git?branch=master#7abf48a2cf4fc3e338fbeb1780ac7507cbb13e98" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f365c8de536236cfdebd0ba2130de22acefed18b1fb99c32783b3840aec5fb46"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -4924,9 +4927,9 @@ dependencies = [
[[package]] [[package]]
name = "llvm-sys" name = "llvm-sys"
version = "211.0.0" version = "181.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "108b3ad2b2eaf2a561fc74196273b20e3436e4a688b8b44e250d83974dc1b2e2" checksum = "d320f9d2723c97d4b78f9190a61ed25cc7cfbe456668c08e6e7dd8e50ceb8500"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cc", "cc",
+2 -3
View File
@@ -80,10 +80,9 @@ polkadot-sdk = { version = "=2507.4.0" }
# llvm # llvm
[workspace.dependencies.inkwell] [workspace.dependencies.inkwell]
git = "https://github.com/TheDan64/inkwell.git" version = "0.6.0"
branch = "master"
default-features = false default-features = false
features = ["serde", "llvm21-1", "no-libffi-linking", "target-riscv"] features = ["serde", "llvm18-1", "no-libffi-linking", "target-riscv"]
[profile.bench] [profile.bench]
inherits = "release" inherits = "release"
+1 -1
View File
@@ -21,7 +21,7 @@ RUN apt update && \
COPY . . COPY . .
COPY --from=llvm-builder /opt/revive/target-llvm /opt/revive/target-llvm COPY --from=llvm-builder /opt/revive/target-llvm /opt/revive/target-llvm
ENV LLVM_SYS_211_PREFIX=/opt/revive/target-llvm/musl/target-final ENV LLVM_SYS_181_PREFIX=/opt/revive/target-llvm/musl/target-final
RUN make install-bin RUN make install-bin
FROM alpine:latest FROM alpine:latest
+5 -5
View File
@@ -69,9 +69,9 @@ Download the [latest LLVM build](https://github.com/paritytech/revive/releases?q
> xattr -rc </path/to/the/extracted/archive>/target-llvm/gnu/target-final/bin/* > xattr -rc </path/to/the/extracted/archive>/target-llvm/gnu/target-final/bin/*
> ``` > ```
After extracting the archive, point `$LLVM_SYS_211_PREFIX` to it: After extracting the archive, point `$LLVM_SYS_181_PREFIX` to it:
```sh ```sh
export LLVM_SYS_211_PREFIX=</path/to/the/extracted/archive>/target-llvm/gnu/target-final export LLVM_SYS_181_PREFIX=</path/to/the/extracted/archive>/target-llvm/gnu/target-final
``` ```
</details> </details>
@@ -79,18 +79,18 @@ export LLVM_SYS_211_PREFIX=</path/to/the/extracted/archive>/target-llvm/gnu/targ
<details> <details>
<summary>Building from source</summary> <summary>Building from source</summary>
The `Makefile` provides a shortcut target to obtain a compatible LLVM build, using the provided [revive-llvm](crates/llvm-builder/README.md) utility. Once installed, point `$LLVM_SYS_211_PREFIX` to the installation afterwards: The `Makefile` provides a shortcut target to obtain a compatible LLVM build, using the provided [revive-llvm](crates/llvm-builder/README.md) utility. Once installed, point `$LLVM_SYS_181_PREFIX` to the installation afterwards:
```sh ```sh
make install-llvm make install-llvm
export LLVM_SYS_211_PREFIX=${PWD}/target-llvm/gnu/target-final export LLVM_SYS_181_PREFIX=${PWD}/target-llvm/gnu/target-final
``` ```
</details> </details>
### The `resolc` Solidity frontend ### The `resolc` Solidity frontend
To build the `resolc` Solidity frontend executable, make sure you have obtained a compatible LLVM build and did export the `LLVM_SYS_211_PREFIX` environment variable pointing to it (see [above](#LLVM)). To build the `resolc` Solidity frontend executable, make sure you have obtained a compatible LLVM build and did export the `LLVM_SYS_181_PREFIX` environment variable pointing to it (see [above](#LLVM)).
To install the `resolc` Solidity frontend executable: To install the `resolc` Solidity frontend executable:
+1 -1
View File
@@ -1,7 +1,7 @@
//! The compiler build utilities library. //! The compiler build utilities library.
/// The revive LLVM host dependency directory prefix environment variable. /// The revive LLVM host dependency directory prefix environment variable.
pub const REVIVE_LLVM_HOST_PREFIX: &str = "LLVM_SYS_211_PREFIX"; pub const REVIVE_LLVM_HOST_PREFIX: &str = "LLVM_SYS_181_PREFIX";
/// The revive LLVM target dependency directory prefix environment variable. /// The revive LLVM target dependency directory prefix environment variable.
pub const REVIVE_LLVM_TARGET_PREFIX: &str = "REVIVE_LLVM_TARGET_PREFIX"; pub const REVIVE_LLVM_TARGET_PREFIX: &str = "REVIVE_LLVM_TARGET_PREFIX";
+50
View File
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8;
// Use a non-zero call gas that works with call gas clipping but not with a truncate.
/* runner.json
{
"differential": true,
"actions": [
{
"Upload": {
"code": {
"Solidity": {
"contract": "Other"
}
}
}
},
{
"Instantiate": {
"code": {
"Solidity": {
"contract": "CallGas"
}
},
"data": "1000000000000000000000000000000000000000000000000000000000000001"
}
}
]
}
*/
contract Other {
address public last;
uint public foo;
fallback() external {
last = msg.sender;
foo += 1;
}
}
contract CallGas {
constructor(uint _gas) payable {
Other other = new Other();
address(other).call{ gas: _gas }(hex"");
assert(other.last() == address(this));
}
}
+4 -4
View File
@@ -20,7 +20,7 @@ pragma solidity ^0.8.28;
"dest": { "dest": {
"Instantiated": 0 "Instantiated": 0
}, },
"data": "e2179b8e" "data": "0be0e4a60000000000000000000000000000000000000000000000000000000000000000"
} }
} }
] ]
@@ -29,12 +29,12 @@ pragma solidity ^0.8.28;
contract MLoad { contract MLoad {
constructor() payable { constructor() payable {
assert(g() == 0); assert(loadAt(0) == 0);
} }
function g() public payable returns (uint m) { function loadAt(uint _offset) public payable returns (uint m) {
assembly { assembly {
m := mload(0) m := mload(_offset)
} }
} }
} }
-15
View File
@@ -23,11 +23,6 @@ pragma solidity ^0.8;
"data": "1c8d16b30000000000000000000000000303030303030303030303030303030303030303000000000000000000000000000000000000000000000000000000000000000a" "data": "1c8d16b30000000000000000000000000303030303030303030303030303030303030303000000000000000000000000000000000000000000000000000000000000000a"
} }
}, },
{
"VerifyCall": {
"success": true
}
},
{ {
"Call": { "Call": {
"dest": { "dest": {
@@ -36,11 +31,6 @@ pragma solidity ^0.8;
"data": "fb9e8d050000000000000000000000000000000000000000000000000000000000000001" "data": "fb9e8d050000000000000000000000000000000000000000000000000000000000000001"
} }
}, },
{
"VerifyCall": {
"success": false
}
},
{ {
"Call": { "Call": {
"dest": { "dest": {
@@ -48,11 +38,6 @@ pragma solidity ^0.8;
}, },
"data": "fb9e8d050000000000000000000000000000000000000000000000000000000000000000" "data": "fb9e8d050000000000000000000000000000000000000000000000000000000000000000"
} }
},
{
"VerifyCall": {
"success": false
}
} }
] ]
} }
-15
View File
@@ -23,11 +23,6 @@ pragma solidity ^0.8;
"data": "1c8d16b30000000000000000000000000303030303030303030303030303030303030303000000000000000000000000000000000000000000000000000000000000000a" "data": "1c8d16b30000000000000000000000000303030303030303030303030303030303030303000000000000000000000000000000000000000000000000000000000000000a"
} }
}, },
{
"VerifyCall": {
"success": true
}
},
{ {
"Call": { "Call": {
"dest": { "dest": {
@@ -36,11 +31,6 @@ pragma solidity ^0.8;
"data": "fb9e8d050000000000000000000000000000000000000000000000000000000000000001" "data": "fb9e8d050000000000000000000000000000000000000000000000000000000000000001"
} }
}, },
{
"VerifyCall": {
"success": false
}
},
{ {
"Call": { "Call": {
"dest": { "dest": {
@@ -48,11 +38,6 @@ pragma solidity ^0.8;
}, },
"data": "fb9e8d050000000000000000000000000000000000000000000000000000000000000000" "data": "fb9e8d050000000000000000000000000000000000000000000000000000000000000000"
} }
},
{
"VerifyCall": {
"success": false
}
} }
] ]
} }
+9
View File
@@ -234,6 +234,15 @@ sol!(
); );
case!("MCopy.sol", MCopy, memcpyCall, memcpy, payload: Bytes); case!("MCopy.sol", MCopy, memcpyCall, memcpy, payload: Bytes);
sol!(
contract MLoad {
constructor() payable;
function loadAt(uint _offset) public payable returns (uint m);
}
);
case!("MLoad.sol", MLoad, loadAtCall, load_at, _offset: U256);
sol!( sol!(
contract Call { contract Call {
function value_transfer(address payable destination) public payable; function value_transfer(address payable destination) public payable;
+39 -44
View File
@@ -66,6 +66,7 @@ test_spec!(add_mod_mul_mod, "AddModMulModTester", "AddModMulMod.sol");
test_spec!(memory_bounds, "MemoryBounds", "MemoryBounds.sol"); test_spec!(memory_bounds, "MemoryBounds", "MemoryBounds.sol");
test_spec!(selfdestruct, "Selfdestruct", "Selfdestruct.sol"); test_spec!(selfdestruct, "Selfdestruct", "Selfdestruct.sol");
test_spec!(clz, "CountLeadingZeros", "CountLeadingZeros.sol"); test_spec!(clz, "CountLeadingZeros", "CountLeadingZeros.sol");
test_spec!(call_gas, "CallGas", "CallGas.sol");
fn instantiate(path: &str, contract: &str) -> Vec<SpecsAction> { fn instantiate(path: &str, contract: &str) -> Vec<SpecsAction> {
vec![Instantiate { vec![Instantiate {
@@ -451,50 +452,6 @@ fn ext_code_size() {
.run(); .run();
} }
#[test]
#[should_panic(expected = "ReentranceDenied")]
fn send_denies_reentrancy() {
let value = 1000;
Specs {
actions: vec![
instantiate("contracts/Send.sol", "Send").remove(0),
Call {
origin: TestAddress::Alice,
dest: TestAddress::Instantiated(0),
value,
gas_limit: None,
storage_deposit_limit: None,
data: Contract::send_self(U256::from(value)).calldata,
},
],
differential: false,
..Default::default()
}
.run();
}
#[test]
#[should_panic(expected = "ReentranceDenied")]
fn transfer_denies_reentrancy() {
let value = 1000;
Specs {
actions: vec![
instantiate("contracts/Transfer.sol", "Transfer").remove(0),
Call {
origin: TestAddress::Alice,
dest: TestAddress::Instantiated(0),
value,
gas_limit: None,
storage_deposit_limit: None,
data: Contract::transfer_self(U256::from(value)).calldata,
},
],
differential: false,
..Default::default()
}
.run();
}
#[test] #[test]
fn create2_salt() { fn create2_salt() {
let salt = U256::from(777); let salt = U256::from(777);
@@ -714,3 +671,41 @@ fn invalid_opcode_works() {
assert_eq!(result.weight_consumed, GAS_LIMIT); assert_eq!(result.weight_consumed, GAS_LIMIT);
} }
/// Load from heap memory using an out of bounds offset and expect the
/// contract to hit the `invalid` syscall to use all gas (like on EVM).
///
/// The offset is picked such that a regular truncate would be in bounds.
#[test]
fn safe_truncate_int_to_xlen_works() {
let offset = 0x10000000_00000000u64;
let data = Contract::load_at(Uint::from(offset)).calldata;
let mut actions = instantiate("contracts/MLoad.sol", "MLoad");
actions.append(&mut vec![
Call {
origin: TestAddress::Alice,
dest: TestAddress::Instantiated(0),
value: 0,
gas_limit: None,
storage_deposit_limit: None,
data,
},
VerifyCall(VerifyCallExpectation {
success: false,
..Default::default()
}),
]);
let results = Specs {
actions,
differential: true,
..Default::default()
}
.run();
let CallResult::Exec { result, .. } = results.last().unwrap() else {
unreachable!()
};
assert_eq!(result.weight_consumed, GAS_LIMIT);
}
-28
View File
@@ -14,7 +14,6 @@ fn set_rustc_link_flags() {
"lldELF", "lldELF",
"lldCommon", "lldCommon",
"lldMachO", "lldMachO",
"lldWasm",
"LLVMSupport", "LLVMSupport",
"LLVMLinker", "LLVMLinker",
"LLVMCore", "LLVMCore",
@@ -69,33 +68,6 @@ fn set_rustc_link_flags() {
"LLVMBitReader", "LLVMBitReader",
"LLVMRemarks", "LLVMRemarks",
"LLVMBitstreamReader", "LLVMBitstreamReader",
"LLVMTextAPI",
"LLVMDebugInfoDWARFLowLevel",
"LLVMDebugInfoGSYM",
"LLVMDebugInfoMSF",
"LLVMDebugInfoPDB",
"LLVMDebugInfoBTF",
"LLVMInterfaceStub",
"LLVMCGData",
"LLVMMIRParser",
"LLVMDWARFLinker",
"LLVMDWARFLinkerParallel",
"LLVMDWARFLinkerClassic",
"LLVMLibDriver",
"LLVMDlltoolDriver",
"LLVMTextAPIBinaryReader",
"LLVMCoverage",
"LLVMLineEditor",
"LLVMRISCVTargetMCA",
"LLVMRuntimeDyld",
"LLVMDWP",
"LLVMDWARFCFIChecker",
"LLVMDebugInfoLogicalView",
"LLVMMCA",
"LLVMipo",
"LLVMVectorize",
"LLVMSandboxIR",
"LLVMExtensions",
] { ] {
println!("cargo:rustc-link-lib=static={lib}"); println!("cargo:rustc-link-lib=static={lib}");
} }
+2 -2
View File
@@ -82,10 +82,10 @@ Obtain a compatible build for your host platform from the release section of thi
Build artifacts end up in the `./target-llvm/gnu/target-final/` directory by default. Build artifacts end up in the `./target-llvm/gnu/target-final/` directory by default.
The `gnu` directory depends on the supported archticture and will either be `gnu`, `musl` or `emscripten`. The `gnu` directory depends on the supported archticture and will either be `gnu`, `musl` or `emscripten`.
You now need to export the final target directory `$LLVM_SYS_211_PREFIX`: You now need to export the final target directory `$LLVM_SYS_181_PREFIX`:
```shell ```shell
export LLVM_SYS_211_PREFIX=${PWD}/target-llvm/gnu/target-final export LLVM_SYS_181_PREFIX=${PWD}/target-llvm/gnu/target-final
``` ```
If built with the `--enable-tests` option, test tools will be in the `./target-llvm/gnu/build-final/` directory, along with copies of the build artifacts. For all supported build options, run `revive-llvm build --help`. If built with the `--enable-tests` option, test tools will be in the `./target-llvm/gnu/build-final/` directory, along with copies of the build artifacts. For all supported build options, run `revive-llvm build --help`.
@@ -221,6 +221,7 @@ fn build_host(
"-DCOMPILER_RT_BUILD_MEMPROF='Off'", "-DCOMPILER_RT_BUILD_MEMPROF='Off'",
"-DCOMPILER_RT_BUILD_ORC='Off'", "-DCOMPILER_RT_BUILD_ORC='Off'",
"-DCOMPILER_RT_DEFAULT_TARGET_ARCH='aarch64'", "-DCOMPILER_RT_DEFAULT_TARGET_ARCH='aarch64'",
"-DCOMPILER_RT_DEFAULT_TARGET_ONLY='On'",
]) ])
.args(crate::platforms::shared::SHARED_BUILD_OPTS) .args(crate::platforms::shared::SHARED_BUILD_OPTS)
.args(crate::platforms::shared::shared_build_opts_ccache( .args(crate::platforms::shared::shared_build_opts_ccache(
@@ -219,6 +219,7 @@ fn build_host(
"-DCOMPILER_RT_BUILD_MEMPROF='Off'", "-DCOMPILER_RT_BUILD_MEMPROF='Off'",
"-DCOMPILER_RT_BUILD_ORC='Off'", "-DCOMPILER_RT_BUILD_ORC='Off'",
"-DCOMPILER_RT_DEFAULT_TARGET_ARCH='x86_64'", "-DCOMPILER_RT_DEFAULT_TARGET_ARCH='x86_64'",
"-DCOMPILER_RT_DEFAULT_TARGET_ONLY='On'",
"-DLIBCLANG_BUILD_STATIC='On'", "-DLIBCLANG_BUILD_STATIC='On'",
"-DBUILD_SHARED_LIBS='Off'", "-DBUILD_SHARED_LIBS='Off'",
]) ])
+1 -1
View File
@@ -38,7 +38,7 @@ pub const MUSL_SNAPSHOTS_URL: &str = "https://git.musl-libc.org/cgit/musl/snapsh
pub const EMSDK_SOURCE_URL: &str = "https://github.com/emscripten-core/emsdk.git"; pub const EMSDK_SOURCE_URL: &str = "https://github.com/emscripten-core/emsdk.git";
/// The emscripten SDK version. /// The emscripten SDK version.
pub const EMSDK_VERSION: &str = "4.0.20"; pub const EMSDK_VERSION: &str = "4.0.9";
/// The subprocess runner. /// The subprocess runner.
/// ///
@@ -8,7 +8,7 @@ use serde::Serialize;
/// inside of the LLVM build directory. This order is actually generated during the building. /// inside of the LLVM build directory. This order is actually generated during the building.
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Attribute { pub enum Attribute {
// FirstEnumAttr = 1, Unused = 0,
AllocAlign = 1, AllocAlign = 1,
AllocatedPointer = 2, AllocatedPointer = 2,
AlwaysInline = 3, AlwaysInline = 3,
@@ -16,107 +16,92 @@ pub enum Attribute {
Cold = 5, Cold = 5,
Convergent = 6, Convergent = 6,
CoroDestroyOnlyWhenComplete = 7, CoroDestroyOnlyWhenComplete = 7,
CoroElideSafe = 8, DeadOnUnwind = 8,
DeadOnReturn = 9, DisableSanitizerInstrumentation = 9,
DeadOnUnwind = 10, FnRetThunkExtern = 10,
DisableSanitizerInstrumentation = 11, Hot = 11,
FnRetThunkExtern = 12, ImmArg = 12,
Hot = 13, InReg = 13,
HybridPatchable = 14, InlineHint = 14,
ImmArg = 15, JumpTable = 15,
InReg = 16, MinSize = 16,
InlineHint = 17, MustProgress = 17,
JumpTable = 18, Naked = 18,
MinSize = 19, Nest = 19,
MustProgress = 20, NoAlias = 20,
Naked = 21, NoBuiltin = 21,
Nest = 22, NoCallback = 22,
NoAlias = 23, NoCapture = 23,
NoBuiltin = 24, NoCfCheck = 24,
NoCallback = 25, NoDuplicate = 25,
NoCfCheck = 26, NoFree = 26,
NoDivergenceSource = 27, NoImplicitFloat = 27,
NoDuplicate = 28, NoInline = 28,
NoExt = 29, NoMerge = 29,
NoFree = 30, NoProfile = 30,
NoImplicitFloat = 31, NoRecurse = 31,
NoInline = 32, NoRedZone = 32,
NoMerge = 33, NoReturn = 33,
NoProfile = 34, NoSanitizeBounds = 34,
NoRecurse = 35, NoSanitizeCoverage = 35,
NoRedZone = 36, NoSync = 36,
NoReturn = 37, NoUndef = 37,
NoSanitizeBounds = 38, NoUnwind = 38,
NoSanitizeCoverage = 39, NonLazyBind = 39,
NoSync = 40, NonNull = 40,
NoUndef = 41, NullPointerIsValid = 41,
NoUnwind = 42, OptForFuzzing = 42,
NonLazyBind = 43, OptimizeForDebugging = 43,
NonNull = 44, OptimizeForSize = 44,
NullPointerIsValid = 45, OptimizeNone = 45,
OptForFuzzing = 46, PresplitCoroutine = 46,
OptimizeForDebugging = 47, ReadNone = 47,
OptimizeForSize = 48, ReadOnly = 48,
OptimizeNone = 49, Returned = 49,
PresplitCoroutine = 50, ReturnsTwice = 50,
ReadNone = 51, SExt = 51,
ReadOnly = 52, SafeStack = 52,
Returned = 53, SanitizeAddress = 53,
ReturnsTwice = 54, SanitizeHWAddress = 54,
SExt = 55, SanitizeMemTag = 55,
SafeStack = 56, SanitizeMemory = 56,
SanitizeAddress = 57, SanitizeThread = 57,
SanitizeHWAddress = 58, ShadowCallStack = 58,
SanitizeMemTag = 59, SkipProfile = 59,
SanitizeMemory = 60, Speculatable = 60,
SanitizeNumericalStability = 61, SpeculativeLoadHardening = 61,
SanitizeRealtime = 62, StackProtect = 62,
SanitizeRealtimeBlocking = 63, StackProtectReq = 63,
SanitizeThread = 64, StackProtectStrong = 64,
SanitizeType = 65, StrictFP = 65,
ShadowCallStack = 66, SwiftAsync = 66,
SkipProfile = 67, SwiftError = 67,
Speculatable = 68, SwiftSelf = 68,
SpeculativeLoadHardening = 69, WillReturn = 69,
StackProtect = 70, Writable = 70,
StackProtectReq = 71, WriteOnly = 71,
StackProtectStrong = 72, ZExt = 72,
StrictFP = 73, // LastEnumAttr = 72,
SwiftAsync = 74, // FirstTypeAttr = 73,
SwiftError = 75, ByRef = 73,
SwiftSelf = 76, ByVal = 74,
WillReturn = 77, ElementType = 75,
Writable = 78, InAlloca = 76,
WriteOnly = 79, Preallocated = 77,
ZExt = 80, StructRet = 78,
//LastEnumAttr = 80, // LastTypeAttr = 78,
//FirstTypeAttr = 81, // FirstIntAttr = 79,
ByRef = 81, Alignment = 79,
ByVal = 82, AllocKind = 80,
ElementType = 83, AllocSize = 81,
InAlloca = 84, Dereferenceable = 82,
Preallocated = 85, DereferenceableOrNull = 83,
StructRet = 86, Memory = 84,
//LastTypeAttr = 86, NoFPClass = 85,
//FirstIntAttr = 87, StackAlignment = 86,
Alignment = 87, UWTable = 87,
AllocKind = 88, VScaleRange = 88,
AllocSize = 89, // LastIntAttr = 88,
Captures = 90,
Dereferenceable = 91,
DereferenceableOrNull = 92,
Memory = 93,
NoFPClass = 94,
StackAlignment = 95,
UWTable = 96,
VScaleRange = 97,
//LastIntAttr = 97,
//FirstConstantRangeAttr = 98,
Range = 98,
//LastConstantRangeAttr = 98,
//FirstConstantRangeListAttr = 99,
Initializes = 99,
//LastConstantRangeListAttr = 99,
} }
impl TryFrom<&str> for Attribute { impl TryFrom<&str> for Attribute {
+12 -5
View File
@@ -838,7 +838,8 @@ impl<'ctx> Context<'ctx> {
.builder() .builder()
.build_call(intrinsic, &[value.into()], "call_byte_swap")? .build_call(intrinsic, &[value.into()], "call_byte_swap")?
.try_as_basic_value() .try_as_basic_value()
.unwrap_basic()) .left()
.unwrap())
} }
/// Builds a GEP instruction. /// Builds a GEP instruction.
@@ -911,7 +912,7 @@ impl<'ctx> Context<'ctx> {
) )
.unwrap() .unwrap()
.try_as_basic_value() .try_as_basic_value()
.basic() .left()
} }
/// Builds a call to the runtime API `import`, where `import` is a "getter" API. /// Builds a call to the runtime API `import`, where `import` is a "getter" API.
@@ -949,7 +950,7 @@ impl<'ctx> Context<'ctx> {
) )
.unwrap(); .unwrap();
self.modify_call_site_value(arguments, call_site_value, function); self.modify_call_site_value(arguments, call_site_value, function);
call_site_value.try_as_basic_value().basic() call_site_value.try_as_basic_value().left()
} }
/// Sets the alignment to `1`, since all non-stack memory pages have such alignment. /// Sets the alignment to `1`, since all non-stack memory pages have such alignment.
@@ -1081,7 +1082,13 @@ impl<'ctx> Context<'ctx> {
Ok(call_site_value Ok(call_site_value
.try_as_basic_value() .try_as_basic_value()
.unwrap_basic() .left()
.unwrap_or_else(|| {
panic!(
"revive runtime function {} should return a value",
<PolkaVMSbrkFunction as RuntimeFunction>::NAME,
)
})
.into_pointer_value()) .into_pointer_value())
} }
@@ -1270,7 +1277,7 @@ impl<'ctx> Context<'ctx> {
call_site_value.add_attribute( call_site_value.add_attribute(
inkwell::attributes::AttributeLoc::Param(index as u32), inkwell::attributes::AttributeLoc::Param(index as u32),
self.llvm self.llvm
.create_enum_attribute(Attribute::Captures as u32, 0), // captures(none) .create_enum_attribute(Attribute::NoCapture as u32, 0),
); );
call_site_value.add_attribute( call_site_value.add_attribute(
inkwell::attributes::AttributeLoc::Param(index as u32), inkwell::attributes::AttributeLoc::Param(index as u32),
@@ -275,6 +275,6 @@ pub fn count_leading_zeros<'ctx>(
"clz", "clz",
)? )?
.try_as_basic_value() .try_as_basic_value()
.basic() .left()
.expect("the llvm.ctlz should return a value")) .expect("the llvm.ctlz should return a value"))
} }
+27 -122
View File
@@ -4,9 +4,8 @@ use inkwell::values::BasicValue;
use crate::polkavm::context::Context; use crate::polkavm::context::Context;
const STATIC_CALL_FLAG: u32 = 0b0001_0000; const STATIC_CALL_FLAG: u64 = 0b0001_0000;
const REENTRANT_CALL_FLAG: u32 = 0b0000_1000; const REENTRANT_CALL_FLAG: u64 = 0b0000_1000;
const SOLIDITY_TRANSFER_GAS_STIPEND_THRESHOLD: u64 = 2300;
/// Translates a contract call. /// Translates a contract call.
pub fn call<'ctx>( pub fn call<'ctx>(
@@ -38,33 +37,12 @@ pub fn call<'ctx>(
let output_length_pointer = context.build_alloca_at_entry(context.xlen_type(), "output_length"); let output_length_pointer = context.build_alloca_at_entry(context.xlen_type(), "output_length");
context.build_store(output_length_pointer, output_length)?; context.build_store(output_length_pointer, output_length)?;
let (flags, deposit_limit_value) = if static_call { let flags = if static_call {
let flags = REENTRANT_CALL_FLAG | STATIC_CALL_FLAG; REENTRANT_CALL_FLAG | STATIC_CALL_FLAG
(
context.xlen_type().const_int(flags as u64, false),
context.word_type().const_zero(),
)
} else { } else {
call_reentrancy_heuristic(context, gas, input_length, output_length)? REENTRANT_CALL_FLAG
}; };
let deposit_pointer = context.build_alloca_at_entry(context.word_type(), "deposit_pointer");
context.build_store(deposit_pointer, deposit_limit_value)?;
let flags_and_callee = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(),
context.llvm(),
flags,
address_pointer.to_int(context),
"address_and_callee",
)?;
let deposit_and_value = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(),
context.llvm(),
deposit_pointer.to_int(context),
value_pointer.to_int(context),
"deposit_and_value",
)?;
let input_data = revive_runtime_api::calling_convention::pack_hi_lo_reg( let input_data = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(), context.builder(),
context.llvm(), context.llvm(),
@@ -85,10 +63,10 @@ pub fn call<'ctx>(
.build_runtime_call( .build_runtime_call(
name, name,
&[ &[
flags_and_callee.into(), context.xlen_type().const_int(flags, false).into(),
context.register_type().const_all_ones().into(), address_pointer.to_int(context).into(),
context.register_type().const_all_ones().into(), value_pointer.to_int(context).into(),
deposit_and_value.into(), clip_call_gas(context, gas)?,
input_data.into(), input_data.into(),
output_data.into(), output_data.into(),
], ],
@@ -111,7 +89,7 @@ pub fn call<'ctx>(
pub fn delegate_call<'ctx>( pub fn delegate_call<'ctx>(
context: &mut Context<'ctx>, context: &mut Context<'ctx>,
_gas: inkwell::values::IntValue<'ctx>, gas: inkwell::values::IntValue<'ctx>,
address: inkwell::values::IntValue<'ctx>, address: inkwell::values::IntValue<'ctx>,
input_offset: inkwell::values::IntValue<'ctx>, input_offset: inkwell::values::IntValue<'ctx>,
input_length: inkwell::values::IntValue<'ctx>, input_length: inkwell::values::IntValue<'ctx>,
@@ -132,18 +110,6 @@ pub fn delegate_call<'ctx>(
let output_length_pointer = context.build_alloca_at_entry(context.xlen_type(), "output_length"); let output_length_pointer = context.build_alloca_at_entry(context.xlen_type(), "output_length");
context.build_store(output_length_pointer, output_length)?; context.build_store(output_length_pointer, output_length)?;
let deposit_pointer = context.build_alloca_at_entry(context.word_type(), "deposit_pointer");
context.build_store(deposit_pointer, context.word_type().const_all_ones())?;
let flags = context.xlen_type().const_int(0u64, false);
let flags_and_callee = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(),
context.llvm(),
flags,
address_pointer.to_int(context),
"address_and_callee",
)?;
let input_data = revive_runtime_api::calling_convention::pack_hi_lo_reg( let input_data = revive_runtime_api::calling_convention::pack_hi_lo_reg(
context.builder(), context.builder(),
context.llvm(), context.llvm(),
@@ -164,10 +130,9 @@ pub fn delegate_call<'ctx>(
.build_runtime_call( .build_runtime_call(
name, name,
&[ &[
flags_and_callee.into(), context.xlen_type().const_int(0u64, false).into(),
context.register_type().const_all_ones().into(), address_pointer.to_int(context).into(),
context.register_type().const_all_ones().into(), clip_call_gas(context, gas)?,
deposit_pointer.to_int(context).into(),
input_data.into(), input_data.into(),
output_data.into(), output_data.into(),
], ],
@@ -201,82 +166,22 @@ pub fn linker_symbol<'ctx>(
context.build_load_address(context.get_global(path)?.into()) context.build_load_address(context.get_global(path)?.into())
} }
/// The Solidity `address.transfer` and `address.send` call detection heuristic. /// The runtime implements gas as `u64` so we clip the stipend to `u64::MAX`.
/// fn clip_call_gas<'ctx>(
/// # Why context: &Context<'ctx>,
/// This heuristic is an additional security feature to guard against re-entrancy attacks
/// in case contract authors violate Solidity best practices and use `address.transfer` or
/// `address.send`.
/// While contract authors are supposed to never use `address.transfer` or `address.send`,
/// for a small cost we can be extra defensive about it.
///
/// # How
/// The gas stipend emitted by solc for `transfer` and `send` is not static, thus:
/// - Dynamically allow re-entrancy only for calls considered not transfer or send.
/// - Detected balance transfers will supply 0 deposit limit instead of `u256::MAX`.
///
/// Calls are considered transfer or send if:
/// - (Input length | Output lenght) == 0;
/// - Gas <= 2300;
///
/// # Returns
/// The call flags xlen `IntValue` and the deposit limit word `IntValue`.
fn call_reentrancy_heuristic<'ctx>(
context: &mut Context<'ctx>,
gas: inkwell::values::IntValue<'ctx>, gas: inkwell::values::IntValue<'ctx>,
input_length: inkwell::values::IntValue<'ctx>, ) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> {
output_length: inkwell::values::IntValue<'ctx>, let builder = context.builder();
) -> anyhow::Result<(
inkwell::values::IntValue<'ctx>, let clipped = context.register_type().const_all_ones();
inkwell::values::IntValue<'ctx>, let is_overflow = builder.build_int_compare(
)> { inkwell::IntPredicate::UGT,
// Branch-free SSA implementation: First derive the heuristic boolean (int1) value.
let input_length_or_output_length =
context
.builder()
.build_or(input_length, output_length, "input_length_or_output_length")?;
let is_no_input_no_output = context.builder().build_int_compare(
inkwell::IntPredicate::EQ,
context.xlen_type().const_zero(),
input_length_or_output_length,
"is_no_input_no_output",
)?;
let gas_stipend = context
.word_type()
.const_int(SOLIDITY_TRANSFER_GAS_STIPEND_THRESHOLD, false);
let is_gas_stipend_for_transfer_or_send = context.builder().build_int_compare(
inkwell::IntPredicate::ULE,
gas, gas,
gas_stipend, builder.build_int_z_extend(clipped, context.word_type(), "gas_clipped")?,
"is_gas_stipend_for_transfer_or_send", "is_gas_overflow",
)?; )?;
let is_balance_transfer = context.builder().build_and( let truncated = builder.build_int_truncate(gas, context.register_type(), "gas_truncated")?;
is_no_input_no_output, let call_gas = builder.build_select(is_overflow, clipped, truncated, "call_gas")?;
is_gas_stipend_for_transfer_or_send,
"is_balance_transfer",
)?;
let is_regular_call = context
.builder()
.build_not(is_balance_transfer, "is_balance_transfer_inverted")?;
// Call flag: Left shift the heuristic boolean value. Ok(call_gas)
let is_regular_call_xlen = context.builder().build_int_z_extend(
is_regular_call,
context.xlen_type(),
"is_balance_transfer_xlen",
)?;
let call_flags = context.builder().build_left_shift(
is_regular_call_xlen,
context.xlen_type().const_int(3, false),
"flags",
)?;
// Deposit limit value: Sign-extended the heuristic boolean value.
let deposit_limit_value = context.builder().build_int_s_extend(
is_regular_call,
context.word_type(),
"deposit_limit_value",
)?;
Ok((call_flags, deposit_limit_value))
} }
+1 -1
View File
@@ -42,7 +42,7 @@ mimalloc = { version = "0.1.46", default-features = false }
[target.'cfg(target_os = "emscripten")'.dependencies] [target.'cfg(target_os = "emscripten")'.dependencies]
libc = { workspace = true } libc = { workspace = true }
inkwell = { workspace = true, features = ["target-riscv", "llvm21-1-no-llvm-linking"]} inkwell = { workspace = true, features = ["target-riscv", "llvm18-1-no-llvm-linking"]}
[build-dependencies] [build-dependencies]
git2 = { workspace = true, default-features = false } git2 = { workspace = true, default-features = false }
+1 -1
View File
@@ -9,7 +9,7 @@ description = "Implements the low level runtime API bindings with pallet contrac
[dependencies] [dependencies]
anyhow = { workspace = true } anyhow = { workspace = true }
inkwell = { workspace = true, features = ["target-riscv", "no-libffi-linking", "llvm21-1"] } inkwell = { workspace = true, features = ["target-riscv", "no-libffi-linking", "llvm18-1"] }
revive-common = { workspace = true } revive-common = { workspace = true }
+2 -2
View File
@@ -53,7 +53,7 @@ POLKAVM_IMPORT(void, block_hash, uint32_t, uint32_t)
POLKAVM_IMPORT(void, block_number, uint32_t) POLKAVM_IMPORT(void, block_number, uint32_t)
POLKAVM_IMPORT(uint32_t, call, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) POLKAVM_IMPORT(uint32_t, call_evm, uint32_t, uint32_t, uint32_t, uint64_t, uint64_t, uint64_t)
POLKAVM_IMPORT(void, call_data_copy, uint32_t, uint32_t, uint32_t) POLKAVM_IMPORT(void, call_data_copy, uint32_t, uint32_t, uint32_t)
@@ -71,7 +71,7 @@ POLKAVM_IMPORT(void, code_hash, uint32_t, uint32_t)
POLKAVM_IMPORT(void, consume_all_gas) POLKAVM_IMPORT(void, consume_all_gas)
POLKAVM_IMPORT(uint32_t, delegate_call, uint64_t, uint64_t, uint64_t, uint32_t, uint64_t, uint64_t) POLKAVM_IMPORT(uint32_t, delegate_call_evm, uint32_t, uint32_t, uint64_t, uint64_t, uint64_t)
POLKAVM_IMPORT(void, deposit_event, uint32_t, uint32_t, uint32_t, uint32_t) POLKAVM_IMPORT(void, deposit_event, uint32_t, uint32_t, uint32_t, uint32_t)
+2 -2
View File
@@ -16,7 +16,7 @@ pub static BLOCK_HASH: &str = "block_hash";
pub static BLOCK_NUMBER: &str = "block_number"; pub static BLOCK_NUMBER: &str = "block_number";
pub static CALL: &str = "call"; pub static CALL: &str = "call_evm";
pub static CALL_DATA_COPY: &str = "call_data_copy"; pub static CALL_DATA_COPY: &str = "call_data_copy";
@@ -32,7 +32,7 @@ pub static CODE_SIZE: &str = "code_size";
pub static CODE_HASH: &str = "code_hash"; pub static CODE_HASH: &str = "code_hash";
pub static DELEGATE_CALL: &str = "delegate_call"; pub static DELEGATE_CALL: &str = "delegate_call_evm";
pub static DEPOSIT_EVENT: &str = "deposit_event"; pub static DEPOSIT_EVENT: &str = "deposit_event";
@@ -113,10 +113,9 @@ impl Error {
let message = r#" let message = r#"
Warning: It looks like you are using '<address payable>.send/transfer(<X>)'. Warning: It looks like you are using '<address payable>.send/transfer(<X>)'.
Using '<address payable>.send/transfer(<X>)' is deprecated and strongly discouraged! Using '<address payable>.send/transfer(<X>)' is deprecated and strongly discouraged!
The resolc compiler uses a heuristic to detect '<address payable>.send/transfer(<X>)' calls, The revive runtime uses a heuristic to detect '<address payable>.send/transfer(<X>)' calls and
which disables call re-entrancy and supplies all remaining gas instead of the 2300 gas stipend. the gas stipend used by the runtime is different from the EVM.
However, detection is not guaranteed. You are advised to carefully test this, employ You are advised to carefully test this, employ re-entrancy guards or use the withdrawal pattern instead!
re-entrancy guards or use the withdrawal pattern instead!
Learn more on https://docs.soliditylang.org/en/latest/security-considerations.html#reentrancy Learn more on https://docs.soliditylang.org/en/latest/security-considerations.html#reentrancy
and https://docs.soliditylang.org/en/latest/common-patterns.html#withdrawal-from-contracts and https://docs.soliditylang.org/en/latest/common-patterns.html#withdrawal-from-contracts
"# "#
+1 -1
View File
@@ -7,7 +7,7 @@ repository.workspace = true
description = "revive compiler stdlib components" description = "revive compiler stdlib components"
[dependencies] [dependencies]
inkwell = { workspace = true, features = ["target-riscv", "no-libffi-linking", "llvm21-1"] } inkwell = { workspace = true, features = ["target-riscv", "no-libffi-linking", "llvm18-1"] }
[build-dependencies] [build-dependencies]
revive-build-utils = { workspace = true } revive-build-utils = { workspace = true }
+1 -1
Submodule llvm updated: f68f64eb81...3b5b5c1ec4