Initial wasm support

This commit is contained in:
Sebastian Miasojed
2024-08-29 17:28:31 +02:00
parent 41c8d4e955
commit 5ac67bdc0d
69 changed files with 2277 additions and 8937 deletions
+9 -10
View File
@@ -1,11 +1,9 @@
[package]
name = "revive-integration"
version.workspace = true
license.workspace = true
edition.workspace = true
repository.workspace = true
authors.workspace = true
description = "revive compiler integration test cases"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
polkavm = { workspace = true }
@@ -14,11 +12,12 @@ alloy-sol-types = { workspace = true }
hex = { workspace = true }
env_logger = { workspace = true }
log = { workspace = true }
once_cell = { workspace = true }
revive-solidity = { workspace = true }
revive-differential = { workspace = true }
revive-llvm-context = { workspace = true }
revive-common = { workspace = true }
revive-solidity = { path = "../solidity" }
revive-differential = { path = "../differential" }
revive-llvm-context = { path = "../llvm-context" }
revive-common = { path = "../common" }
[dev-dependencies]
sha1 = { workspace = true }
+2 -2
View File
@@ -2,9 +2,9 @@
"Baseline": 934,
"Computation": 4360,
"DivisionArithmetics": 39824,
"ERC20": 46471,
"ERC20": 52825,
"Events": 1749,
"FibonacciIterative": 2973,
"Flipper": 3563,
"SHA1": 32543
"SHA1": 32623
}
+375 -73
View File
@@ -1,8 +1,6 @@
use alloy_primitives::{Address, I256, U256};
use alloy_sol_types::{sol, SolCall, SolConstructor};
use revive_solidity::test_utils::*;
use crate::mock_runtime::{CallOutput, State};
#[derive(Clone)]
@@ -13,90 +11,45 @@ pub struct Contract {
pub calldata: Vec<u8>,
}
macro_rules! case {
// Arguments:
// 1. The file name, expect to live under "../contracts/"
// 2. The Solidity contract name
// 3. The derived Solidity function call name
// 4. The method name on [Contract]
// 5. Any parameters to the Solidity functions
($file_name:literal, $contract_name:ident, $contract_method:ident, $method_name:ident, $( $v:ident: $t:ty ),* ) => {
impl Contract {
pub fn $method_name($($v: $t),*) -> Self {
let code = include_str!(concat!("../contracts/", $file_name));
let args = $contract_name::$contract_method::new(($($v,)*)).abi_encode();
let name = stringify!($contract_name);
Contract::build(args, name, code)
}
}
};
// Arguments:
// 1. The file name, expect to live under "../contracts/"
// 2. The Solidity contract name
// 3. Raw Calldata
// 4. The method name on [Contract]
($file_name:literal, $contract_name:literal, $calldata:expr, $method_name:ident) => {
impl Contract {
pub fn $method_name() -> Self {
let code = include_str!(concat!("../contracts/", $file_name));
Contract::build($calldata, $contract_name, code)
}
}
};
}
case!("Create.sol", "CreateA", vec![0; 4], create_a);
case!("Create.sol", "CreateB", vec![0; 4], create_b);
sol!(contract Baseline { function baseline() public payable; });
case!("Baseline.sol", Baseline, baselineCall, baseline,);
sol!(contract Flipper {
constructor (bool);
function flip() public;
});
case!("flipper.sol", Flipper, flipCall, flipper,);
case!("flipper.sol", Flipper, constructorCall, flipper_constructor, coin: bool);
sol!(contract Computation {
function odd_product(int32 n) public pure returns (int64);
function triangle_number(int64 n) public pure returns (int64 sum);
});
case!("Computation.sol", Computation, odd_productCall, odd_product, n: i32);
case!("Computation.sol", Computation, triangle_numberCall, triangle_number, n: i64);
sol!(
contract FibonacciRecursive {
function fib3(uint n) public pure returns (uint);
}
);
case!("Fibonacci.sol", FibonacciRecursive, fib3Call, fib_recursive, n: U256);
sol!(
contract FibonacciIterative {
function fib3(uint n) external pure returns (uint b);
}
);
case!("Fibonacci.sol", FibonacciIterative, fib3Call, fib_iterative, n: U256);
sol!(
contract FibonacciBinet {
function fib3(uint n) external pure returns (uint a);
}
);
case!("Fibonacci.sol", FibonacciBinet, fib3Call, fib_binet, n: U256);
sol!(
contract SHA1 {
function sha1(bytes memory data) public pure returns (bytes20 ret);
}
);
case!("SHA1.sol", SHA1, sha1Call, sha1, pre: Vec<u8>);
sol!(
contract ERC20 {
interface IERC20 {
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
@@ -120,7 +73,6 @@ sol!(
event Approval(address indexed owner, address indexed spender, uint value);
}
);
case!("ERC20.sol", ERC20, totalSupplyCall, erc20,);
sol!(
contract Block {
@@ -129,8 +81,6 @@ sol!(
function number() public view returns (uint ret);
}
);
case!("Block.sol", Block, numberCall, block_number,);
case!("Block.sol", Block, timestampCall, block_timestamp,);
sol!(
contract Context {
@@ -139,8 +89,6 @@ sol!(
function caller() public pure returns (address);
}
);
case!("Context.sol", Context, address_thisCall, context_address,);
case!("Context.sol", Context, callerCall, context_caller,);
sol!(
contract DivisionArithmetics {
@@ -153,17 +101,12 @@ sol!(
function smod(int n, int d) public pure returns (int r);
}
);
case!("DivisionArithmetics.sol", DivisionArithmetics, divCall, division_arithmetics_div, n: U256, d: U256);
case!("DivisionArithmetics.sol", DivisionArithmetics, sdivCall, division_arithmetics_sdiv, n: I256, d: I256);
case!("DivisionArithmetics.sol", DivisionArithmetics, modCall, division_arithmetics_mod, n: U256, d: U256);
case!("DivisionArithmetics.sol", DivisionArithmetics, smodCall, division_arithmetics_smod, n: I256, d: I256);
sol!(
contract MStore8 {
function mStore8(uint value) public pure returns (uint256 word);
}
);
case!("mStore8.sol", MStore8, mStore8Call, mstore8, value: U256);
sol!(
contract Events {
@@ -173,7 +116,12 @@ sol!(
function emitEvent(uint topics) public;
}
);
case!("Events.sol", Events, emitEventCall, event, topics: U256);
sol!(
contract CreateB {
fallback() external payable;
}
);
sol!(
contract ExtCode {
@@ -182,15 +130,12 @@ sol!(
function CodeSize() public pure returns (uint ret);
}
);
case!("ExtCode.sol", ExtCode, ExtCodeSizeCall, ext_code_size, address: Address);
case!("ExtCode.sol", ExtCode, CodeSizeCall, code_size,);
sol!(
contract MCopy {
function memcpy(bytes memory payload) public pure returns (bytes memory);
}
);
case!("MCopy.sol", MCopy, memcpyCall, memcpy, payload: Vec<u8>);
sol!(
contract Call {
@@ -204,30 +149,24 @@ sol!(
) public payable returns (bytes memory);
}
);
case!("Call.sol", Call, value_transferCall, call_value_transfer, destination: Address);
case!("Call.sol", Call, callCall, call_call, destination: Address, payload: Vec<u8>);
case!("Call.sol", "Call", vec![], call_constructor);
sol!(
contract Value {
function balance_of(address _address) public view returns (uint ret);
}
);
case!("Value.sol", Value, balance_ofCall, value_balance_of, address: Address);
sol!(
contract Bitwise {
function opByte(uint i, uint x) public payable returns (uint ret);
}
);
case!("Bitwise.sol", Bitwise, opByteCall, bitwise_byte, index: U256, value: U256);
sol!(
contract Storage {
function transient(uint value) public returns (uint ret);
}
);
case!("Storage.sol", Storage, transientCall, storage_transient, value: U256);
impl Contract {
/// Execute the contract.
@@ -248,12 +187,375 @@ impl Contract {
.call()
}
fn build(calldata: Vec<u8>, name: &'static str, code: &str) -> Self {
pub fn baseline() -> Self {
let code = include_str!("../contracts/Baseline.sol");
let name = "Baseline";
Self {
name,
evm_runtime: compile_evm_bin_runtime(name, code),
pvm_runtime: compile_blob(name, code),
calldata,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Baseline::baselineCall::new(()).abi_encode(),
}
}
pub fn odd_product(n: i32) -> Self {
let code = include_str!("../contracts/Computation.sol");
let name = "Computation";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Computation::odd_productCall::new((n,)).abi_encode(),
}
}
pub fn triangle_number(n: i64) -> Self {
let code = include_str!("../contracts/Computation.sol");
let name = "Computation";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Computation::triangle_numberCall::new((n,)).abi_encode(),
}
}
pub fn fib_recursive(n: u32) -> Self {
let code = include_str!("../contracts/Fibonacci.sol");
let name = "FibonacciRecursive";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: FibonacciRecursive::fib3Call::new((U256::from(n),)).abi_encode(),
}
}
pub fn fib_iterative(n: u32) -> Self {
let code = include_str!("../contracts/Fibonacci.sol");
let name = "FibonacciIterative";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: FibonacciIterative::fib3Call::new((U256::from(n),)).abi_encode(),
}
}
pub fn fib_binet(n: u32) -> Self {
let code = include_str!("../contracts/Fibonacci.sol");
let name = "FibonacciBinet";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: FibonacciBinet::fib3Call::new((U256::from(n),)).abi_encode(),
}
}
pub fn sha1(pre: Vec<u8>) -> Self {
let code = include_str!("../contracts/SHA1.sol");
let name = "SHA1";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: SHA1::sha1Call::new((pre,)).abi_encode(),
}
}
pub fn flipper() -> Self {
let code = include_str!("../contracts/flipper.sol");
let name = "Flipper";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Flipper::flipCall::new(()).abi_encode(),
}
}
pub fn flipper_constructor(coin: bool) -> Self {
let code = include_str!("../contracts/flipper.sol");
let name = "Flipper";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Flipper::constructorCall::new((coin,)).abi_encode(),
}
}
pub fn erc20() -> Self {
let code = include_str!("../contracts/ERC20.sol");
let name = "ERC20";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: IERC20::totalSupplyCall::new(()).abi_encode(),
}
}
pub fn block_number() -> Self {
let code = include_str!("../contracts/Block.sol");
let name = "Block";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Block::numberCall::new(()).abi_encode(),
}
}
pub fn block_timestamp() -> Self {
let code = include_str!("../contracts/Block.sol");
let name = "Block";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Block::timestampCall::new(()).abi_encode(),
}
}
pub fn context_address() -> Self {
let code = include_str!("../contracts/Context.sol");
let name = "Context";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Context::address_thisCall::new(()).abi_encode(),
}
}
pub fn context_caller() -> Self {
let code = include_str!("../contracts/Context.sol");
let name = "Context";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Context::callerCall::new(()).abi_encode(),
}
}
pub fn division_arithmetics_div(n: U256, d: U256) -> Self {
let code = include_str!("../contracts/DivisionArithmetics.sol");
let name = "DivisionArithmetics";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: DivisionArithmetics::divCall::new((n, d)).abi_encode(),
}
}
pub fn division_arithmetics_sdiv(n: I256, d: I256) -> Self {
let code = include_str!("../contracts/DivisionArithmetics.sol");
let name = "DivisionArithmetics";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: DivisionArithmetics::sdivCall::new((n, d)).abi_encode(),
}
}
pub fn division_arithmetics_mod(n: U256, d: U256) -> Self {
let code = include_str!("../contracts/DivisionArithmetics.sol");
let name = "DivisionArithmetics";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: DivisionArithmetics::modCall::new((n, d)).abi_encode(),
}
}
pub fn division_arithmetics_smod(n: I256, d: I256) -> Self {
let code = include_str!("../contracts/DivisionArithmetics.sol");
let name = "DivisionArithmetics";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: DivisionArithmetics::smodCall::new((n, d)).abi_encode(),
}
}
pub fn mstore8(value: U256) -> Self {
let code = include_str!("../contracts/mStore8.sol");
let name = "MStore8";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: MStore8::mStore8Call::new((value,)).abi_encode(),
}
}
pub fn event(topics: U256) -> Self {
let code = include_str!("../contracts/Events.sol");
let name = "Events";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Events::emitEventCall::new((topics,)).abi_encode(),
}
}
pub fn create_a() -> Self {
let code = include_str!("../contracts/Create.sol");
let name = "CreateA";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: vec![0; 4],
}
}
pub fn create_b() -> Self {
let code = include_str!("../contracts/Create.sol");
let name = "CreateB";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: vec![0; 4],
}
}
pub fn ext_code_size(address: Address) -> Self {
let code = include_str!("../contracts/ExtCode.sol");
let name = "ExtCode";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: ExtCode::ExtCodeSizeCall::new((address,)).abi_encode(),
}
}
pub fn code_size() -> Self {
let code = include_str!("../contracts/ExtCode.sol");
let name = "ExtCode";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: ExtCode::CodeSizeCall::new(()).abi_encode(),
}
}
pub fn memcpy(payload: Vec<u8>) -> Self {
let code = include_str!("../contracts/MCopy.sol");
let name = "MCopy";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: MCopy::memcpyCall::new((payload,)).abi_encode(),
}
}
pub fn call_value_transfer(destination: Address) -> Self {
let code = include_str!("../contracts/Call.sol");
let name = "Call";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Call::value_transferCall::new((destination,)).abi_encode(),
}
}
pub fn call_call(callee: Address, payload: Vec<u8>) -> Self {
let code = include_str!("../contracts/Call.sol");
let name = "Call";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Call::callCall::new((callee, payload)).abi_encode(),
}
}
pub fn call_constructor() -> Self {
let code = include_str!("../contracts/Call.sol");
let name = "Call";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Default::default(),
}
}
pub fn value_balance_of(address: Address) -> Self {
let code = include_str!("../contracts/Value.sol");
let name = "Value";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Value::balance_ofCall::new((address,)).abi_encode(),
}
}
pub fn bitwise_byte(index: U256, value: U256) -> Self {
let code = include_str!("../contracts/Bitwise.sol");
let name = "Bitwise";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Bitwise::opByteCall::new((index, value)).abi_encode(),
}
}
pub fn storage_transient(value: U256) -> Self {
let code = include_str!("../contracts/Storage.sol");
let name = "Storage";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Storage::transientCall::new((value,)).abi_encode(),
}
}
}
@@ -303,7 +605,7 @@ mod tests {
Contract::baseline as fn() -> Contract,
Contract::flipper as fn() -> Contract,
(|| Contract::odd_product(0)) as fn() -> Contract,
(|| Contract::fib_iterative(U256::ZERO)) as fn() -> Contract,
(|| Contract::fib_iterative(0)) as fn() -> Contract,
Contract::erc20 as fn() -> Contract,
(|| Contract::sha1(Vec::new())) as fn() -> Contract,
(|| Contract::division_arithmetics_div(U256::ZERO, U256::ZERO)) as fn() -> Contract,
+108
View File
@@ -4,12 +4,120 @@ use mock_runtime::{CallOutput, State};
use crate::mock_runtime::{Event, ReturnFlags};
use once_cell::sync::Lazy;
use std::{collections::HashMap, sync::Mutex};
pub mod cases;
pub mod mock_runtime;
#[cfg(test)]
mod tests;
pub(crate) static PVM_BLOB_CACHE: Lazy<Mutex<HashMap<CompiledBlobId, Vec<u8>>>> =
Lazy::new(Default::default);
pub(crate) static EVM_BLOB_CACHE: Lazy<Mutex<HashMap<CompiledBlobId, Vec<u8>>>> =
Lazy::new(Default::default);
#[derive(Hash, PartialEq, Eq)]
struct CompiledBlobId {
contract_name: String,
solc_optimizer_enabled: bool,
pipeline: revive_solidity::SolcPipeline,
}
/// Compile the blob of `contract_name` found in given `source_code`.
/// The `solc` optimizer will be enabled
pub fn compile_blob(contract_name: &str, source_code: &str) -> Vec<u8> {
compile_blob_with_options(
contract_name,
source_code,
true,
revive_solidity::SolcPipeline::Yul,
)
}
/// Compile the EVM bin-runtime of `contract_name` found in given `source_code`.
/// The `solc` optimizer will be enabled
pub fn compile_evm_bin_runtime(contract_name: &str, source_code: &str) -> Vec<u8> {
let pipeline = revive_solidity::SolcPipeline::Yul;
let solc_optimizer_enabled = true;
let id = CompiledBlobId {
contract_name: contract_name.to_owned(),
pipeline,
solc_optimizer_enabled,
};
if let Some(blob) = EVM_BLOB_CACHE.lock().unwrap().get(&id) {
return blob.clone();
}
let file_name = "contract.sol";
let contracts = revive_solidity::test_utils::build_solidity_with_options_evm(
[(file_name.into(), source_code.into())].into(),
Default::default(),
None,
pipeline,
solc_optimizer_enabled,
)
.expect("source should compile");
let bin_runtime = &contracts
.get(contract_name)
.unwrap_or_else(|| panic!("contract '{}' didn't produce bin-runtime", contract_name))
.object;
let blob = hex::decode(bin_runtime).expect("bin-runtime shold be hex encoded");
EVM_BLOB_CACHE.lock().unwrap().insert(id, blob.clone());
blob
}
/// Compile the blob of `contract_name` found in given `source_code`.
pub fn compile_blob_with_options(
contract_name: &str,
source_code: &str,
solc_optimizer_enabled: bool,
pipeline: revive_solidity::SolcPipeline,
) -> Vec<u8> {
let id = CompiledBlobId {
contract_name: contract_name.to_owned(),
solc_optimizer_enabled,
pipeline,
};
if let Some(blob) = PVM_BLOB_CACHE.lock().unwrap().get(&id) {
return blob.clone();
}
let file_name = "contract.sol";
let contracts = revive_solidity::test_utils::build_solidity_with_options(
[(file_name.into(), source_code.into())].into(),
Default::default(),
None,
pipeline,
revive_llvm_context::OptimizerSettings::cycles(),
solc_optimizer_enabled,
)
.expect("source should compile")
.contracts
.expect("source should contain at least one contract");
let bytecode = contracts[file_name][contract_name]
.evm
.as_ref()
.expect("source should produce EVM output")
.bytecode
.as_ref()
.expect("source should produce assembly text")
.object
.as_str();
let blob = hex::decode(bytecode).expect("hex encoding should always be valid");
PVM_BLOB_CACHE.lock().unwrap().insert(id, blob.clone());
blob
}
pub fn assert_success(contract: &Contract, differential: bool) -> (State, CallOutput) {
let (state, output) = contract.execute();
assert_eq!(output.flags, ReturnFlags::Success);
+8 -10
View File
@@ -5,8 +5,6 @@ use alloy_sol_types::{sol, SolCall, SolValue};
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use sha1::Digest;
use revive_solidity::test_utils::*;
use crate::{
assert_success,
cases::Contract,
@@ -18,9 +16,9 @@ fn fibonacci() {
let parameter = 6;
for contract in [
Contract::fib_recursive(U256::from(parameter)),
Contract::fib_iterative(U256::from(parameter)),
Contract::fib_binet(U256::from(parameter)),
Contract::fib_recursive(parameter),
Contract::fib_iterative(parameter),
Contract::fib_binet(parameter),
] {
let (_, output) = assert_success(&contract, true);
let received = U256::from_be_bytes::<32>(output.data.try_into().unwrap());
@@ -64,7 +62,7 @@ fn hash_keccak_256() {
hash = keccak256(bytes(_pre));
}
}"#;
let code = compile_blob("TestSha3", source);
let code = crate::compile_blob("TestSha3", source);
let param = "hello";
let input = TestSha3::testCall::new((param.to_string(),)).abi_encode();
@@ -84,7 +82,7 @@ fn hash_keccak_256() {
#[test]
fn erc20() {
let _ = compile_blob("ERC20", include_str!("../contracts/ERC20.sol"));
let _ = crate::compile_blob("ERC20", include_str!("../contracts/ERC20.sol"));
}
#[test]
@@ -111,7 +109,7 @@ fn msize_plain() {
function mSize() public pure returns (uint);
}
);
let code = compile_blob_with_options(
let code = crate::compile_blob_with_options(
"MSize",
include_str!("../contracts/MSize.sol"),
false,
@@ -140,7 +138,7 @@ fn transferred_value() {
function value() public payable returns (uint);
}
);
let code = compile_blob("Value", include_str!("../contracts/Value.sol"));
let code = crate::compile_blob("Value", include_str!("../contracts/Value.sol"));
let (_, output) = State::default()
.transaction()
@@ -164,7 +162,7 @@ fn msize_non_word_sized_access() {
function mStore100() public pure returns (uint);
}
);
let code = compile_blob_with_options(
let code = crate::compile_blob_with_options(
"MSize",
include_str!("../contracts/MSize.sol"),
false,