mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-14 16:51:04 +00:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ddddc989d | |||
| 5992ad0043 | |||
| 2fd96f6188 | |||
| 7d8fa75a0f | |||
| 80f94b5c76 | |||
| 06d324259c | |||
| 7669320e31 | |||
| ea0ff27c6f | |||
| 60e41a9210 | |||
| 0089d58d85 | |||
| 09c8f64eef | |||
| 4e6c562fac | |||
| 12a8685f11 | |||
| ce1766dc64 | |||
| 2c1097ef36 | |||
| a5ad9a917a | |||
| c929dc9b03 | |||
| dab29bc89b | |||
| 313c033261 | |||
| 87c1d7a8be | |||
| 8a98346a9c | |||
| 1b4d2c6bb8 | |||
| 004b8ac16c | |||
| 497dae2494 | |||
| 36ea69b50f | |||
| 2bbc5d713d | |||
| 4a9b651235 |
@@ -1,4 +1,5 @@
|
||||
name: "Install Solidity Compiler"
|
||||
description: "Installs the Ethereum solc Solidity compiler frontend executable"
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
@@ -18,7 +19,7 @@ runs:
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p solc
|
||||
curl -sSL --output solc/solc https://github.com/ethereum/solidity/releases/download/v0.8.28/${SOLC_NAME}
|
||||
curl -sSL --output solc/solc https://github.com/ethereum/solidity/releases/download/v0.8.29/${SOLC_NAME}
|
||||
|
||||
- name: Make Solc Executable
|
||||
if: ${{ runner.os == 'Windows' }}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import requests
|
||||
from datetime import datetime
|
||||
|
||||
def validate_github_token():
|
||||
"""Validate that GITHUB_TOKEN environment variable is set."""
|
||||
if 'GITHUB_TOKEN' not in os.environ:
|
||||
print("Error: GITHUB_TOKEN environment variable is not set.")
|
||||
sys.exit(1)
|
||||
|
||||
def fetch_release_data(repo, tag):
|
||||
"""Fetch release data from GitHub API."""
|
||||
url = f"https://api.github.com/repos/{repo}/releases/tags/{tag}"
|
||||
headers = {
|
||||
'Authorization': f"Bearer {os.environ['GITHUB_TOKEN']}",
|
||||
'Accept': 'application/vnd.github+json',
|
||||
'X-GitHub-Api-Version': '2022-11-28'
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.get(url, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except requests.RequestException as e:
|
||||
print(f"Error fetching release data: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
def extract_build_hash(target_commitish):
|
||||
"""Extract the first 8 characters of the commit hash."""
|
||||
return f"commit.{target_commitish[:8]}"
|
||||
|
||||
def generate_asset_json(release_data, asset):
|
||||
"""Generate JSON for a specific asset."""
|
||||
version = release_data['tag_name'].lstrip('v')
|
||||
build = extract_build_hash(release_data['target_commitish'])
|
||||
long_version = f"{version}+{build}"
|
||||
path = f"{asset['name']}+{long_version}"
|
||||
|
||||
return {
|
||||
"path": path,
|
||||
"name": asset['name'],
|
||||
"version": version,
|
||||
"build": build,
|
||||
"longVersion": long_version,
|
||||
"url": asset['browser_download_url'],
|
||||
"firstSolcVersion": os.environ["FIRST_SOLC_VERSION"],
|
||||
"lastSolcVersion": os.environ["LAST_SOLC_VERSION"]
|
||||
}
|
||||
|
||||
def save_platform_json(platform_folder, asset_json, tag):
|
||||
"""Save asset JSON and update list.json for a specific platform."""
|
||||
# Create platform folder if it doesn't exist
|
||||
os.makedirs(platform_folder, exist_ok=True)
|
||||
|
||||
# Update or create list.json
|
||||
list_file_path = os.path.join(platform_folder, "list.json")
|
||||
|
||||
if os.path.exists(list_file_path):
|
||||
with open(list_file_path, 'r') as f:
|
||||
try:
|
||||
list_data = json.load(f)
|
||||
except json.JSONDecodeError:
|
||||
list_data = {"builds": [], "releases": {}, "latestRelease": ""}
|
||||
else:
|
||||
list_data = {"builds": [], "releases": {}, "latestRelease": ""}
|
||||
|
||||
# Remove any existing entry with the same path
|
||||
list_data['builds'] = [
|
||||
build for build in list_data['builds']
|
||||
if build['path'] != asset_json['path']
|
||||
]
|
||||
# Add the new build
|
||||
list_data['builds'].append(asset_json)
|
||||
|
||||
# Update releases
|
||||
version = asset_json['version']
|
||||
list_data['releases'][version] = asset_json['path']
|
||||
|
||||
# Update latest release
|
||||
list_data['latestRelease'] = version
|
||||
|
||||
with open(list_file_path, 'w') as f:
|
||||
json.dump(list_data, f, indent=4)
|
||||
|
||||
def main():
|
||||
# Validate arguments
|
||||
if len(sys.argv) != 3:
|
||||
print("Usage: python script.py <repo> <tag>")
|
||||
sys.exit(1)
|
||||
|
||||
repo, tag = sys.argv[1], sys.argv[2]
|
||||
|
||||
# Validate GitHub token
|
||||
validate_github_token()
|
||||
|
||||
# Fetch release data
|
||||
release_data = fetch_release_data(repo, tag)
|
||||
|
||||
# Mapping of asset names to platform folders
|
||||
platform_mapping = {
|
||||
'resolc-x86_64-unknown-linux-musl': 'linux',
|
||||
'resolc-universal-apple-darwin': 'macos',
|
||||
'resolc-x86_64-pc-windows-msvc.exe': 'windows',
|
||||
'resolc_web.js': 'wasm'
|
||||
}
|
||||
|
||||
# Process each asset
|
||||
for asset in release_data['assets']:
|
||||
platform_name = platform_mapping.get(asset['name'])
|
||||
if platform_name:
|
||||
platform_folder = os.path.join(platform_name)
|
||||
asset_json = generate_asset_json(release_data, asset)
|
||||
save_platform_json(platform_folder, asset_json, tag)
|
||||
print(f"Processed {asset['name']} for {platform_name}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,64 @@
|
||||
name: Generate JSON for resolc-bin
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
generateJson:
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(github.event.release.tag_name, 'llvm') == false
|
||||
environment: tags
|
||||
env:
|
||||
# the token is needed for json_generator.py
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: tmp
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: paritytech/resolc-bin
|
||||
path: resolc-bin
|
||||
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.REVIVE_JSON_APP_ID }}
|
||||
private-key: ${{ secrets.REVIVE_JSON_APP_KEY }}
|
||||
owner: paritytech
|
||||
repositories: resolc-bin
|
||||
|
||||
- name: Generate json and push
|
||||
env:
|
||||
TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
APP_NAME: "paritytech-revive-json"
|
||||
Green: "\e[32m"
|
||||
NC: "\e[0m"
|
||||
run: |
|
||||
sudo apt-get update && sudo apt-get install -y wget
|
||||
wget https://github.com/${GITHUB_REPOSITORY}/releases/download/${GITHUB_REF_NAME}/resolc-x86_64-unknown-linux-musl
|
||||
chmod +x resolc-x86_64-unknown-linux-musl
|
||||
export FIRST_SOLC_VERSION=$(./resolc-x86_64-unknown-linux-musl --supported-solc-versions | cut -f 1 -d "," | tr -d ">=")
|
||||
export LAST_SOLC_VERSION=$(./resolc-x86_64-unknown-linux-musl --supported-solc-versions | cut -f 2 -d "," | tr -d "<=")
|
||||
|
||||
cd resolc-bin
|
||||
python ../tmp/.github/scripts/json_generator.py ${GITHUB_REPOSITORY} ${{ github.event.release.tag_name }}
|
||||
|
||||
echo "${Green}Add new remote with gh app token${NC}"
|
||||
git remote set-url origin $(git config remote.origin.url | sed "s/github.com/${APP_NAME}:${TOKEN}@github.com/g")
|
||||
|
||||
echo "${Green}Remove http section that causes issues with gh app auth token${NC}"
|
||||
sed -i.bak '/\[http/d' ./.git/config
|
||||
sed -i.bak '/extraheader/d' ./.git/config
|
||||
|
||||
git config user.email "ci@parity.io"
|
||||
git config user.name "${APP_NAME}"
|
||||
|
||||
git add .
|
||||
git commit -m "Update json"
|
||||
git push origin main
|
||||
|
||||
echo "::notice::info.list files were successfully published to https://github.com/paritytech/resolc-bin"
|
||||
@@ -1,11 +1,12 @@
|
||||
name: Release
|
||||
name: Build & Release
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
tags:
|
||||
- "v*"
|
||||
pull_request:
|
||||
branches: ["main"]
|
||||
types: [opened, synchronize, labled, unlabled]
|
||||
workflow_dispatch:
|
||||
types: [opened, synchronize, labeled, unlabeled]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
@@ -17,40 +18,44 @@ env:
|
||||
|
||||
jobs:
|
||||
check-version-changed:
|
||||
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'release-test')
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
contents: write
|
||||
env:
|
||||
CURRENT_TAG: ${{ github.ref_name }}
|
||||
outputs:
|
||||
TAG: ${{ steps.versions.outputs.TAG }}
|
||||
PKG_VER: ${{ steps.versions.outputs.PKG_VER }}
|
||||
RELEASE_NOTES: ${{ steps.versions.outputs.RELEASE_NOTES }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-tags: true
|
||||
|
||||
- name: Check Versions
|
||||
# Check that tag and version in Cargo.toml match
|
||||
- name: Check versions
|
||||
id: versions
|
||||
run: |
|
||||
export CURRENT_TAG=$(git describe --tags --abbrev=0 --exclude "llvm-*")
|
||||
if [[ $CURRENT_TAG == 'main' ]];
|
||||
then
|
||||
echo "::notice::Tag $CURRENT_TAG is not a release tag, skipping the check in the main branch";
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ $CURRENT_TAG != "v"* ]];
|
||||
then
|
||||
echo "::notice::Tag $CURRENT_TAG is not a release tag, skipping the check in a PR";
|
||||
exit 0
|
||||
fi
|
||||
|
||||
export PKG_VER=v$(cat Cargo.toml | grep -A 5 package] | grep version | cut -d '=' -f 2 | tr -d '"' | tr -d " ")
|
||||
echo "Current tag $CURRENT_TAG"
|
||||
echo "Package version $PKG_VER"
|
||||
#
|
||||
echo "PKG_VER=$PKG_VER" >> $GITHUB_OUTPUT
|
||||
if [[ $CURRENT_TAG == $PKG_VER ]];
|
||||
if [[ $CURRENT_TAG != $PKG_VER ]];
|
||||
then
|
||||
echo "Tag is up to date. Nothing to do.";
|
||||
export TAG=old;
|
||||
else
|
||||
echo "Tag was updated.";
|
||||
export TAG=new;
|
||||
echo "::error::Tag $CURRENT_TAG doesn't match package version $PKG_VER in Cargo.toml, please fix";
|
||||
exit 1
|
||||
fi
|
||||
echo "TAG=$TAG" >> $GITHUB_OUTPUT
|
||||
|
||||
# Generating release notes early, in order to avoid checkout at the last step
|
||||
export RELEASE_NOTES="$(sed '/^## '${PKG_VER}'/,/^## v/!d' CHANGELOG.md | sed -e '1d' -e '$d')"
|
||||
export RELEASE_NOTES="$(sed '/^## '${CURRENT_TAG}'/,/^## v/!d' CHANGELOG.md | sed -e '1d' -e '$d')"
|
||||
|
||||
echo "Release notes:"
|
||||
echo "$RELEASE_NOTES"
|
||||
@@ -62,7 +67,13 @@ jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
target: [x86_64-unknown-linux-musl, aarch64-apple-darwin, x86_64-apple-darwin, x86_64-pc-windows-msvc]
|
||||
target:
|
||||
[
|
||||
x86_64-unknown-linux-musl,
|
||||
aarch64-apple-darwin,
|
||||
x86_64-apple-darwin,
|
||||
x86_64-pc-windows-msvc,
|
||||
]
|
||||
include:
|
||||
- target: x86_64-unknown-linux-musl
|
||||
type: musl
|
||||
@@ -76,14 +87,13 @@ jobs:
|
||||
- target: x86_64-pc-windows-msvc
|
||||
type: native
|
||||
runner: windows-2022
|
||||
if: ${{ needs.check-version-changed.outputs.TAG == 'new' }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
needs: [check-version-changed]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
# without this it will override our rust flags
|
||||
# without this it will override our rust flags
|
||||
rustflags: ""
|
||||
cache-key: ${{ matrix.target }}
|
||||
|
||||
@@ -130,9 +140,10 @@ jobs:
|
||||
retention-days: 1
|
||||
|
||||
build-wasm:
|
||||
if: ${{ needs.check-version-changed.outputs.TAG == 'new' }}
|
||||
runs-on: ubuntu-24.04
|
||||
needs: [check-version-changed]
|
||||
env:
|
||||
RELEASE_RESOLC_WASM_URI: https://github.com/paritytech/revive-workflow-test/releases/download/${{ github.ref_name }}/resolc.wasm
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
@@ -165,12 +176,12 @@ jobs:
|
||||
- name: Set Up Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "20"
|
||||
node-version: "20"
|
||||
|
||||
- name: Basic Sanity Check
|
||||
run: |
|
||||
mkdir -p solc
|
||||
curl -sSLo solc/soljson.js https://github.com/ethereum/solidity/releases/download/v0.8.28/soljson.js
|
||||
curl -sSLo solc/soljson.js https://github.com/ethereum/solidity/releases/download/v0.8.29/soljson.js
|
||||
node -e "
|
||||
const soljson = require('solc/soljson');
|
||||
const createRevive = require('./target/wasm32-unknown-emscripten/release/resolc.js');
|
||||
@@ -207,23 +218,22 @@ jobs:
|
||||
|
||||
- name: Compress Artifact
|
||||
run: |
|
||||
tar -czf $(pwd)/resolc-wasm32-unknown-emscripten.tar.gz -C ./target/wasm32-unknown-emscripten/release/ \
|
||||
resolc.js \
|
||||
resolc.wasm \
|
||||
resolc_web.js
|
||||
mkdir -p resolc-wasm32-unknown-emscripten
|
||||
mv ./target/wasm32-unknown-emscripten/release/resolc.js ./resolc-wasm32-unknown-emscripten/
|
||||
mv ./target/wasm32-unknown-emscripten/release/resolc.wasm ./resolc-wasm32-unknown-emscripten/
|
||||
mv ./target/wasm32-unknown-emscripten/release/resolc_web.js ./resolc-wasm32-unknown-emscripten/
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: resolc-wasm32-unknown-emscripten
|
||||
path: resolc-wasm32-unknown-emscripten.tar.gz
|
||||
path: resolc-wasm32-unknown-emscripten/*
|
||||
retention-days: 1
|
||||
|
||||
create-release:
|
||||
if: github.event_name != 'pull_request'
|
||||
if: startsWith(github.ref_name, 'v')
|
||||
needs: [check-version-changed, build-wasm]
|
||||
runs-on: macos-14
|
||||
permissions:
|
||||
contents: write
|
||||
environment: tags
|
||||
steps:
|
||||
- name: Download Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
@@ -234,13 +244,16 @@ jobs:
|
||||
run: |
|
||||
lipo resolc-aarch64-apple-darwin resolc-x86_64-apple-darwin -create -output resolc-universal-apple-darwin
|
||||
|
||||
- name: Compress Artifacts
|
||||
- name: Make Executable
|
||||
run: |
|
||||
chmod +x resolc-x86_64-unknown-linux-musl
|
||||
chmod +x resolc-universal-apple-darwin
|
||||
tar -czf resolc-x86_64-unknown-linux-musl.tar.gz resolc-x86_64-unknown-linux-musl
|
||||
tar -czf resolc-universal-apple-darwin.tar.gz resolc-universal-apple-darwin
|
||||
zip -j resolc-x86_64-pc-windows-msvc.zip resolc-x86_64-pc-windows-msvc.exe
|
||||
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ secrets.REVIVE_RELEASE_APP_ID }}
|
||||
private-key: ${{ secrets.REVIVE_RELEASE_APP_KEY }}
|
||||
|
||||
- name: create-release
|
||||
uses: softprops/action-gh-release@v2
|
||||
@@ -251,12 +264,15 @@ jobs:
|
||||
|
||||
## Note for macOS Users
|
||||
The macOS binary is unsigned and it needs to be made runnable using `xattr -c resolc-universal-apple-darwin`.
|
||||
tag_name: ${{ needs.check-version-changed.outputs.PKG_VER }}
|
||||
name: ${{ needs.check-version-changed.outputs.PKG_VER }}
|
||||
draft: true
|
||||
tag_name: ${{ github.ref_name }}
|
||||
name: ${{ github.ref_name }}
|
||||
prerelease: true
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
target_commitish: ${{ github.sha }}
|
||||
files: |
|
||||
resolc-x86_64-unknown-linux-musl.tar.gz
|
||||
resolc-universal-apple-darwin.tar.gz
|
||||
resolc-wasm32-unknown-emscripten.tar.gz
|
||||
resolc-x86_64-pc-windows-msvc.zip
|
||||
resolc-x86_64-unknown-linux-musl
|
||||
resolc-universal-apple-darwin
|
||||
resolc-x86_64-pc-windows-msvc.exe
|
||||
resolc.js
|
||||
resolc.wasm
|
||||
resolc_web.js
|
||||
|
||||
@@ -6,6 +6,19 @@ This is a development pre-release.
|
||||
|
||||
Supported `polkadot-sdk` rev:`c29e72a8628835e34deb6aa7db9a78a2e4eabcee`
|
||||
|
||||
### Added
|
||||
- Support for solc v0.8.29
|
||||
- Decouples the solc JSON-input-output type definitions from the Solidity fronted and expose them via a dedicated crate.
|
||||
- `--supported-solc-versions` for `resolc` binary to return a `semver` range of supported `solc` versions.
|
||||
- Support for passing LLVM command line options via the prcoess input or providing one or more `--llvm-arg='..'` resolc CLI flag. This allows more fine-grained control over the LLVM backend configuration.
|
||||
|
||||
### Changed
|
||||
- Storage keys and values are big endian. This was a pre-mature optimization because for the contract itself it this is a no-op and thus not observable. However we should consider the storage layout as part of the contract ABI. The endianness of transient storage values are still kept as-is.
|
||||
- Runner `resolc` using webkit is no longer supported.
|
||||
|
||||
### Fixed
|
||||
- A missing byte swap for the create2 salt value.
|
||||
|
||||
## v0.1.0-dev.12
|
||||
|
||||
This is a development pre-release.
|
||||
|
||||
Generated
+19
-4
@@ -4965,9 +4965,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.71"
|
||||
version = "0.10.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd"
|
||||
checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"cfg-if",
|
||||
@@ -4997,9 +4997,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.106"
|
||||
version = "0.9.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd"
|
||||
checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
@@ -8368,12 +8368,14 @@ dependencies = [
|
||||
"hex",
|
||||
"inkwell",
|
||||
"itertools 0.14.0",
|
||||
"libc",
|
||||
"num",
|
||||
"polkavm-common 0.21.0",
|
||||
"polkavm-disassembler",
|
||||
"revive-common",
|
||||
"revive-linker",
|
||||
"revive-runtime-api",
|
||||
"revive-solc-json-interface",
|
||||
"revive-stdlib",
|
||||
"semver 1.0.25",
|
||||
"serde",
|
||||
@@ -8406,6 +8408,18 @@ dependencies = [
|
||||
"revive-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "revive-solc-json-interface"
|
||||
version = "0.1.0-dev.12"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"rayon",
|
||||
"revive-common",
|
||||
"semver 1.0.25",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "revive-solidity"
|
||||
version = "0.1.0-dev.12"
|
||||
@@ -8424,6 +8438,7 @@ dependencies = [
|
||||
"regex",
|
||||
"revive-common",
|
||||
"revive-llvm-context",
|
||||
"revive-solc-json-interface",
|
||||
"semver 1.0.25",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
||||
@@ -24,6 +24,7 @@ lld-sys = { version = "0.1.0-dev.12", path = "crates/lld-sys" }
|
||||
revive-llvm-context = { version = "0.1.0-dev.12", path = "crates/llvm-context" }
|
||||
revive-runtime-api = { version = "0.1.0-dev.12", path = "crates/runtime-api" }
|
||||
revive-runner = { version = "0.1.0-dev.12", path = "crates/runner" }
|
||||
revive-solc-json-interface = { version = "0.1.0-dev.12", path = "crates/solc-json-interface" }
|
||||
revive-solidity = { version = "0.1.0-dev.12", path = "crates/solidity" }
|
||||
revive-stdlib = { version = "0.1.0-dev.12", path = "crates/stdlib" }
|
||||
revive-build-utils = { version = "0.1.0-dev.12", path = "crates/build-utils" }
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
install: install-bin install-npm
|
||||
|
||||
install-bin:
|
||||
cargo install --path crates/solidity
|
||||
cargo install --locked --path crates/solidity
|
||||
|
||||
install-npm:
|
||||
npm install && npm fund
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||

|
||||

|
||||
[](https://contracts.polkadot.io/revive_compiler/)
|
||||
|
||||
# revive
|
||||
|
||||
+8
-5
@@ -4,11 +4,14 @@ Prior to the first stable release we neither have formal release processes nor d
|
||||
|
||||
To create a new pre-release:
|
||||
|
||||
1. Create a release PR which updates the `-dev.X` versions in the workspace `Cargo.toml` and updates the `CHANGELOG.md` accordingly. Add the `release-test` label to trigger the release workflows.
|
||||
2. If the CI passes, merge the release PR. The release workflow will attempt to build and publish a new release whenever the latest git tag does not match the cargo package version.
|
||||
3. Wait for the `Release` workflow to finish. If the workflow fails after the `build-linux-all` step, check if a tag has been created and delete it before restarting or pushing updates. Note: It's more convenient to debug the release workflow in a fork (the fork has to be under the `paritytech` org to access `parity-large` runners).
|
||||
4. Check draft release on [Releases page](https://github.com/paritytech/revive/releases) and publish (should contain `resolc.js`, `resolc.wasm`, `resolc-web.js`, and `resolc-static-linux` release assets)
|
||||
5. Update the [contract-docs](https://github.com/paritytech/contract-docs/) accordingly
|
||||
1. Create a release PR which updates the `-dev.X` versions in the workspace `Cargo.toml` and updates the `CHANGELOG.md` accordingly.
|
||||
2. If the CI passes, merge the release PR.
|
||||
3. Push a tag that has the same `-dev.X` version as in `Cargo.toml`
|
||||
4. The release workflow will attempt to build and publish a new pre-release if the latest tag does match the cargo package version.
|
||||
5. Wait for the `Release` workflow to finish. It should create the pre-release with the same `-dev.X` name.
|
||||
6. Check that pre-release was created on the [Releases page](https://github.com/paritytech/revive/releases) with all artifacts.
|
||||
7. After the release is published, another workflow should start automatically and update json files in https://github.com/paritytech/resolc-bin. Check the changes.
|
||||
8. Update the [contract-docs](https://github.com/paritytech/contract-docs/) accordingly
|
||||
|
||||
# LLVM release
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
"Baseline": 1443,
|
||||
"Computation": 2788,
|
||||
"DivisionArithmetics": 9748,
|
||||
"ERC20": 19203,
|
||||
"ERC20": 19150,
|
||||
"Events": 2201,
|
||||
"FibonacciIterative": 2041,
|
||||
"Flipper": 2632,
|
||||
"SHA1": 8958
|
||||
"Flipper": 2691,
|
||||
"SHA1": 8997
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.28;
|
||||
|
||||
contract Predicted {
|
||||
uint public salt;
|
||||
|
||||
constructor(uint _salt) {
|
||||
salt = _salt;
|
||||
}
|
||||
}
|
||||
|
||||
contract AddressPredictor {
|
||||
constructor(uint _salt, bytes memory _bytecode) payable {
|
||||
address deployed = address(new Predicted{salt: bytes32(_salt)}(_salt));
|
||||
address predicted = predictAddress(_salt, _bytecode);
|
||||
assert(deployed == predicted);
|
||||
}
|
||||
|
||||
function predictAddress(
|
||||
uint _foo,
|
||||
bytes memory _bytecode
|
||||
) public view returns (address predicted) {
|
||||
bytes32 addr = keccak256(
|
||||
abi.encodePacked(
|
||||
bytes1(0xff),
|
||||
address(this),
|
||||
bytes32(_foo),
|
||||
keccak256(abi.encodePacked(_bytecode, abi.encode(_foo)))
|
||||
)
|
||||
);
|
||||
predicted = address(uint160(uint(addr)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.29;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"differential": true,
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "LayoutAt"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "a7a0d537"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "15393349"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract LayoutAt layout at 0xDEADBEEF + 0xCAFEBABE {
|
||||
uint[3] public something;
|
||||
|
||||
constructor() payable {
|
||||
something[0] = 1337;
|
||||
something[1] = 42;
|
||||
something[2] = 69;
|
||||
}
|
||||
|
||||
function slotOfSomething() public pure returns (uint ret) {
|
||||
assembly {
|
||||
ret := something.slot
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ pragma solidity ^0.8;
|
||||
"Instantiated": 0
|
||||
},
|
||||
"key": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"expected": "0100000000000000000000000000000000000000000000000000000000000000"
|
||||
"expected": "0000000000000000000000000000000000000000000000000000000000000001"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -250,6 +250,17 @@ sol!(
|
||||
);
|
||||
case!("Storage.sol", Storage, transientCall, storage_transient, value: U256);
|
||||
|
||||
sol!(
|
||||
contract Predicted {
|
||||
constructor(uint _foo);
|
||||
}
|
||||
contract AddressPredictor {
|
||||
constructor(uint _foo, bytes memory _bytecode) payable;
|
||||
}
|
||||
);
|
||||
case!("AddressPredictor.sol", Predicted, constructorCall, predicted_constructor, salt: U256);
|
||||
case!("AddressPredictor.sol", AddressPredictor, constructorCall, address_predictor_constructor, salt: U256, bytecode: Bytes);
|
||||
|
||||
impl Contract {
|
||||
pub fn build(calldata: Vec<u8>, name: &'static str, code: &str) -> Self {
|
||||
Self {
|
||||
|
||||
@@ -59,6 +59,7 @@ test_spec!(function_pointer, "FunctionPointer", "FunctionPointer.sol");
|
||||
test_spec!(mload, "MLoad", "MLoad.sol");
|
||||
test_spec!(delegate_no_contract, "DelegateCaller", "DelegateCaller.sol");
|
||||
test_spec!(function_type, "FunctionType", "FunctionType.sol");
|
||||
test_spec!(layout_at, "LayoutAt", "LayoutAt.sol");
|
||||
|
||||
fn instantiate(path: &str, contract: &str) -> Vec<SpecsAction> {
|
||||
vec![Instantiate {
|
||||
@@ -485,3 +486,31 @@ fn transfer_denies_reentrancy() {
|
||||
}
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create2_salt() {
|
||||
let salt = U256::from(777);
|
||||
let predicted = Contract::predicted_constructor(salt).pvm_runtime;
|
||||
let predictor = Contract::address_predictor_constructor(salt, predicted.clone().into());
|
||||
Specs {
|
||||
actions: vec![
|
||||
Upload {
|
||||
origin: TestAddress::Alice,
|
||||
code: Code::Bytes(predicted),
|
||||
storage_deposit_limit: None,
|
||||
},
|
||||
Instantiate {
|
||||
origin: TestAddress::Alice,
|
||||
value: 0,
|
||||
gas_limit: Some(GAS_LIMIT),
|
||||
storage_deposit_limit: None,
|
||||
code: Code::Bytes(predictor.pvm_runtime),
|
||||
data: predictor.calldata,
|
||||
salt: OptionalHex::default(),
|
||||
},
|
||||
],
|
||||
differential: false,
|
||||
..Default::default()
|
||||
}
|
||||
.run();
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ num = { workspace = true }
|
||||
hex = { workspace = true }
|
||||
sha3 = { workspace = true }
|
||||
inkwell = { workspace = true }
|
||||
libc = { workspace = true }
|
||||
polkavm-disassembler = { workspace = true }
|
||||
polkavm-common = { workspace = true }
|
||||
|
||||
@@ -29,3 +30,4 @@ revive-common = { workspace = true }
|
||||
revive-runtime-api = { workspace = true }
|
||||
revive-linker = { workspace = true }
|
||||
revive-stdlib = { workspace = true }
|
||||
revive-solc-json-interface = { workspace = true }
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
//! The LLVM context library.
|
||||
|
||||
pub(crate) mod debug_config;
|
||||
pub(crate) mod optimizer;
|
||||
pub(crate) mod polkavm;
|
||||
pub(crate) mod target_machine;
|
||||
use std::ffi::CString;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
pub use self::debug_config::ir_type::IRType as DebugConfigIR;
|
||||
pub use self::debug_config::DebugConfig;
|
||||
@@ -38,7 +36,9 @@ pub use self::polkavm::context::function::Function as PolkaVMFunction;
|
||||
pub use self::polkavm::context::global::Global as PolkaVMGlobal;
|
||||
pub use self::polkavm::context::pointer::heap::LoadWord as PolkaVMLoadHeapWordFunction;
|
||||
pub use self::polkavm::context::pointer::heap::StoreWord as PolkaVMStoreHeapWordFunction;
|
||||
pub use self::polkavm::context::pointer::storage::LoadTransientWord as PolkaVMLoadTransientStorageWordFunction;
|
||||
pub use self::polkavm::context::pointer::storage::LoadWord as PolkaVMLoadStorageWordFunction;
|
||||
pub use self::polkavm::context::pointer::storage::StoreTransientWord as PolkaVMStoreTransientStorageWordFunction;
|
||||
pub use self::polkavm::context::pointer::storage::StoreWord as PolkaVMStoreStorageWordFunction;
|
||||
pub use self::polkavm::context::pointer::Pointer as PolkaVMPointer;
|
||||
pub use self::polkavm::context::r#loop::Loop as PolkaVMLoop;
|
||||
@@ -66,7 +66,6 @@ pub use self::polkavm::evm::memory as polkavm_evm_memory;
|
||||
pub use self::polkavm::evm::r#return as polkavm_evm_return;
|
||||
pub use self::polkavm::evm::return_data as polkavm_evm_return_data;
|
||||
pub use self::polkavm::evm::storage as polkavm_evm_storage;
|
||||
pub use self::polkavm::metadata_hash::MetadataHash as PolkaVMMetadataHash;
|
||||
pub use self::polkavm::r#const as polkavm_const;
|
||||
pub use self::polkavm::Dependency as PolkaVMDependency;
|
||||
pub use self::polkavm::DummyDependency as PolkaVMDummyDependency;
|
||||
@@ -75,9 +74,41 @@ pub use self::polkavm::WriteLLVM as PolkaVMWriteLLVM;
|
||||
pub use self::target_machine::target::Target;
|
||||
pub use self::target_machine::TargetMachine;
|
||||
|
||||
/// Initializes the target machine.
|
||||
pub fn initialize_target(target: Target) {
|
||||
pub(crate) mod debug_config;
|
||||
pub(crate) mod optimizer;
|
||||
pub(crate) mod polkavm;
|
||||
pub(crate) mod target_machine;
|
||||
|
||||
static DID_INITIALIZE: OnceLock<()> = OnceLock::new();
|
||||
|
||||
/// Initializes the LLVM compiler backend.
|
||||
///
|
||||
/// This is a no-op if called subsequentially.
|
||||
///
|
||||
/// `llvm_arguments` are passed as-is to the LLVM CL options parser.
|
||||
pub fn initialize_llvm(target: Target, name: &str, llvm_arguments: &[String]) {
|
||||
let Ok(_) = DID_INITIALIZE.set(()) else {
|
||||
return; // Tests don't go through a recursive process
|
||||
};
|
||||
|
||||
let argv = [name.to_string()]
|
||||
.iter()
|
||||
.chain(llvm_arguments)
|
||||
.map(|arg| CString::new(arg.as_bytes()).unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
let argv: Vec<*const libc::c_char> = argv.iter().map(|arg| arg.as_ptr()).collect();
|
||||
let overview = CString::new("").unwrap();
|
||||
unsafe {
|
||||
inkwell::llvm_sys::support::LLVMParseCommandLineOptions(
|
||||
argv.len() as i32,
|
||||
argv.as_ptr(),
|
||||
overview.as_ptr(),
|
||||
);
|
||||
}
|
||||
|
||||
inkwell::support::enable_llvm_pretty_stack_trace();
|
||||
|
||||
match target {
|
||||
Target::PVM => self::polkavm::initialize_target(),
|
||||
Target::PVM => inkwell::targets::Target::initialize_riscv(&Default::default()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
pub mod size_level;
|
||||
|
||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsOptimizer;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -226,3 +227,18 @@ impl std::fmt::Display for Settings {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&SolcStandardJsonInputSettingsOptimizer> for Settings {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: &SolcStandardJsonInputSettingsOptimizer) -> Result<Self, Self::Error> {
|
||||
let mut result = match value.mode {
|
||||
Some(mode) => Self::try_from_cli(mode)?,
|
||||
None => Self::cycles(),
|
||||
};
|
||||
if value.fallback_to_optimizing_for_size.unwrap_or_default() {
|
||||
result.enable_fallback_to_size();
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,6 +83,8 @@ where
|
||||
current_function: Option<Rc<RefCell<Function<'ctx>>>>,
|
||||
/// The loop context stack.
|
||||
loop_stack: Vec<Loop<'ctx>>,
|
||||
/// The extra LLVM arguments that were used during target initialization.
|
||||
llvm_arguments: &'ctx [String],
|
||||
|
||||
/// The project dependency manager. It can be any entity implementing the trait.
|
||||
/// The manager is used to get information about contracts and their dependencies during
|
||||
@@ -223,6 +225,7 @@ where
|
||||
dependency_manager: Option<D>,
|
||||
include_metadata_hash: bool,
|
||||
debug_config: DebugConfig,
|
||||
llvm_arguments: &'ctx [String],
|
||||
) -> Self {
|
||||
Self::set_data_layout(llvm, &module);
|
||||
Self::link_stdlib_module(llvm, &module);
|
||||
@@ -250,6 +253,7 @@ where
|
||||
functions: HashMap::with_capacity(Self::FUNCTIONS_HASHMAP_INITIAL_CAPACITY),
|
||||
current_function: None,
|
||||
loop_stack: Vec::with_capacity(Self::LOOP_STACK_INITIAL_CAPACITY),
|
||||
llvm_arguments,
|
||||
|
||||
dependency_manager,
|
||||
include_metadata_hash,
|
||||
@@ -639,6 +643,7 @@ where
|
||||
self.optimizer.settings().to_owned(),
|
||||
self.include_metadata_hash,
|
||||
self.debug_config.clone(),
|
||||
self.llvm_arguments,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -17,47 +17,20 @@ where
|
||||
const NAME: &'static str = "__revive_load_storage_word";
|
||||
|
||||
fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> {
|
||||
context.word_type().fn_type(
|
||||
&[context.xlen_type().into(), context.word_type().into()],
|
||||
false,
|
||||
)
|
||||
context
|
||||
.word_type()
|
||||
.fn_type(&[context.word_type().into()], false)
|
||||
}
|
||||
|
||||
fn emit_body<'ctx>(
|
||||
&self,
|
||||
context: &mut Context<'ctx, D>,
|
||||
) -> anyhow::Result<Option<BasicValueEnum<'ctx>>> {
|
||||
let is_transient = Self::paramater(context, 0);
|
||||
let key_value = Self::paramater(context, 1);
|
||||
|
||||
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
|
||||
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
|
||||
let length_pointer = context.build_alloca_at_entry(context.xlen_type(), "length_pointer");
|
||||
|
||||
context
|
||||
.builder()
|
||||
.build_store(key_pointer.value, key_value)?;
|
||||
context.build_store(value_pointer, context.word_const(0))?;
|
||||
context.build_store(
|
||||
length_pointer,
|
||||
context
|
||||
.xlen_type()
|
||||
.const_int(revive_common::BYTE_LENGTH_WORD as u64, false),
|
||||
)?;
|
||||
|
||||
let arguments = [
|
||||
is_transient,
|
||||
key_pointer.to_int(context).into(),
|
||||
context.xlen_type().const_all_ones().into(),
|
||||
value_pointer.to_int(context).into(),
|
||||
length_pointer.to_int(context).into(),
|
||||
];
|
||||
context.build_runtime_call(revive_runtime_api::polkavm_imports::GET_STORAGE, &arguments);
|
||||
|
||||
// We do not to check the return value: Solidity assumes infallible loads.
|
||||
// If a key doesn't exist the "zero" value is returned (ensured by above write).
|
||||
|
||||
Ok(Some(context.build_load(value_pointer, "storage_value")?))
|
||||
Ok(Some(emit_load(
|
||||
context,
|
||||
Self::paramater(context, 0),
|
||||
false,
|
||||
)?))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +47,42 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Load a word size value from a transient storage pointer.
|
||||
pub struct LoadTransientWord;
|
||||
|
||||
impl<D> RuntimeFunction<D> for LoadTransientWord
|
||||
where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
const NAME: &'static str = "__revive_load_transient_storage_word";
|
||||
|
||||
fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> {
|
||||
context
|
||||
.word_type()
|
||||
.fn_type(&[context.word_type().into()], false)
|
||||
}
|
||||
|
||||
fn emit_body<'ctx>(
|
||||
&self,
|
||||
context: &mut Context<'ctx, D>,
|
||||
) -> anyhow::Result<Option<BasicValueEnum<'ctx>>> {
|
||||
Ok(Some(emit_load(context, Self::paramater(context, 0), true)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> WriteLLVM<D> for LoadTransientWord
|
||||
where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
fn declare(&mut self, context: &mut Context<D>) -> anyhow::Result<()> {
|
||||
<Self as RuntimeFunction<_>>::declare(self, context)
|
||||
}
|
||||
|
||||
fn into_llvm(self, context: &mut Context<D>) -> anyhow::Result<()> {
|
||||
<Self as RuntimeFunction<_>>::emit(&self, context)
|
||||
}
|
||||
}
|
||||
|
||||
/// Store a word size value through a storage pointer.
|
||||
pub struct StoreWord;
|
||||
|
||||
@@ -85,11 +94,7 @@ where
|
||||
|
||||
fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> {
|
||||
context.void_type().fn_type(
|
||||
&[
|
||||
context.xlen_type().into(),
|
||||
context.word_type().into(),
|
||||
context.word_type().into(),
|
||||
],
|
||||
&[context.word_type().into(), context.word_type().into()],
|
||||
false,
|
||||
)
|
||||
}
|
||||
@@ -98,24 +103,12 @@ where
|
||||
&self,
|
||||
context: &mut Context<'ctx, D>,
|
||||
) -> anyhow::Result<Option<BasicValueEnum<'ctx>>> {
|
||||
let is_transient = Self::paramater(context, 0);
|
||||
let key = Self::paramater(context, 1);
|
||||
let value = Self::paramater(context, 2);
|
||||
|
||||
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
|
||||
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
|
||||
|
||||
context.build_store(key_pointer, key)?;
|
||||
context.build_store(value_pointer, value)?;
|
||||
|
||||
let arguments = [
|
||||
is_transient,
|
||||
key_pointer.to_int(context).into(),
|
||||
context.xlen_type().const_all_ones().into(),
|
||||
value_pointer.to_int(context).into(),
|
||||
context.integer_const(crate::polkavm::XLEN, 32).into(),
|
||||
];
|
||||
context.build_runtime_call(revive_runtime_api::polkavm_imports::SET_STORAGE, &arguments);
|
||||
emit_store(
|
||||
context,
|
||||
Self::paramater(context, 0),
|
||||
Self::paramater(context, 1),
|
||||
false,
|
||||
)?;
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
@@ -133,3 +126,122 @@ where
|
||||
<Self as RuntimeFunction<_>>::emit(&self, context)
|
||||
}
|
||||
}
|
||||
|
||||
/// Store a word size value through a transient storage pointer.
|
||||
pub struct StoreTransientWord;
|
||||
|
||||
impl<D> RuntimeFunction<D> for StoreTransientWord
|
||||
where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
const NAME: &'static str = "__revive_store_transient_storage_word";
|
||||
|
||||
fn r#type<'ctx>(context: &Context<'ctx, D>) -> inkwell::types::FunctionType<'ctx> {
|
||||
context.void_type().fn_type(
|
||||
&[context.word_type().into(), context.word_type().into()],
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
fn emit_body<'ctx>(
|
||||
&self,
|
||||
context: &mut Context<'ctx, D>,
|
||||
) -> anyhow::Result<Option<BasicValueEnum<'ctx>>> {
|
||||
emit_store(
|
||||
context,
|
||||
Self::paramater(context, 0),
|
||||
Self::paramater(context, 1),
|
||||
true,
|
||||
)?;
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> WriteLLVM<D> for StoreTransientWord
|
||||
where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
fn declare(&mut self, context: &mut Context<D>) -> anyhow::Result<()> {
|
||||
<Self as RuntimeFunction<_>>::declare(self, context)
|
||||
}
|
||||
|
||||
fn into_llvm(self, context: &mut Context<D>) -> anyhow::Result<()> {
|
||||
<Self as RuntimeFunction<_>>::emit(&self, context)
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_load<'ctx, D: Dependency + Clone>(
|
||||
context: &mut Context<'ctx, D>,
|
||||
mut key: BasicValueEnum<'ctx>,
|
||||
transient: bool,
|
||||
) -> anyhow::Result<BasicValueEnum<'ctx>> {
|
||||
if !transient {
|
||||
key = context.build_byte_swap(key)?;
|
||||
}
|
||||
|
||||
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
|
||||
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
|
||||
let length_pointer = context.build_alloca_at_entry(context.xlen_type(), "length_pointer");
|
||||
|
||||
context.builder().build_store(key_pointer.value, key)?;
|
||||
context.build_store(value_pointer, context.word_const(0))?;
|
||||
context.build_store(
|
||||
length_pointer,
|
||||
context
|
||||
.xlen_type()
|
||||
.const_int(revive_common::BYTE_LENGTH_WORD as u64, false),
|
||||
)?;
|
||||
|
||||
let is_transient = context.xlen_type().const_int(transient as u64, false);
|
||||
|
||||
let arguments = [
|
||||
is_transient.into(),
|
||||
key_pointer.to_int(context).into(),
|
||||
context.xlen_type().const_all_ones().into(),
|
||||
value_pointer.to_int(context).into(),
|
||||
length_pointer.to_int(context).into(),
|
||||
];
|
||||
context.build_runtime_call(revive_runtime_api::polkavm_imports::GET_STORAGE, &arguments);
|
||||
|
||||
// We do not to check the return value: Solidity assumes infallible loads.
|
||||
// If a key doesn't exist the "zero" value is returned (ensured by above write).
|
||||
|
||||
let value = context.build_load(value_pointer, "storage_value")?;
|
||||
Ok(if transient {
|
||||
value
|
||||
} else {
|
||||
context.build_byte_swap(value)?
|
||||
})
|
||||
}
|
||||
|
||||
fn emit_store<'ctx, D: Dependency + Clone>(
|
||||
context: &mut Context<'ctx, D>,
|
||||
mut key: BasicValueEnum<'ctx>,
|
||||
mut value: BasicValueEnum<'ctx>,
|
||||
transient: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
if !transient {
|
||||
key = context.build_byte_swap(key)?;
|
||||
value = context.build_byte_swap(value)?;
|
||||
}
|
||||
|
||||
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
|
||||
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
|
||||
|
||||
context.build_store(key_pointer, key)?;
|
||||
context.build_store(value_pointer, value)?;
|
||||
|
||||
let is_transient = context.xlen_type().const_int(transient as u64, false);
|
||||
|
||||
let arguments = [
|
||||
is_transient.into(),
|
||||
key_pointer.to_int(context).into(),
|
||||
context.xlen_type().const_all_ones().into(),
|
||||
value_pointer.to_int(context).into(),
|
||||
context.integer_const(crate::polkavm::XLEN, 32).into(),
|
||||
];
|
||||
context.build_runtime_call(revive_runtime_api::polkavm_imports::SET_STORAGE, &arguments);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -10,12 +10,20 @@ pub fn create_context(
|
||||
llvm: &inkwell::context::Context,
|
||||
optimizer_settings: OptimizerSettings,
|
||||
) -> Context<DummyDependency> {
|
||||
crate::polkavm::initialize_target();
|
||||
crate::initialize_llvm(crate::Target::PVM, "resolc", Default::default());
|
||||
|
||||
let module = llvm.create_module("test");
|
||||
let optimizer = Optimizer::new(optimizer_settings);
|
||||
|
||||
Context::<DummyDependency>::new(llvm, module, optimizer, None, true, Default::default())
|
||||
Context::<DummyDependency>::new(
|
||||
llvm,
|
||||
module,
|
||||
optimizer,
|
||||
None,
|
||||
true,
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -32,6 +32,7 @@ where
|
||||
let salt_pointer = match salt {
|
||||
Some(salt) => {
|
||||
let salt_pointer = context.build_alloca_at_entry(context.word_type(), "salt_pointer");
|
||||
let salt = context.build_byte_swap(salt.into())?;
|
||||
context.build_store(salt_pointer, salt)?;
|
||||
salt_pointer
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@ use crate::polkavm::context::runtime::RuntimeFunction;
|
||||
use crate::polkavm::context::Context;
|
||||
use crate::polkavm::Dependency;
|
||||
use crate::PolkaVMLoadStorageWordFunction;
|
||||
use crate::PolkaVMLoadTransientStorageWordFunction;
|
||||
use crate::PolkaVMStoreStorageWordFunction;
|
||||
use crate::PolkaVMStoreTransientStorageWordFunction;
|
||||
|
||||
/// Translates the storage load.
|
||||
pub fn load<'ctx, D>(
|
||||
@@ -16,7 +18,7 @@ where
|
||||
{
|
||||
let name = <PolkaVMLoadStorageWordFunction as RuntimeFunction<D>>::NAME;
|
||||
let declaration = <PolkaVMLoadStorageWordFunction as RuntimeFunction<D>>::declaration(context);
|
||||
let arguments = [context.xlen_type().const_zero().into(), position.into()];
|
||||
let arguments = [position.into()];
|
||||
Ok(context
|
||||
.build_call(declaration, &arguments, "storage_load")
|
||||
.unwrap_or_else(|| panic!("runtime function {name} should return a value")))
|
||||
@@ -32,11 +34,7 @@ where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
let declaration = <PolkaVMStoreStorageWordFunction as RuntimeFunction<D>>::declaration(context);
|
||||
let arguments = [
|
||||
context.xlen_type().const_zero().into(),
|
||||
position.into(),
|
||||
value.into(),
|
||||
];
|
||||
let arguments = [position.into(), value.into()];
|
||||
context.build_call(declaration, &arguments, "storage_store");
|
||||
Ok(())
|
||||
}
|
||||
@@ -49,14 +47,12 @@ pub fn transient_load<'ctx, D>(
|
||||
where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
let name = <PolkaVMLoadStorageWordFunction as RuntimeFunction<D>>::NAME;
|
||||
let declaration = <PolkaVMLoadStorageWordFunction as RuntimeFunction<D>>::declaration(context);
|
||||
let arguments = [
|
||||
context.xlen_type().const_int(1, false).into(),
|
||||
position.into(),
|
||||
];
|
||||
let name = <PolkaVMLoadTransientStorageWordFunction as RuntimeFunction<D>>::NAME;
|
||||
let arguments = [position.into()];
|
||||
let declaration =
|
||||
<PolkaVMLoadTransientStorageWordFunction as RuntimeFunction<D>>::declaration(context);
|
||||
Ok(context
|
||||
.build_call(declaration, &arguments, "storage_load")
|
||||
.build_call(declaration, &arguments, "transient_storage_load")
|
||||
.unwrap_or_else(|| panic!("runtime function {name} should return a value")))
|
||||
}
|
||||
|
||||
@@ -69,12 +65,9 @@ pub fn transient_store<'ctx, D>(
|
||||
where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
let declaration = <PolkaVMStoreStorageWordFunction as RuntimeFunction<D>>::declaration(context);
|
||||
let arguments = [
|
||||
context.xlen_type().const_int(1, false).into(),
|
||||
position.into(),
|
||||
value.into(),
|
||||
];
|
||||
context.build_call(declaration, &arguments, "storage_store");
|
||||
let declaration =
|
||||
<PolkaVMStoreTransientStorageWordFunction as RuntimeFunction<D>>::declaration(context);
|
||||
let arguments = [position.into(), value.into()];
|
||||
context.build_call(declaration, &arguments, "transient_storage_store");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
pub mod r#const;
|
||||
pub mod context;
|
||||
pub mod evm;
|
||||
pub mod metadata_hash;
|
||||
|
||||
pub use self::r#const::*;
|
||||
|
||||
@@ -18,11 +17,6 @@ use sha3::Digest;
|
||||
use self::context::build::Build;
|
||||
use self::context::Context;
|
||||
|
||||
/// Initializes the PolkaVM target machine.
|
||||
pub fn initialize_target() {
|
||||
inkwell::targets::Target::initialize_riscv(&Default::default());
|
||||
}
|
||||
|
||||
/// Builds PolkaVM assembly text.
|
||||
pub fn build_assembly_text(
|
||||
contract_path: &str,
|
||||
@@ -95,6 +89,7 @@ pub trait Dependency {
|
||||
optimizer_settings: OptimizerSettings,
|
||||
include_metadata_hash: bool,
|
||||
debug_config: DebugConfig,
|
||||
llvm_arguments: &[String],
|
||||
) -> anyhow::Result<String>;
|
||||
|
||||
/// Resolves a full contract path.
|
||||
@@ -115,6 +110,7 @@ impl Dependency for DummyDependency {
|
||||
_optimizer_settings: OptimizerSettings,
|
||||
_include_metadata_hash: bool,
|
||||
_debug_config: DebugConfig,
|
||||
_llvm_arguments: &[String],
|
||||
) -> anyhow::Result<String> {
|
||||
Ok(String::new())
|
||||
}
|
||||
|
||||
@@ -106,14 +106,10 @@ impl SpecsAction {
|
||||
};
|
||||
|
||||
for (key, expected) in storage {
|
||||
let mut key = **key;
|
||||
let mut expected = **expected;
|
||||
key.reverse();
|
||||
expected.reverse();
|
||||
actions.push(Self::VerifyStorage {
|
||||
contract: account_pvm.clone(),
|
||||
key,
|
||||
expected,
|
||||
key: **key,
|
||||
expected: **expected,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
[package]
|
||||
name = "revive-solc-json-interface"
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
license.workspace = true
|
||||
edition.workspace = true
|
||||
repository.workspace = true
|
||||
rust-version.workspace = true
|
||||
description = "Rust bindings for the solc standard JSON and combined JSON interface"
|
||||
|
||||
[features]
|
||||
default = ["parallel"]
|
||||
parallel = ["rayon"]
|
||||
resolc = [] # The resolc binary adds a bunch of custom fields to the format
|
||||
|
||||
[dependencies]
|
||||
revive-common = { workspace = true }
|
||||
|
||||
anyhow = { workspace = true }
|
||||
rayon = { workspace = true, optional = true }
|
||||
semver = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
@@ -0,0 +1,27 @@
|
||||
//! This crates provides (de)serializable Rust types for interacting
|
||||
//! `solc` via the [JSON-input-output][0] interface.
|
||||
//!
|
||||
//! [0]: https://docs.soliditylang.org/en/latest/using-the-compiler.html#compiler-input-and-output-json-description
|
||||
|
||||
pub use self::combined_json::contract::Contract as CombinedJsonContract;
|
||||
pub use self::standard_json::input::language::Language as SolcStandardJsonInputLanguage;
|
||||
pub use self::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
|
||||
pub use self::standard_json::input::settings::metadata_hash::MetadataHash as SolcStandardJsonInputSettingsMetadataHash;
|
||||
pub use self::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
||||
pub use self::standard_json::input::settings::selection::file::flag::Flag as SolcStandardJsonInputSettingsSelectionFileFlag;
|
||||
pub use self::standard_json::input::settings::selection::file::File as SolcStandardJsonInputSettingsSelectionFile;
|
||||
pub use self::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
|
||||
pub use self::standard_json::input::settings::Settings as SolcStandardJsonInputSettings;
|
||||
pub use self::standard_json::input::source::Source as SolcStandardJsonInputSource;
|
||||
pub use self::standard_json::input::Input as SolcStandardJsonInput;
|
||||
pub use self::standard_json::output::contract::evm::bytecode::Bytecode as SolcStandardJsonOutputContractEVMBytecode;
|
||||
pub use self::standard_json::output::contract::evm::EVM as SolcStandardJsonOutputContractEVM;
|
||||
pub use self::standard_json::output::contract::Contract as SolcStandardJsonOutputContract;
|
||||
pub use self::standard_json::output::Output as SolcStandardJsonOutput;
|
||||
#[cfg(feature = "resolc")]
|
||||
pub use self::warning::Warning as ResolcWarning;
|
||||
|
||||
pub mod combined_json;
|
||||
pub mod standard_json;
|
||||
#[cfg(feature = "resolc")]
|
||||
pub mod warning;
|
||||
+9
-5
@@ -8,14 +8,15 @@ use std::collections::BTreeMap;
|
||||
use std::collections::BTreeSet;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg(feature = "parallel")]
|
||||
#[cfg(all(feature = "parallel", feature = "resolc"))]
|
||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::solc::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
|
||||
use crate::solc::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
||||
use crate::solc::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
|
||||
use crate::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
|
||||
use crate::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
||||
use crate::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
|
||||
#[cfg(feature = "resolc")]
|
||||
use crate::warning::Warning;
|
||||
|
||||
use self::language::Language;
|
||||
@@ -33,6 +34,7 @@ pub struct Input {
|
||||
/// The compiler settings.
|
||||
pub settings: Settings,
|
||||
/// The suppressed warnings.
|
||||
#[cfg(feature = "resolc")]
|
||||
#[serde(skip_serializing)]
|
||||
pub suppressed_warnings: Option<Vec<Warning>>,
|
||||
}
|
||||
@@ -60,7 +62,7 @@ impl Input {
|
||||
output_selection: SolcStandardJsonInputSettingsSelection,
|
||||
optimizer: SolcStandardJsonInputSettingsOptimizer,
|
||||
metadata: Option<SolcStandardJsonInputSettingsMetadata>,
|
||||
suppressed_warnings: Option<Vec<Warning>>,
|
||||
#[cfg(feature = "resolc")] suppressed_warnings: Option<Vec<Warning>>,
|
||||
) -> anyhow::Result<Self> {
|
||||
let mut paths: BTreeSet<PathBuf> = paths.iter().cloned().collect();
|
||||
let libraries = Settings::parse_libraries(library_map)?;
|
||||
@@ -89,12 +91,14 @@ impl Input {
|
||||
optimizer,
|
||||
metadata,
|
||||
),
|
||||
#[cfg(feature = "resolc")]
|
||||
suppressed_warnings,
|
||||
})
|
||||
}
|
||||
|
||||
/// A shortcut constructor from source code.
|
||||
/// Only for the integration test purposes.
|
||||
#[cfg(feature = "resolc")]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn try_from_sources(
|
||||
evm_version: Option<revive_common::EVMVersion>,
|
||||
+4
-2
@@ -3,18 +3,20 @@
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::standard_json::input::settings::metadata_hash::MetadataHash;
|
||||
|
||||
/// The `solc --standard-json` input settings metadata.
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Metadata {
|
||||
/// The bytecode hash mode.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub bytecode_hash: Option<revive_llvm_context::PolkaVMMetadataHash>,
|
||||
pub bytecode_hash: Option<MetadataHash>,
|
||||
}
|
||||
|
||||
impl Metadata {
|
||||
/// A shortcut constructor.
|
||||
pub fn new(bytecode_hash: revive_llvm_context::PolkaVMMetadataHash) -> Self {
|
||||
pub fn new(bytecode_hash: MetadataHash) -> Self {
|
||||
Self {
|
||||
bytecode_hash: Some(bytecode_hash),
|
||||
}
|
||||
+1
@@ -1,6 +1,7 @@
|
||||
//! The `solc --standard-json` input settings.
|
||||
|
||||
pub mod metadata;
|
||||
pub mod metadata_hash;
|
||||
pub mod optimizer;
|
||||
pub mod selection;
|
||||
|
||||
-15
@@ -49,18 +49,3 @@ impl Optimizer {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&Optimizer> for revive_llvm_context::OptimizerSettings {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(value: &Optimizer) -> Result<Self, Self::Error> {
|
||||
let mut result = match value.mode {
|
||||
Some(mode) => Self::try_from_cli(mode)?,
|
||||
None => Self::cycles(),
|
||||
};
|
||||
if value.fallback_to_optimizing_for_size.unwrap_or_default() {
|
||||
result.enable_fallback_to_size();
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
//! The `solc <input>.sol --standard-json` interface input and output.
|
||||
|
||||
pub mod input;
|
||||
pub mod output;
|
||||
@@ -0,0 +1,71 @@
|
||||
//! The `solc --standard-json` output.
|
||||
|
||||
pub mod contract;
|
||||
pub mod error;
|
||||
pub mod source;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
#[cfg(feature = "resolc")]
|
||||
use crate::warning::Warning;
|
||||
|
||||
use self::contract::Contract;
|
||||
use self::error::Error as SolcStandardJsonOutputError;
|
||||
use self::source::Source;
|
||||
|
||||
/// The `solc --standard-json` output.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct Output {
|
||||
/// The file-contract hashmap.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub contracts: Option<BTreeMap<String, BTreeMap<String, Contract>>>,
|
||||
/// The source code mapping data.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub sources: Option<BTreeMap<String, Source>>,
|
||||
/// The compilation errors and warnings.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub errors: Option<Vec<SolcStandardJsonOutputError>>,
|
||||
/// The `solc` compiler version.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub version: Option<String>,
|
||||
/// The `solc` compiler long version.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub long_version: Option<String>,
|
||||
/// The `resolc` compiler version.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub revive_version: Option<String>,
|
||||
}
|
||||
|
||||
impl Output {
|
||||
/// Traverses the AST and returns the list of additional errors and warnings.
|
||||
#[cfg(feature = "resolc")]
|
||||
pub fn preprocess_ast(&mut self, suppressed_warnings: &[Warning]) -> anyhow::Result<()> {
|
||||
let sources = match self.sources.as_ref() {
|
||||
Some(sources) => sources,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let mut messages = Vec::new();
|
||||
for (path, source) in sources.iter() {
|
||||
if let Some(ast) = source.ast.as_ref() {
|
||||
let mut polkavm_messages = Source::get_messages(ast, suppressed_warnings);
|
||||
for message in polkavm_messages.iter_mut() {
|
||||
message.push_contract_path(path.as_str());
|
||||
}
|
||||
messages.extend(polkavm_messages);
|
||||
}
|
||||
}
|
||||
self.errors = match self.errors.take() {
|
||||
Some(mut errors) => {
|
||||
errors.extend(messages);
|
||||
Some(errors)
|
||||
}
|
||||
None => Some(messages),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -3,7 +3,8 @@
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::solc::standard_json::output::error::Error as SolcStandardJsonOutputError;
|
||||
use crate::standard_json::output::error::Error as SolcStandardJsonOutputError;
|
||||
#[cfg(feature = "resolc")]
|
||||
use crate::warning::Warning;
|
||||
|
||||
/// The `solc --standard-json` output source.
|
||||
@@ -131,6 +132,7 @@ impl Source {
|
||||
}
|
||||
|
||||
/// Returns the list of messages for some specific parts of the AST.
|
||||
#[cfg(feature = "resolc")]
|
||||
pub fn get_messages(
|
||||
ast: &serde_json::Value,
|
||||
suppressed_warnings: &[Warning],
|
||||
@@ -194,7 +196,7 @@ impl Source {
|
||||
_ => None,
|
||||
},
|
||||
)
|
||||
.last()
|
||||
.next_back()
|
||||
.ok_or_else(|| anyhow::anyhow!("The last contract not found in the AST"))
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,22 @@
|
||||
//! The compiler warning.
|
||||
//! `resolc` custom compiler warnings.
|
||||
//!
|
||||
//! The revive compiler adds warnings only applicable when compilng
|
||||
//! to the revive stack on Polkadot to the output.
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
/// The compiler warning.
|
||||
// The `resolc` custom compiler warning.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Warning {
|
||||
/// The warning for eponymous feature.
|
||||
EcRecover,
|
||||
/// The warning for eponymous feature.
|
||||
SendTransfer,
|
||||
/// The warning for eponymous feature.
|
||||
ExtCodeSize,
|
||||
/// The warning for eponymous feature.
|
||||
TxOrigin,
|
||||
/// The warning for eponymous feature.
|
||||
BlockTimestamp,
|
||||
/// The warning for eponymous feature.
|
||||
BlockNumber,
|
||||
/// The warning for eponymous feature.
|
||||
BlockHash,
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ inkwell = { workspace = true }
|
||||
|
||||
revive-common = { workspace = true }
|
||||
revive-llvm-context = { workspace = true }
|
||||
revive-solc-json-interface = { workspace = true, features = ["resolc"] }
|
||||
|
||||
[target.'cfg(target_env = "musl")'.dependencies]
|
||||
mimalloc = { version = "*", default-features = false }
|
||||
|
||||
@@ -5,12 +5,11 @@ use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
use revive_solc_json_interface::CombinedJsonContract;
|
||||
use revive_solc_json_interface::SolcStandardJsonOutputContract;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::solc::combined_json::contract::Contract as CombinedJsonContract;
|
||||
use crate::solc::standard_json::output::contract::Contract as StandardJsonOutputContract;
|
||||
|
||||
/// The Solidity contract build.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Contract {
|
||||
@@ -131,7 +130,7 @@ impl Contract {
|
||||
/// Writes the contract text assembly and bytecode to the standard JSON.
|
||||
pub fn write_to_standard_json(
|
||||
self,
|
||||
standard_json_contract: &mut StandardJsonOutputContract,
|
||||
standard_json_contract: &mut SolcStandardJsonOutputContract,
|
||||
) -> anyhow::Result<()> {
|
||||
standard_json_contract.metadata = Some(self.metadata_json);
|
||||
|
||||
|
||||
@@ -5,8 +5,9 @@ pub mod contract;
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::solc::combined_json::CombinedJson;
|
||||
use crate::solc::standard_json::output::Output as StandardJsonOutput;
|
||||
use revive_solc_json_interface::combined_json::CombinedJson;
|
||||
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||
|
||||
use crate::solc::version::Version as SolcVersion;
|
||||
use crate::ResolcVersion;
|
||||
|
||||
@@ -66,7 +67,7 @@ impl Build {
|
||||
/// Writes all contracts assembly and bytecode to the standard JSON.
|
||||
pub fn write_to_standard_json(
|
||||
mut self,
|
||||
standard_json: &mut StandardJsonOutput,
|
||||
standard_json: &mut SolcStandardJsonOutput,
|
||||
solc_version: &SolcVersion,
|
||||
) -> anyhow::Result<()> {
|
||||
let contracts = match standard_json.contracts.as_mut() {
|
||||
|
||||
+58
-31
@@ -7,7 +7,6 @@ pub(crate) mod process;
|
||||
pub(crate) mod project;
|
||||
pub(crate) mod solc;
|
||||
pub(crate) mod version;
|
||||
pub(crate) mod warning;
|
||||
pub(crate) mod yul;
|
||||
|
||||
pub use self::build::contract::Contract as ContractBuild;
|
||||
@@ -23,29 +22,16 @@ pub use self::process::Process;
|
||||
pub use self::project::contract::Contract as ProjectContract;
|
||||
pub use self::project::Project;
|
||||
pub use self::r#const::*;
|
||||
pub use self::solc::combined_json::contract::Contract as SolcCombinedJsonContract;
|
||||
pub use self::solc::combined_json::CombinedJson as SolcCombinedJson;
|
||||
#[cfg(not(target_os = "emscripten"))]
|
||||
pub use self::solc::solc_compiler::SolcCompiler;
|
||||
#[cfg(target_os = "emscripten")]
|
||||
pub use self::solc::soljson_compiler::SoljsonCompiler;
|
||||
pub use self::solc::standard_json::input::language::Language as SolcStandardJsonInputLanguage;
|
||||
pub use self::solc::standard_json::input::settings::metadata::Metadata as SolcStandardJsonInputSettingsMetadata;
|
||||
pub use self::solc::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
||||
pub use self::solc::standard_json::input::settings::selection::file::flag::Flag as SolcStandardJsonInputSettingsSelectionFileFlag;
|
||||
pub use self::solc::standard_json::input::settings::selection::file::File as SolcStandardJsonInputSettingsSelectionFile;
|
||||
pub use self::solc::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
|
||||
pub use self::solc::standard_json::input::settings::Settings as SolcStandardJsonInputSettings;
|
||||
pub use self::solc::standard_json::input::source::Source as SolcStandardJsonInputSource;
|
||||
pub use self::solc::standard_json::input::Input as SolcStandardJsonInput;
|
||||
pub use self::solc::standard_json::output::contract::evm::bytecode::Bytecode as SolcStandardJsonOutputContractEVMBytecode;
|
||||
pub use self::solc::standard_json::output::contract::evm::EVM as SolcStandardJsonOutputContractEVM;
|
||||
pub use self::solc::standard_json::output::contract::Contract as SolcStandardJsonOutputContract;
|
||||
pub use self::solc::standard_json::output::Output as SolcStandardJsonOutput;
|
||||
pub use self::solc::version::Version as SolcVersion;
|
||||
pub use self::solc::Compiler;
|
||||
pub use self::solc::FIRST_SUPPORTED_VERSION as SolcFirstSupportedVersion;
|
||||
pub use self::solc::LAST_SUPPORTED_VERSION as SolcLastSupportedVersion;
|
||||
pub use self::version::Version as ResolcVersion;
|
||||
pub use self::warning::Warning;
|
||||
|
||||
#[cfg(not(target_os = "emscripten"))]
|
||||
pub mod test_utils;
|
||||
pub mod tests;
|
||||
@@ -54,6 +40,13 @@ use std::collections::BTreeSet;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use revive_solc_json_interface::standard_json::input::settings::metadata_hash::MetadataHash;
|
||||
use revive_solc_json_interface::ResolcWarning;
|
||||
use revive_solc_json_interface::SolcStandardJsonInput;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputLanguage;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsOptimizer;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsSelection;
|
||||
|
||||
/// Runs the Yul mode.
|
||||
pub fn yul<T: Compiler>(
|
||||
input_files: &[PathBuf],
|
||||
@@ -61,6 +54,7 @@ pub fn yul<T: Compiler>(
|
||||
optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
include_metadata_hash: bool,
|
||||
debug_config: revive_llvm_context::DebugConfig,
|
||||
llvm_arguments: &[String],
|
||||
) -> anyhow::Result<Build> {
|
||||
let path = match input_files.len() {
|
||||
1 => input_files.first().expect("Always exists"),
|
||||
@@ -81,7 +75,12 @@ pub fn yul<T: Compiler>(
|
||||
let solc_validator = Some(&*solc);
|
||||
let project = Project::try_from_yul_path(path, solc_validator)?;
|
||||
|
||||
let build = project.compile(optimizer_settings, include_metadata_hash, debug_config)?;
|
||||
let build = project.compile(
|
||||
optimizer_settings,
|
||||
include_metadata_hash,
|
||||
debug_config,
|
||||
llvm_arguments,
|
||||
)?;
|
||||
|
||||
Ok(build)
|
||||
}
|
||||
@@ -92,6 +91,7 @@ pub fn llvm_ir(
|
||||
optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
include_metadata_hash: bool,
|
||||
debug_config: revive_llvm_context::DebugConfig,
|
||||
llvm_arguments: &[String],
|
||||
) -> anyhow::Result<Build> {
|
||||
let path = match input_files.len() {
|
||||
1 => input_files.first().expect("Always exists"),
|
||||
@@ -104,7 +104,12 @@ pub fn llvm_ir(
|
||||
|
||||
let project = Project::try_from_llvm_ir_path(path)?;
|
||||
|
||||
let build = project.compile(optimizer_settings, include_metadata_hash, debug_config)?;
|
||||
let build = project.compile(
|
||||
optimizer_settings,
|
||||
include_metadata_hash,
|
||||
debug_config,
|
||||
llvm_arguments,
|
||||
)?;
|
||||
|
||||
Ok(build)
|
||||
}
|
||||
@@ -123,8 +128,9 @@ pub fn standard_output<T: Compiler>(
|
||||
include_paths: Vec<String>,
|
||||
allow_paths: Option<String>,
|
||||
remappings: Option<BTreeSet<String>>,
|
||||
suppressed_warnings: Option<Vec<Warning>>,
|
||||
suppressed_warnings: Option<Vec<ResolcWarning>>,
|
||||
debug_config: revive_llvm_context::DebugConfig,
|
||||
llvm_arguments: &[String],
|
||||
) -> anyhow::Result<Build> {
|
||||
let solc_version = solc.version()?;
|
||||
|
||||
@@ -152,7 +158,7 @@ pub fn standard_output<T: Compiler>(
|
||||
.collect();
|
||||
|
||||
let libraries = solc_input.settings.libraries.clone().unwrap_or_default();
|
||||
let mut solc_output = solc.standard_json(solc_input, base_path, include_paths, allow_paths)?;
|
||||
let solc_output = solc.standard_json(solc_input, base_path, include_paths, allow_paths)?;
|
||||
|
||||
if let Some(errors) = solc_output.errors.as_deref() {
|
||||
let mut has_errors = false;
|
||||
@@ -170,10 +176,20 @@ pub fn standard_output<T: Compiler>(
|
||||
}
|
||||
}
|
||||
|
||||
let project =
|
||||
solc_output.try_to_project(source_code_files, libraries, &solc_version, &debug_config)?;
|
||||
let project = Project::try_from_standard_json_output(
|
||||
&solc_output,
|
||||
source_code_files,
|
||||
libraries,
|
||||
&solc_version,
|
||||
&debug_config,
|
||||
)?;
|
||||
|
||||
let build = project.compile(optimizer_settings, include_metadata_hash, debug_config)?;
|
||||
let build = project.compile(
|
||||
optimizer_settings,
|
||||
include_metadata_hash,
|
||||
debug_config,
|
||||
llvm_arguments,
|
||||
)?;
|
||||
|
||||
Ok(build)
|
||||
}
|
||||
@@ -186,6 +202,7 @@ pub fn standard_json<T: Compiler>(
|
||||
include_paths: Vec<String>,
|
||||
allow_paths: Option<String>,
|
||||
debug_config: revive_llvm_context::DebugConfig,
|
||||
llvm_arguments: &[String],
|
||||
) -> anyhow::Result<()> {
|
||||
let solc_version = solc.version()?;
|
||||
|
||||
@@ -200,9 +217,7 @@ pub fn standard_json<T: Compiler>(
|
||||
revive_llvm_context::OptimizerSettings::try_from(&solc_input.settings.optimizer)?;
|
||||
|
||||
let include_metadata_hash = match solc_input.settings.metadata {
|
||||
Some(ref metadata) => {
|
||||
metadata.bytecode_hash != Some(revive_llvm_context::PolkaVMMetadataHash::None)
|
||||
}
|
||||
Some(ref metadata) => metadata.bytecode_hash != Some(MetadataHash::None),
|
||||
None => true,
|
||||
};
|
||||
|
||||
@@ -218,14 +233,24 @@ pub fn standard_json<T: Compiler>(
|
||||
}
|
||||
}
|
||||
|
||||
let project =
|
||||
solc_output.try_to_project(source_code_files, libraries, &solc_version, &debug_config)?;
|
||||
let project = Project::try_from_standard_json_output(
|
||||
&solc_output,
|
||||
source_code_files,
|
||||
libraries,
|
||||
&solc_version,
|
||||
&debug_config,
|
||||
)?;
|
||||
|
||||
if detect_missing_libraries {
|
||||
let missing_libraries = project.get_missing_libraries();
|
||||
missing_libraries.write_to_standard_json(&mut solc_output, &solc_version)?;
|
||||
} else {
|
||||
let build = project.compile(optimizer_settings, include_metadata_hash, debug_config)?;
|
||||
let build = project.compile(
|
||||
optimizer_settings,
|
||||
include_metadata_hash,
|
||||
debug_config,
|
||||
llvm_arguments,
|
||||
)?;
|
||||
build.write_to_standard_json(&mut solc_output, &solc_version)?;
|
||||
}
|
||||
serde_json::to_writer(std::io::stdout(), &solc_output)?;
|
||||
@@ -247,10 +272,11 @@ pub fn combined_json<T: Compiler>(
|
||||
include_paths: Vec<String>,
|
||||
allow_paths: Option<String>,
|
||||
remappings: Option<BTreeSet<String>>,
|
||||
suppressed_warnings: Option<Vec<Warning>>,
|
||||
suppressed_warnings: Option<Vec<ResolcWarning>>,
|
||||
debug_config: revive_llvm_context::DebugConfig,
|
||||
output_directory: Option<PathBuf>,
|
||||
overwrite: bool,
|
||||
llvm_arguments: &[String],
|
||||
) -> anyhow::Result<()> {
|
||||
let build = standard_output(
|
||||
input_files,
|
||||
@@ -266,6 +292,7 @@ pub fn combined_json<T: Compiler>(
|
||||
remappings,
|
||||
suppressed_warnings,
|
||||
debug_config,
|
||||
llvm_arguments,
|
||||
)?;
|
||||
|
||||
let mut combined_json = solc.combined_json(input_files, format.as_str())?;
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use crate::solc::standard_json::output::Output as StandardJsonOutput;
|
||||
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||
|
||||
use crate::solc::version::Version as SolcVersion;
|
||||
use crate::ResolcVersion;
|
||||
|
||||
@@ -22,7 +23,7 @@ impl MissingLibraries {
|
||||
/// Writes the missing libraries to the standard JSON.
|
||||
pub fn write_to_standard_json(
|
||||
mut self,
|
||||
standard_json: &mut StandardJsonOutput,
|
||||
standard_json: &mut SolcStandardJsonOutput,
|
||||
solc_version: &SolcVersion,
|
||||
) -> anyhow::Result<()> {
|
||||
let contracts = match standard_json.contracts.as_mut() {
|
||||
|
||||
@@ -20,6 +20,8 @@ pub struct Input {
|
||||
pub optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
/// The debug output config.
|
||||
pub debug_config: revive_llvm_context::DebugConfig,
|
||||
/// The extra LLVM arguments give used for manual control.
|
||||
pub llvm_arguments: Vec<String>,
|
||||
}
|
||||
|
||||
impl Input {
|
||||
@@ -30,6 +32,7 @@ impl Input {
|
||||
include_metadata_hash: bool,
|
||||
optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
debug_config: revive_llvm_context::DebugConfig,
|
||||
llvm_arguments: Vec<String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
contract,
|
||||
@@ -37,6 +40,7 @@ impl Input {
|
||||
include_metadata_hash,
|
||||
optimizer_settings,
|
||||
debug_config,
|
||||
llvm_arguments,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,11 +37,19 @@ pub trait Process {
|
||||
}
|
||||
|
||||
let input: Input = revive_common::deserialize_from_slice(buffer.as_slice())?;
|
||||
|
||||
revive_llvm_context::initialize_llvm(
|
||||
revive_llvm_context::Target::PVM,
|
||||
crate::DEFAULT_EXECUTABLE_NAME,
|
||||
&input.llvm_arguments,
|
||||
);
|
||||
|
||||
let result = input.contract.compile(
|
||||
input.project,
|
||||
input.optimizer_settings,
|
||||
input.include_metadata_hash,
|
||||
input.debug_config,
|
||||
&input.llvm_arguments,
|
||||
);
|
||||
|
||||
match result {
|
||||
|
||||
@@ -18,6 +18,8 @@ pub struct Metadata {
|
||||
pub revive_version: String,
|
||||
/// The PolkaVM compiler optimizer settings.
|
||||
pub optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
/// The extra LLVM arguments give used for manual control.
|
||||
pub llvm_arguments: Vec<String>,
|
||||
}
|
||||
|
||||
impl Metadata {
|
||||
@@ -27,6 +29,7 @@ impl Metadata {
|
||||
solc_version: String,
|
||||
revive_pallet_version: Option<semver::Version>,
|
||||
optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
llvm_arguments: Vec<String>,
|
||||
) -> Self {
|
||||
Self {
|
||||
solc_metadata,
|
||||
@@ -34,6 +37,7 @@ impl Metadata {
|
||||
revive_pallet_version,
|
||||
revive_version: ResolcVersion::default().long,
|
||||
optimizer_settings,
|
||||
llvm_arguments,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ impl Contract {
|
||||
optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
include_metadata_hash: bool,
|
||||
debug_config: revive_llvm_context::DebugConfig,
|
||||
llvm_arguments: &[String],
|
||||
) -> anyhow::Result<ContractBuild> {
|
||||
let llvm = inkwell::context::Context::create();
|
||||
let optimizer = revive_llvm_context::Optimizer::new(optimizer_settings);
|
||||
@@ -89,6 +90,7 @@ impl Contract {
|
||||
version.long.clone(),
|
||||
version.l2_revision.clone(),
|
||||
optimizer.settings().to_owned(),
|
||||
llvm_arguments.to_vec(),
|
||||
);
|
||||
let metadata_json = serde_json::to_value(&metadata).expect("Always valid");
|
||||
let metadata_hash: Option<[u8; revive_common::BYTE_LENGTH_WORD]> = if include_metadata_hash
|
||||
@@ -120,6 +122,7 @@ impl Contract {
|
||||
Some(project),
|
||||
include_metadata_hash,
|
||||
debug_config,
|
||||
llvm_arguments,
|
||||
);
|
||||
context.set_solidity_data(revive_llvm_context::PolkaVMContextSolidityData::default());
|
||||
match self.ir {
|
||||
|
||||
@@ -9,6 +9,7 @@ use std::path::Path;
|
||||
|
||||
#[cfg(feature = "parallel")]
|
||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use sha3::Digest;
|
||||
@@ -65,6 +66,7 @@ impl Project {
|
||||
optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
include_metadata_hash: bool,
|
||||
debug_config: revive_llvm_context::DebugConfig,
|
||||
llvm_arguments: &[String],
|
||||
) -> anyhow::Result<Build> {
|
||||
let project = self.clone();
|
||||
#[cfg(feature = "parallel")]
|
||||
@@ -80,6 +82,7 @@ impl Project {
|
||||
include_metadata_hash,
|
||||
optimizer_settings.clone(),
|
||||
debug_config.clone(),
|
||||
llvm_arguments.to_vec(),
|
||||
);
|
||||
let process_output = {
|
||||
#[cfg(target_os = "emscripten")]
|
||||
@@ -243,6 +246,69 @@ impl Project {
|
||||
BTreeMap::new(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Converts the `solc` JSON output into a convenient project.
|
||||
pub fn try_from_standard_json_output(
|
||||
output: &SolcStandardJsonOutput,
|
||||
source_code_files: BTreeMap<String, String>,
|
||||
libraries: BTreeMap<String, BTreeMap<String, String>>,
|
||||
solc_version: &SolcVersion,
|
||||
debug_config: &revive_llvm_context::DebugConfig,
|
||||
) -> anyhow::Result<Self> {
|
||||
let files = match output.contracts.as_ref() {
|
||||
Some(files) => files,
|
||||
None => match &output.errors {
|
||||
Some(errors) if errors.iter().any(|e| e.severity == "error") => {
|
||||
anyhow::bail!(serde_json::to_string_pretty(errors).expect("Always valid"));
|
||||
}
|
||||
_ => &BTreeMap::new(),
|
||||
},
|
||||
};
|
||||
let mut project_contracts = BTreeMap::new();
|
||||
|
||||
for (path, contracts) in files.iter() {
|
||||
for (name, contract) in contracts.iter() {
|
||||
let full_path = format!("{path}:{name}");
|
||||
|
||||
let ir_optimized = match contract.ir_optimized.to_owned() {
|
||||
Some(ir_optimized) => ir_optimized,
|
||||
None => continue,
|
||||
};
|
||||
if ir_optimized.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
debug_config.dump_yul(full_path.as_str(), ir_optimized.as_str())?;
|
||||
|
||||
let mut lexer = Lexer::new(ir_optimized.to_owned());
|
||||
let object = Object::parse(&mut lexer, None).map_err(|error| {
|
||||
anyhow::anyhow!("Contract `{}` parsing error: {:?}", full_path, error)
|
||||
})?;
|
||||
|
||||
let source = IR::new_yul(ir_optimized.to_owned(), object);
|
||||
|
||||
let source_code = source_code_files
|
||||
.get(path.as_str())
|
||||
.ok_or_else(|| anyhow::anyhow!("Source code for path `{}` not found", path))?;
|
||||
let source_hash = sha3::Keccak256::digest(source_code.as_bytes()).into();
|
||||
|
||||
let project_contract = Contract::new(
|
||||
full_path.clone(),
|
||||
source_hash,
|
||||
solc_version.to_owned(),
|
||||
source,
|
||||
contract.metadata.to_owned(),
|
||||
);
|
||||
project_contracts.insert(full_path, project_contract);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Project::new(
|
||||
solc_version.to_owned(),
|
||||
project_contracts,
|
||||
libraries,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl revive_llvm_context::PolkaVMDependency for Project {
|
||||
@@ -252,6 +318,7 @@ impl revive_llvm_context::PolkaVMDependency for Project {
|
||||
optimizer_settings: revive_llvm_context::OptimizerSettings,
|
||||
include_metadata_hash: bool,
|
||||
debug_config: revive_llvm_context::DebugConfig,
|
||||
llvm_arguments: &[String],
|
||||
) -> anyhow::Result<String> {
|
||||
let contract_path = project.resolve_path(identifier)?;
|
||||
let contract = project
|
||||
@@ -271,6 +338,7 @@ impl revive_llvm_context::PolkaVMDependency for Project {
|
||||
optimizer_settings,
|
||||
include_metadata_hash,
|
||||
debug_config,
|
||||
llvm_arguments,
|
||||
)
|
||||
.map_err(|error| {
|
||||
anyhow::anyhow!(
|
||||
|
||||
@@ -19,6 +19,10 @@ pub struct Arguments {
|
||||
#[arg(long = "version")]
|
||||
pub version: bool,
|
||||
|
||||
/// Print supported `solc` versions and exit.
|
||||
#[arg(long = "supported-solc-versions")]
|
||||
pub supported_solc_versions: bool,
|
||||
|
||||
/// Print the licence and exit.
|
||||
#[arg(long = "license")]
|
||||
pub license: bool,
|
||||
@@ -162,6 +166,10 @@ pub struct Arguments {
|
||||
#[cfg(debug_assertions)]
|
||||
#[arg(long = "recursive-process-input")]
|
||||
pub recursive_process_input: Option<String>,
|
||||
|
||||
#[arg(long = "llvm-arg")]
|
||||
/// These are passed to LLVM as the command line to allow manual control.
|
||||
pub llvm_arguments: Vec<String>,
|
||||
}
|
||||
|
||||
impl Arguments {
|
||||
@@ -171,6 +179,12 @@ impl Arguments {
|
||||
anyhow::bail!("No other options are allowed while getting the compiler version.");
|
||||
}
|
||||
|
||||
if self.supported_solc_versions && std::env::args().count() > 2 {
|
||||
anyhow::bail!(
|
||||
"No other options are allowed while getting the supported `solc` versions."
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
if self.recursive_process_input.is_some() && !self.recursive_process {
|
||||
anyhow::bail!("--process-input can be only used when --recursive-process is given");
|
||||
|
||||
@@ -41,6 +41,16 @@ fn main_inner() -> anyhow::Result<()> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if arguments.supported_solc_versions {
|
||||
writeln!(
|
||||
std::io::stdout(),
|
||||
">={},<={}",
|
||||
revive_solidity::SolcFirstSupportedVersion,
|
||||
revive_solidity::SolcLastSupportedVersion,
|
||||
)?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if arguments.license {
|
||||
let license_mit = include_str!("../../../../LICENSE-MIT");
|
||||
let license_apache = include_str!("../../../../LICENSE-APACHE");
|
||||
@@ -54,8 +64,6 @@ fn main_inner() -> anyhow::Result<()> {
|
||||
.stack_size(RAYON_WORKER_STACK_SIZE)
|
||||
.build_global()
|
||||
.expect("Thread pool configuration failure");
|
||||
inkwell::support::enable_llvm_pretty_stack_trace();
|
||||
revive_llvm_context::initialize_target(revive_llvm_context::Target::PVM); // TODO: pass from CLI
|
||||
|
||||
if arguments.recursive_process {
|
||||
#[cfg(debug_assertions)]
|
||||
@@ -94,7 +102,7 @@ fn main_inner() -> anyhow::Result<()> {
|
||||
let (input_files, remappings) = arguments.split_input_files_and_remappings()?;
|
||||
|
||||
let suppressed_warnings = match arguments.suppress_warnings {
|
||||
Some(warnings) => Some(revive_solidity::Warning::try_from_strings(
|
||||
Some(warnings) => Some(revive_solc_json_interface::ResolcWarning::try_from_strings(
|
||||
warnings.as_slice(),
|
||||
)?),
|
||||
None => None,
|
||||
@@ -132,8 +140,10 @@ fn main_inner() -> anyhow::Result<()> {
|
||||
let include_metadata_hash = match arguments.metadata_hash {
|
||||
Some(metadata_hash) => {
|
||||
let metadata =
|
||||
revive_llvm_context::PolkaVMMetadataHash::from_str(metadata_hash.as_str())?;
|
||||
metadata != revive_llvm_context::PolkaVMMetadataHash::None
|
||||
revive_solc_json_interface::SolcStandardJsonInputSettingsMetadataHash::from_str(
|
||||
metadata_hash.as_str(),
|
||||
)?;
|
||||
metadata != revive_solc_json_interface::SolcStandardJsonInputSettingsMetadataHash::None
|
||||
}
|
||||
None => true,
|
||||
};
|
||||
@@ -145,6 +155,7 @@ fn main_inner() -> anyhow::Result<()> {
|
||||
optimizer_settings,
|
||||
include_metadata_hash,
|
||||
debug_config,
|
||||
&arguments.llvm_arguments,
|
||||
)
|
||||
} else if arguments.llvm_ir {
|
||||
revive_solidity::llvm_ir(
|
||||
@@ -152,6 +163,7 @@ fn main_inner() -> anyhow::Result<()> {
|
||||
optimizer_settings,
|
||||
include_metadata_hash,
|
||||
debug_config,
|
||||
&arguments.llvm_arguments,
|
||||
)
|
||||
} else if arguments.standard_json {
|
||||
revive_solidity::standard_json(
|
||||
@@ -161,6 +173,7 @@ fn main_inner() -> anyhow::Result<()> {
|
||||
arguments.include_paths,
|
||||
arguments.allow_paths,
|
||||
debug_config,
|
||||
&arguments.llvm_arguments,
|
||||
)?;
|
||||
return Ok(());
|
||||
} else if let Some(format) = arguments.combined_json {
|
||||
@@ -181,6 +194,7 @@ fn main_inner() -> anyhow::Result<()> {
|
||||
debug_config,
|
||||
arguments.output_directory,
|
||||
arguments.overwrite,
|
||||
&arguments.llvm_arguments,
|
||||
)?;
|
||||
return Ok(());
|
||||
} else {
|
||||
@@ -198,6 +212,7 @@ fn main_inner() -> anyhow::Result<()> {
|
||||
remappings,
|
||||
suppressed_warnings,
|
||||
debug_config,
|
||||
&arguments.llvm_arguments,
|
||||
)
|
||||
}?;
|
||||
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
//! The Solidity compiler.
|
||||
|
||||
pub mod combined_json;
|
||||
#[cfg(not(target_os = "emscripten"))]
|
||||
pub mod solc_compiler;
|
||||
#[cfg(target_os = "emscripten")]
|
||||
pub mod soljson_compiler;
|
||||
pub mod standard_json;
|
||||
pub mod version;
|
||||
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use self::combined_json::CombinedJson;
|
||||
use self::standard_json::input::Input as StandardJsonInput;
|
||||
use self::standard_json::output::Output as StandardJsonOutput;
|
||||
use revive_solc_json_interface::combined_json::CombinedJson;
|
||||
use revive_solc_json_interface::SolcStandardJsonInput;
|
||||
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||
|
||||
use self::version::Version;
|
||||
|
||||
/// The first version of `solc` with the support of standard JSON interface.
|
||||
pub const FIRST_SUPPORTED_VERSION: semver::Version = semver::Version::new(0, 8, 0);
|
||||
|
||||
/// The last supported version of `solc`.
|
||||
pub const LAST_SUPPORTED_VERSION: semver::Version = semver::Version::new(0, 8, 28);
|
||||
pub const LAST_SUPPORTED_VERSION: semver::Version = semver::Version::new(0, 8, 29);
|
||||
|
||||
/// `--include-path` was introduced in solc `0.8.8` <https://github.com/ethereum/solidity/releases/tag/v0.8.8>
|
||||
pub const FIRST_INCLUDE_PATH_VERSION: semver::Version = semver::Version::new(0, 8, 8);
|
||||
@@ -30,11 +29,11 @@ pub trait Compiler {
|
||||
/// Compiles the Solidity `--standard-json` input into Yul IR.
|
||||
fn standard_json(
|
||||
&mut self,
|
||||
input: StandardJsonInput,
|
||||
input: SolcStandardJsonInput,
|
||||
base_path: Option<String>,
|
||||
include_paths: Vec<String>,
|
||||
allow_paths: Option<String>,
|
||||
) -> anyhow::Result<StandardJsonOutput>;
|
||||
) -> anyhow::Result<SolcStandardJsonOutput>;
|
||||
|
||||
/// The `solc --combined-json abi,hashes...` mirror.
|
||||
fn combined_json(
|
||||
|
||||
@@ -4,9 +4,10 @@ use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::solc::combined_json::CombinedJson;
|
||||
use crate::solc::standard_json::input::Input as StandardJsonInput;
|
||||
use crate::solc::standard_json::output::Output as StandardJsonOutput;
|
||||
use revive_solc_json_interface::combined_json::CombinedJson;
|
||||
use revive_solc_json_interface::SolcStandardJsonInput;
|
||||
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||
|
||||
use crate::solc::version::Version;
|
||||
|
||||
use super::Compiler;
|
||||
@@ -39,11 +40,11 @@ impl Compiler for SolcCompiler {
|
||||
/// Compiles the Solidity `--standard-json` input into Yul IR.
|
||||
fn standard_json(
|
||||
&mut self,
|
||||
mut input: StandardJsonInput,
|
||||
mut input: SolcStandardJsonInput,
|
||||
base_path: Option<String>,
|
||||
include_paths: Vec<String>,
|
||||
allow_paths: Option<String>,
|
||||
) -> anyhow::Result<StandardJsonOutput> {
|
||||
) -> anyhow::Result<SolcStandardJsonOutput> {
|
||||
let version = self.version()?.validate(&include_paths)?.default;
|
||||
|
||||
let mut command = std::process::Command::new(self.executable.as_str());
|
||||
@@ -93,7 +94,7 @@ impl Compiler for SolcCompiler {
|
||||
);
|
||||
}
|
||||
|
||||
let mut output: StandardJsonOutput =
|
||||
let mut output: SolcStandardJsonOutput =
|
||||
revive_common::deserialize_from_slice(output.stdout.as_slice()).map_err(|error| {
|
||||
anyhow::anyhow!(
|
||||
"{} subprocess output parsing error: {}\n{}",
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::solc::combined_json::CombinedJson;
|
||||
use crate::solc::standard_json::input::Input as StandardJsonInput;
|
||||
use crate::solc::standard_json::output::Output as StandardJsonOutput;
|
||||
use revive_solc_json_interface::combined_json::CombinedJson;
|
||||
use revive_solc_json_interface::SolcStandardJsonInput;
|
||||
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||
|
||||
use crate::solc::version::Version;
|
||||
use anyhow::Context;
|
||||
use std::ffi::{c_char, c_void, CStr, CString};
|
||||
@@ -24,11 +25,11 @@ impl Compiler for SoljsonCompiler {
|
||||
/// Compiles the Solidity `--standard-json` input into Yul IR.
|
||||
fn standard_json(
|
||||
&mut self,
|
||||
mut input: StandardJsonInput,
|
||||
mut input: SolcStandardJsonInput,
|
||||
base_path: Option<String>,
|
||||
include_paths: Vec<String>,
|
||||
allow_paths: Option<String>,
|
||||
) -> anyhow::Result<StandardJsonOutput> {
|
||||
) -> anyhow::Result<SolcStandardJsonOutput> {
|
||||
if !include_paths.is_empty() {
|
||||
anyhow::bail!("configuring include paths is not supported with solJson")
|
||||
}
|
||||
@@ -46,8 +47,8 @@ impl Compiler for SoljsonCompiler {
|
||||
|
||||
let input_json = serde_json::to_string(&input).expect("Always valid");
|
||||
let out = Self::compile_standard_json(input_json)?;
|
||||
let mut output: StandardJsonOutput = revive_common::deserialize_from_slice(out.as_bytes())
|
||||
.map_err(|error| {
|
||||
let mut output: SolcStandardJsonOutput =
|
||||
revive_common::deserialize_from_slice(out.as_bytes()).map_err(|error| {
|
||||
anyhow::anyhow!(
|
||||
"Soljson output parsing error: {}\n{}",
|
||||
error,
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
//! The `solc <input>.sol --standard-json`.
|
||||
|
||||
pub mod input;
|
||||
pub mod output;
|
||||
@@ -1,138 +0,0 @@
|
||||
//! The `solc --standard-json` output.
|
||||
|
||||
pub mod contract;
|
||||
pub mod error;
|
||||
pub mod source;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use sha3::Digest;
|
||||
|
||||
use crate::project::contract::ir::IR as ProjectContractIR;
|
||||
use crate::project::contract::Contract as ProjectContract;
|
||||
use crate::project::Project;
|
||||
use crate::solc::version::Version as SolcVersion;
|
||||
use crate::warning::Warning;
|
||||
use crate::yul::lexer::Lexer;
|
||||
use crate::yul::parser::statement::object::Object;
|
||||
|
||||
use self::contract::Contract;
|
||||
use self::error::Error as SolcStandardJsonOutputError;
|
||||
use self::source::Source;
|
||||
/// The `solc --standard-json` output.
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct Output {
|
||||
/// The file-contract hashmap.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub contracts: Option<BTreeMap<String, BTreeMap<String, Contract>>>,
|
||||
/// The source code mapping data.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub sources: Option<BTreeMap<String, Source>>,
|
||||
/// The compilation errors and warnings.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub errors: Option<Vec<SolcStandardJsonOutputError>>,
|
||||
/// The `solc` compiler version.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub version: Option<String>,
|
||||
/// The `solc` compiler long version.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub long_version: Option<String>,
|
||||
/// The `resolc` compiler version.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub revive_version: Option<String>,
|
||||
}
|
||||
|
||||
impl Output {
|
||||
/// Converts the `solc` JSON output into a convenient project.
|
||||
pub fn try_to_project(
|
||||
&mut self,
|
||||
source_code_files: BTreeMap<String, String>,
|
||||
libraries: BTreeMap<String, BTreeMap<String, String>>,
|
||||
solc_version: &SolcVersion,
|
||||
debug_config: &revive_llvm_context::DebugConfig,
|
||||
) -> anyhow::Result<Project> {
|
||||
let files = match self.contracts.as_ref() {
|
||||
Some(files) => files,
|
||||
None => match &self.errors {
|
||||
Some(errors) if errors.iter().any(|e| e.severity == "error") => {
|
||||
anyhow::bail!(serde_json::to_string_pretty(errors).expect("Always valid"));
|
||||
}
|
||||
_ => &BTreeMap::new(),
|
||||
},
|
||||
};
|
||||
let mut project_contracts = BTreeMap::new();
|
||||
|
||||
for (path, contracts) in files.iter() {
|
||||
for (name, contract) in contracts.iter() {
|
||||
let full_path = format!("{path}:{name}");
|
||||
|
||||
let ir_optimized = match contract.ir_optimized.to_owned() {
|
||||
Some(ir_optimized) => ir_optimized,
|
||||
None => continue,
|
||||
};
|
||||
if ir_optimized.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
debug_config.dump_yul(full_path.as_str(), ir_optimized.as_str())?;
|
||||
|
||||
let mut lexer = Lexer::new(ir_optimized.to_owned());
|
||||
let object = Object::parse(&mut lexer, None).map_err(|error| {
|
||||
anyhow::anyhow!("Contract `{}` parsing error: {:?}", full_path, error)
|
||||
})?;
|
||||
|
||||
let source = ProjectContractIR::new_yul(ir_optimized.to_owned(), object);
|
||||
|
||||
let source_code = source_code_files
|
||||
.get(path.as_str())
|
||||
.ok_or_else(|| anyhow::anyhow!("Source code for path `{}` not found", path))?;
|
||||
let source_hash = sha3::Keccak256::digest(source_code.as_bytes()).into();
|
||||
|
||||
let project_contract = ProjectContract::new(
|
||||
full_path.clone(),
|
||||
source_hash,
|
||||
solc_version.to_owned(),
|
||||
source,
|
||||
contract.metadata.to_owned(),
|
||||
);
|
||||
project_contracts.insert(full_path, project_contract);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Project::new(
|
||||
solc_version.to_owned(),
|
||||
project_contracts,
|
||||
libraries,
|
||||
))
|
||||
}
|
||||
|
||||
/// Traverses the AST and returns the list of additional errors and warnings.
|
||||
pub fn preprocess_ast(&mut self, suppressed_warnings: &[Warning]) -> anyhow::Result<()> {
|
||||
let sources = match self.sources.as_ref() {
|
||||
Some(sources) => sources,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let mut messages = Vec::new();
|
||||
for (path, source) in sources.iter() {
|
||||
if let Some(ast) = source.ast.as_ref() {
|
||||
let mut polkavm_messages = Source::get_messages(ast, suppressed_warnings);
|
||||
for message in polkavm_messages.iter_mut() {
|
||||
message.push_contract_path(path.as_str());
|
||||
}
|
||||
messages.extend(polkavm_messages);
|
||||
}
|
||||
}
|
||||
self.errors = match self.errors.take() {
|
||||
Some(mut errors) => {
|
||||
errors.extend(messages);
|
||||
Some(errors)
|
||||
}
|
||||
None => Some(messages),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -7,17 +7,17 @@ use std::sync::Mutex;
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use revive_llvm_context::OptimizerSettings;
|
||||
use revive_solc_json_interface::standard_json::output::contract::evm::bytecode::Bytecode;
|
||||
use revive_solc_json_interface::standard_json::output::contract::evm::bytecode::DeployedBytecode;
|
||||
use revive_solc_json_interface::warning::Warning;
|
||||
use revive_solc_json_interface::SolcStandardJsonInput;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsOptimizer;
|
||||
use revive_solc_json_interface::SolcStandardJsonInputSettingsSelection;
|
||||
use revive_solc_json_interface::SolcStandardJsonOutput;
|
||||
|
||||
use crate::project::Project;
|
||||
use crate::solc::solc_compiler::SolcCompiler;
|
||||
use crate::solc::standard_json::input::settings::optimizer::Optimizer as SolcStandardJsonInputSettingsOptimizer;
|
||||
use crate::solc::standard_json::input::settings::selection::Selection as SolcStandardJsonInputSettingsSelection;
|
||||
use crate::solc::standard_json::input::Input as SolcStandardJsonInput;
|
||||
use crate::solc::standard_json::output::contract::evm::bytecode::Bytecode;
|
||||
use crate::solc::standard_json::output::contract::evm::bytecode::DeployedBytecode;
|
||||
use crate::solc::standard_json::output::Output as SolcStandardJsonOutput;
|
||||
use crate::solc::Compiler;
|
||||
use crate::warning::Warning;
|
||||
|
||||
static PVM_BLOB_CACHE: Lazy<Mutex<HashMap<CachedBlob, Vec<u8>>>> = Lazy::new(Default::default);
|
||||
static EVM_BLOB_CACHE: Lazy<Mutex<HashMap<CachedBlob, Vec<u8>>>> = Lazy::new(Default::default);
|
||||
@@ -73,7 +73,11 @@ pub fn build_solidity_with_options(
|
||||
check_dependencies();
|
||||
|
||||
inkwell::support::enable_llvm_pretty_stack_trace();
|
||||
revive_llvm_context::initialize_target(revive_llvm_context::Target::PVM);
|
||||
revive_llvm_context::initialize_llvm(
|
||||
revive_llvm_context::Target::PVM,
|
||||
crate::DEFAULT_EXECUTABLE_NAME,
|
||||
&[],
|
||||
);
|
||||
let _ = crate::process::native_process::EXECUTABLE
|
||||
.set(PathBuf::from(crate::r#const::DEFAULT_EXECUTABLE_NAME));
|
||||
|
||||
@@ -98,9 +102,16 @@ pub fn build_solidity_with_options(
|
||||
|
||||
let mut output = solc.standard_json(input, None, vec![], None)?;
|
||||
|
||||
let project = output.try_to_project(sources, libraries, &solc_version, &DEBUG_CONFIG)?;
|
||||
let project = Project::try_from_standard_json_output(
|
||||
&output,
|
||||
sources,
|
||||
libraries,
|
||||
&solc_version,
|
||||
&DEBUG_CONFIG,
|
||||
)?;
|
||||
|
||||
let build: crate::Build = project.compile(optimizer_settings, false, DEBUG_CONFIG)?;
|
||||
let build: crate::Build =
|
||||
project.compile(optimizer_settings, false, DEBUG_CONFIG, Default::default())?;
|
||||
build.write_to_standard_json(&mut output, &solc_version)?;
|
||||
|
||||
Ok(output)
|
||||
@@ -116,7 +127,11 @@ pub fn build_solidity_with_options_evm(
|
||||
check_dependencies();
|
||||
|
||||
inkwell::support::enable_llvm_pretty_stack_trace();
|
||||
revive_llvm_context::initialize_target(revive_llvm_context::Target::PVM);
|
||||
revive_llvm_context::initialize_llvm(
|
||||
revive_llvm_context::Target::PVM,
|
||||
crate::DEFAULT_EXECUTABLE_NAME,
|
||||
&[],
|
||||
);
|
||||
let _ = crate::process::native_process::EXECUTABLE
|
||||
.set(PathBuf::from(crate::r#const::DEFAULT_EXECUTABLE_NAME));
|
||||
|
||||
@@ -168,7 +183,11 @@ pub fn build_solidity_and_detect_missing_libraries(
|
||||
check_dependencies();
|
||||
|
||||
inkwell::support::enable_llvm_pretty_stack_trace();
|
||||
revive_llvm_context::initialize_target(revive_llvm_context::Target::PVM);
|
||||
revive_llvm_context::initialize_llvm(
|
||||
revive_llvm_context::Target::PVM,
|
||||
crate::DEFAULT_EXECUTABLE_NAME,
|
||||
&[],
|
||||
);
|
||||
let _ = crate::process::native_process::EXECUTABLE
|
||||
.set(PathBuf::from(crate::r#const::DEFAULT_EXECUTABLE_NAME));
|
||||
|
||||
@@ -188,7 +207,13 @@ pub fn build_solidity_and_detect_missing_libraries(
|
||||
|
||||
let mut output = solc.standard_json(input, None, vec![], None)?;
|
||||
|
||||
let project = output.try_to_project(sources, libraries, &solc_version, &DEBUG_CONFIG)?;
|
||||
let project = Project::try_from_standard_json_output(
|
||||
&output,
|
||||
sources,
|
||||
libraries,
|
||||
&solc_version,
|
||||
&DEBUG_CONFIG,
|
||||
)?;
|
||||
|
||||
let missing_libraries = project.get_missing_libraries();
|
||||
missing_libraries.write_to_standard_json(&mut output, &solc.version()?)?;
|
||||
@@ -201,7 +226,11 @@ pub fn build_yul(source_code: &str) -> anyhow::Result<()> {
|
||||
check_dependencies();
|
||||
|
||||
inkwell::support::enable_llvm_pretty_stack_trace();
|
||||
revive_llvm_context::initialize_target(revive_llvm_context::Target::PVM);
|
||||
revive_llvm_context::initialize_llvm(
|
||||
revive_llvm_context::Target::PVM,
|
||||
crate::DEFAULT_EXECUTABLE_NAME,
|
||||
&[],
|
||||
);
|
||||
let optimizer_settings = revive_llvm_context::OptimizerSettings::none();
|
||||
|
||||
let project = Project::try_from_yul_string::<SolcCompiler>(
|
||||
@@ -209,7 +238,7 @@ pub fn build_yul(source_code: &str) -> anyhow::Result<()> {
|
||||
source_code,
|
||||
None,
|
||||
)?;
|
||||
let _build = project.compile(optimizer_settings, false, DEBUG_CONFIG)?;
|
||||
let _build = project.compile(optimizer_settings, false, DEBUG_CONFIG, Default::default())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::warning::Warning;
|
||||
use revive_solc_json_interface::warning::Warning;
|
||||
|
||||
pub const ECRECOVER_TEST_SOURCE: &str = r#"
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -192,6 +192,8 @@ where
|
||||
revive_llvm_context::PolkaVMStoreHeapWordFunction.declare(context)?;
|
||||
revive_llvm_context::PolkaVMLoadStorageWordFunction.declare(context)?;
|
||||
revive_llvm_context::PolkaVMStoreStorageWordFunction.declare(context)?;
|
||||
revive_llvm_context::PolkaVMLoadTransientStorageWordFunction.declare(context)?;
|
||||
revive_llvm_context::PolkaVMStoreTransientStorageWordFunction.declare(context)?;
|
||||
|
||||
revive_llvm_context::PolkaVMWordToPointerFunction.declare(context)?;
|
||||
revive_llvm_context::PolkaVMExitFunction.declare(context)?;
|
||||
@@ -242,6 +244,8 @@ where
|
||||
revive_llvm_context::PolkaVMStoreHeapWordFunction.into_llvm(context)?;
|
||||
revive_llvm_context::PolkaVMLoadStorageWordFunction.into_llvm(context)?;
|
||||
revive_llvm_context::PolkaVMStoreStorageWordFunction.into_llvm(context)?;
|
||||
revive_llvm_context::PolkaVMLoadTransientStorageWordFunction.into_llvm(context)?;
|
||||
revive_llvm_context::PolkaVMStoreTransientStorageWordFunction.into_llvm(context)?;
|
||||
|
||||
revive_llvm_context::PolkaVMWordToPointerFunction.into_llvm(context)?;
|
||||
revive_llvm_context::PolkaVMExitFunction.into_llvm(context)?;
|
||||
|
||||
+3
-2
@@ -3,8 +3,9 @@ const path = require("path");
|
||||
const { minify } = require("terser");
|
||||
|
||||
const SOLJSON_URI =
|
||||
"https://binaries.soliditylang.org/wasm/soljson-v0.8.28+commit.7893614a.js";
|
||||
const RESOLC_WASM_URI = "http://127.0.0.1:8080/resolc.wasm";
|
||||
"https://binaries.soliditylang.org/wasm/soljson-v0.8.29+commit.ab55807c.js";
|
||||
const RESOLC_WASM_URI =
|
||||
process.env.RELEASE_RESOLC_WASM_URI || "http://127.0.0.1:8080/resolc.wasm";
|
||||
const RESOLC_WASM_TARGET_DIR = path.join(
|
||||
__dirname,
|
||||
"../target/wasm32-unknown-emscripten/release",
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"name": "revive",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"solc": "^0.8.28"
|
||||
"solc": "^0.8.29"
|
||||
},
|
||||
"scripts": {
|
||||
"example:web": "http-server ./examples/web/",
|
||||
|
||||
@@ -35,11 +35,6 @@ module.exports = defineConfig({
|
||||
name: "firefox",
|
||||
use: { ...devices["Desktop Firefox"] },
|
||||
},
|
||||
|
||||
{
|
||||
name: "webkit",
|
||||
use: { ...devices["Desktop Safari"] },
|
||||
},
|
||||
],
|
||||
|
||||
/* Run your local dev server before starting the tests */
|
||||
|
||||
Reference in New Issue
Block a user