mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-24 19:46:12 +00:00
Add dedicated crate for building Solidity contracts
This commit is contained in:
parent
239127aae5
commit
bdf89f5350
9 changed files with 133 additions and 43 deletions
1
.github/workflows/networks-tests.yml
vendored
1
.github/workflows/networks-tests.yml
vendored
|
@ -30,6 +30,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
GITHUB_CI=true RUST_BACKTRACE=1 cargo test --all-features \
|
GITHUB_CI=true RUST_BACKTRACE=1 cargo test --all-features \
|
||||||
-p bitcoin-serai \
|
-p bitcoin-serai \
|
||||||
|
-p build-solidity-contracts \
|
||||||
-p alloy-simple-request-transport \
|
-p alloy-simple-request-transport \
|
||||||
-p serai-ethereum-relayer \
|
-p serai-ethereum-relayer \
|
||||||
-p monero-io \
|
-p monero-io \
|
||||||
|
|
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -1318,6 +1318,10 @@ dependencies = [
|
||||||
"semver 0.6.0",
|
"semver 0.6.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "build-solidity-contracts"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.16.0"
|
version = "3.16.0"
|
||||||
|
@ -8677,6 +8681,7 @@ name = "serai-processor-ethereum-contracts"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloy-sol-types",
|
"alloy-sol-types",
|
||||||
|
"build-solidity-contracts",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -46,6 +46,7 @@ members = [
|
||||||
|
|
||||||
"networks/bitcoin",
|
"networks/bitcoin",
|
||||||
|
|
||||||
|
"networks/ethereum/build-contracts",
|
||||||
"networks/ethereum/alloy-simple-request-transport",
|
"networks/ethereum/alloy-simple-request-transport",
|
||||||
"networks/ethereum/relayer",
|
"networks/ethereum/relayer",
|
||||||
|
|
||||||
|
|
15
networks/ethereum/build-contracts/Cargo.toml
Normal file
15
networks/ethereum/build-contracts/Cargo.toml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[package]
|
||||||
|
name = "build-solidity-contracts"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "A helper function to build Solidity contracts"
|
||||||
|
license = "MIT"
|
||||||
|
repository = "https://github.com/serai-dex/serai/tree/develop/networks/ethereum/build-contracts"
|
||||||
|
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
all-features = true
|
||||||
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
15
networks/ethereum/build-contracts/LICENSE
Normal file
15
networks/ethereum/build-contracts/LICENSE
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
AGPL-3.0-only license
|
||||||
|
|
||||||
|
Copyright (c) 2022-2024 Luke Parker
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License Version 3 as
|
||||||
|
published by the Free Software Foundation.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
4
networks/ethereum/build-contracts/README.md
Normal file
4
networks/ethereum/build-contracts/README.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Build Solidity Contracts
|
||||||
|
|
||||||
|
A helper function to build Solidity contracts. This is intended to be called
|
||||||
|
from within build scripts.
|
88
networks/ethereum/build-contracts/src/lib.rs
Normal file
88
networks/ethereum/build-contracts/src/lib.rs
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
|
#![doc = include_str!("../README.md")]
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
use std::{path::PathBuf, fs, process::Command};
|
||||||
|
|
||||||
|
/// Build contracts placed in `contracts/`, outputting to `artifacts/`.
|
||||||
|
///
|
||||||
|
/// Requires solc 0.8.25.
|
||||||
|
pub fn build(contracts_path: &str, artifacts_path: &str) -> Result<(), String> {
|
||||||
|
println!("cargo:rerun-if-changed={contracts_path}/*");
|
||||||
|
println!("cargo:rerun-if-changed={artifacts_path}/*");
|
||||||
|
|
||||||
|
for line in String::from_utf8(
|
||||||
|
Command::new("solc")
|
||||||
|
.args(["--version"])
|
||||||
|
.output()
|
||||||
|
.map_err(|_| "couldn't fetch solc output".to_string())?
|
||||||
|
.stdout,
|
||||||
|
)
|
||||||
|
.map_err(|_| "solc stdout wasn't UTF-8")?
|
||||||
|
.lines()
|
||||||
|
{
|
||||||
|
if let Some(version) = line.strip_prefix("Version: ") {
|
||||||
|
let version =
|
||||||
|
version.split('+').next().ok_or_else(|| "no value present on line".to_string())?;
|
||||||
|
if version != "0.8.25" {
|
||||||
|
Err(format!("version was {version}, 0.8.25 required"))?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
let args = [
|
||||||
|
"--base-path", ".",
|
||||||
|
"-o", "./artifacts", "--overwrite",
|
||||||
|
"--bin", "--abi",
|
||||||
|
"--via-ir", "--optimize",
|
||||||
|
"--no-color",
|
||||||
|
];
|
||||||
|
let mut args = args.into_iter().map(str::to_string).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let mut queue = vec![PathBuf::from(contracts_path)];
|
||||||
|
while let Some(folder) = queue.pop() {
|
||||||
|
for entry in fs::read_dir(folder).map_err(|e| format!("couldn't read directory: {e:?}"))? {
|
||||||
|
let entry = entry.map_err(|e| format!("couldn't read directory in entry: {e:?}"))?;
|
||||||
|
let kind = entry.file_type().map_err(|e| format!("couldn't fetch file type: {e:?}"))?;
|
||||||
|
if kind.is_dir() {
|
||||||
|
queue.push(entry.path());
|
||||||
|
}
|
||||||
|
|
||||||
|
if kind.is_file() &&
|
||||||
|
entry
|
||||||
|
.file_name()
|
||||||
|
.into_string()
|
||||||
|
.map_err(|_| "file name wasn't a valid UTF-8 string".to_string())?
|
||||||
|
.ends_with(".sol")
|
||||||
|
{
|
||||||
|
args.push(
|
||||||
|
entry
|
||||||
|
.path()
|
||||||
|
.into_os_string()
|
||||||
|
.into_string()
|
||||||
|
.map_err(|_| "file path wasn't a valid UTF-8 string".to_string())?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We on purposely ignore symlinks to avoid recursive structures
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let solc = Command::new("solc")
|
||||||
|
.args(args)
|
||||||
|
.output()
|
||||||
|
.map_err(|_| "couldn't fetch solc output".to_string())?;
|
||||||
|
let stderr =
|
||||||
|
String::from_utf8(solc.stderr).map_err(|_| "solc stderr wasn't UTF-8".to_string())?;
|
||||||
|
if !solc.status.success() {
|
||||||
|
Err(format!("solc didn't successfully execute: {stderr}"))?;
|
||||||
|
}
|
||||||
|
for line in stderr.lines() {
|
||||||
|
if line.contains("Error:") {
|
||||||
|
Err(format!("solc output had error: {stderr}"))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -18,3 +18,6 @@ workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
alloy-sol-types = { version = "0.8", default-features = false }
|
alloy-sol-types = { version = "0.8", default-features = false }
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
build-solidity-contracts = { path = "../../../networks/ethereum/build-contracts" }
|
||||||
|
|
|
@ -1,45 +1,3 @@
|
||||||
use std::process::Command;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo:rerun-if-changed=contracts/*");
|
build_solidity_contracts::build("contracts", "artifacts").unwrap();
|
||||||
println!("cargo:rerun-if-changed=artifacts/*");
|
|
||||||
|
|
||||||
for line in String::from_utf8(Command::new("solc").args(["--version"]).output().unwrap().stdout)
|
|
||||||
.unwrap()
|
|
||||||
.lines()
|
|
||||||
{
|
|
||||||
if let Some(version) = line.strip_prefix("Version: ") {
|
|
||||||
let version = version.split('+').next().unwrap();
|
|
||||||
assert_eq!(version, "0.8.25");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
let args = [
|
|
||||||
"--base-path", ".",
|
|
||||||
"-o", "./artifacts", "--overwrite",
|
|
||||||
"--bin", "--abi",
|
|
||||||
"--via-ir", "--optimize",
|
|
||||||
|
|
||||||
"./contracts/IERC20.sol",
|
|
||||||
|
|
||||||
"./contracts/Schnorr.sol",
|
|
||||||
"./contracts/Deployer.sol",
|
|
||||||
"./contracts/Sandbox.sol",
|
|
||||||
"./contracts/Router.sol",
|
|
||||||
|
|
||||||
"./contracts/tests/Schnorr.sol",
|
|
||||||
"./contracts/tests/ERC20.sol",
|
|
||||||
|
|
||||||
"--no-color",
|
|
||||||
];
|
|
||||||
let solc = Command::new("solc").args(args).output().unwrap();
|
|
||||||
assert!(solc.status.success());
|
|
||||||
let stderr = String::from_utf8(solc.stderr).unwrap();
|
|
||||||
for line in stderr.lines() {
|
|
||||||
if line.contains("Error:") {
|
|
||||||
println!("{stderr}");
|
|
||||||
panic!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue