Merge remote-tracking branch 'origin/main' into resolc.js

This commit is contained in:
Sebastian Miasojed
2024-11-06 15:04:34 +01:00
143 changed files with 14572 additions and 5271 deletions
+7 -11
View File
@@ -5,9 +5,10 @@ pub mod contract;
use std::collections::BTreeMap;
use std::path::Path;
use crate::compiler::combined_json::CombinedJson;
use crate::compiler::standard_json::output::Output as StandardJsonOutput;
use crate::compiler::version::Version as SolcVersion;
use crate::solc::combined_json::CombinedJson;
use crate::solc::standard_json::output::Output as StandardJsonOutput;
use crate::solc::version::Version as SolcVersion;
use crate::ResolcVersion;
use self::contract::Contract;
@@ -40,11 +41,7 @@ impl Build {
}
/// Writes all contracts assembly and bytecode to the combined JSON.
pub fn write_to_combined_json(
self,
combined_json: &mut CombinedJson,
resolc_version: &semver::Version,
) -> anyhow::Result<()> {
pub fn write_to_combined_json(self, combined_json: &mut CombinedJson) -> anyhow::Result<()> {
for (path, contract) in self.contracts.into_iter() {
let combined_json_contract = combined_json
.contracts
@@ -61,7 +58,7 @@ impl Build {
contract.write_to_combined_json(combined_json_contract)?;
}
combined_json.zk_version = Some(resolc_version.to_string());
combined_json.revive_version = Some(ResolcVersion::default().long);
Ok(())
}
@@ -71,7 +68,6 @@ impl Build {
mut self,
standard_json: &mut StandardJsonOutput,
solc_version: &SolcVersion,
resolc_version: &semver::Version,
) -> anyhow::Result<()> {
let contracts = match standard_json.contracts.as_mut() {
Some(contracts) => contracts,
@@ -90,7 +86,7 @@ impl Build {
standard_json.version = Some(solc_version.default.to_string());
standard_json.long_version = Some(solc_version.long.to_owned());
standard_json.zk_version = Some(resolc_version.to_string());
standard_json.revive_version = Some(ResolcVersion::default().long);
Ok(())
}
@@ -199,6 +199,7 @@ where
revive_llvm_context::PolkaVMDummyLLVMWritable::default(),
)
.declare(context)?;
revive_llvm_context::PolkaVMImmutableDataLoadFunction.declare(context)?;
entry.into_llvm(context)?;
@@ -266,6 +267,7 @@ where
revive_llvm_context::PolkaVMCodeType::Runtime,
))
.into_llvm(context)?;
revive_llvm_context::PolkaVMImmutableDataLoadFunction.into_llvm(context)?;
Ok(())
}
@@ -45,7 +45,7 @@ impl Element {
fn pop_arguments_llvm<'ctx, D>(
&mut self,
context: &mut revive_llvm_context::PolkaVMContext<'ctx, D>,
) -> Vec<inkwell::values::BasicValueEnum<'ctx>>
) -> anyhow::Result<Vec<inkwell::values::BasicValueEnum<'ctx>>>
where
D: revive_llvm_context::PolkaVMDependency + Clone,
{
@@ -57,15 +57,13 @@ impl Element {
[self.stack.elements.len() + input_size - output_size - 1 - index]
.to_llvm()
.into_pointer_value();
let value = context
.build_load(
revive_llvm_context::PolkaVMPointer::new_stack_field(context, pointer),
format!("argument_{index}").as_str(),
)
.unwrap();
let value = context.build_load(
revive_llvm_context::PolkaVMPointer::new_stack_field(context, pointer),
format!("argument_{index}").as_str(),
)?;
arguments.push(value);
}
arguments
Ok(arguments)
}
}
@@ -426,7 +424,7 @@ where
InstructionName::JUMPDEST => Ok(None),
InstructionName::ADD => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_arithmetic::addition(
context,
arguments[0].into_int_value(),
@@ -435,7 +433,7 @@ where
.map(Some)
}
InstructionName::SUB => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_arithmetic::subtraction(
context,
arguments[0].into_int_value(),
@@ -444,7 +442,7 @@ where
.map(Some)
}
InstructionName::MUL => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_arithmetic::multiplication(
context,
arguments[0].into_int_value(),
@@ -453,7 +451,7 @@ where
.map(Some)
}
InstructionName::DIV => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_arithmetic::division(
context,
arguments[0].into_int_value(),
@@ -462,7 +460,7 @@ where
.map(Some)
}
InstructionName::MOD => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_arithmetic::remainder(
context,
arguments[0].into_int_value(),
@@ -471,7 +469,7 @@ where
.map(Some)
}
InstructionName::SDIV => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_arithmetic::division_signed(
context,
arguments[0].into_int_value(),
@@ -480,7 +478,7 @@ where
.map(Some)
}
InstructionName::SMOD => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_arithmetic::remainder_signed(
context,
arguments[0].into_int_value(),
@@ -490,7 +488,7 @@ where
}
InstructionName::LT => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_comparison::compare(
context,
arguments[0].into_int_value(),
@@ -500,7 +498,7 @@ where
.map(Some)
}
InstructionName::GT => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_comparison::compare(
context,
arguments[0].into_int_value(),
@@ -510,7 +508,7 @@ where
.map(Some)
}
InstructionName::EQ => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_comparison::compare(
context,
arguments[0].into_int_value(),
@@ -520,7 +518,7 @@ where
.map(Some)
}
InstructionName::ISZERO => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_comparison::compare(
context,
arguments[0].into_int_value(),
@@ -530,7 +528,7 @@ where
.map(Some)
}
InstructionName::SLT => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_comparison::compare(
context,
arguments[0].into_int_value(),
@@ -540,7 +538,7 @@ where
.map(Some)
}
InstructionName::SGT => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_comparison::compare(
context,
arguments[0].into_int_value(),
@@ -551,7 +549,7 @@ where
}
InstructionName::OR => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_bitwise::or(
context,
arguments[0].into_int_value(),
@@ -560,7 +558,7 @@ where
.map(Some)
}
InstructionName::XOR => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_bitwise::xor(
context,
arguments[0].into_int_value(),
@@ -569,7 +567,7 @@ where
.map(Some)
}
InstructionName::NOT => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_bitwise::xor(
context,
arguments[0].into_int_value(),
@@ -578,7 +576,7 @@ where
.map(Some)
}
InstructionName::AND => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_bitwise::and(
context,
arguments[0].into_int_value(),
@@ -587,7 +585,7 @@ where
.map(Some)
}
InstructionName::SHL => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_bitwise::shift_left(
context,
arguments[0].into_int_value(),
@@ -596,7 +594,7 @@ where
.map(Some)
}
InstructionName::SHR => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_bitwise::shift_right(
context,
arguments[0].into_int_value(),
@@ -605,7 +603,7 @@ where
.map(Some)
}
InstructionName::SAR => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_bitwise::shift_right_arithmetic(
context,
arguments[0].into_int_value(),
@@ -614,7 +612,7 @@ where
.map(Some)
}
InstructionName::BYTE => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_bitwise::byte(
context,
arguments[0].into_int_value(),
@@ -624,7 +622,7 @@ where
}
InstructionName::ADDMOD => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_math::add_mod(
context,
arguments[0].into_int_value(),
@@ -634,7 +632,7 @@ where
.map(Some)
}
InstructionName::MULMOD => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_math::mul_mod(
context,
arguments[0].into_int_value(),
@@ -644,7 +642,7 @@ where
.map(Some)
}
InstructionName::EXP => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_math::exponent(
context,
arguments[0].into_int_value(),
@@ -653,7 +651,7 @@ where
.map(Some)
}
InstructionName::SIGNEXTEND => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_math::sign_extend(
context,
arguments[0].into_int_value(),
@@ -663,7 +661,7 @@ where
}
InstructionName::SHA3 | InstructionName::KECCAK256 => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_crypto::sha3(
context,
arguments[0].into_int_value(),
@@ -673,7 +671,7 @@ where
}
InstructionName::MLOAD => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_memory::load(
context,
arguments[0].into_int_value(),
@@ -681,7 +679,7 @@ where
.map(Some)
}
InstructionName::MSTORE => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_memory::store(
context,
arguments[0].into_int_value(),
@@ -690,7 +688,7 @@ where
.map(|_| None)
}
InstructionName::MSTORE8 => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_memory::store_byte(
context,
arguments[0].into_int_value(),
@@ -699,7 +697,7 @@ where
.map(|_| None)
}
InstructionName::MCOPY => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
let destination = revive_llvm_context::PolkaVMPointer::new_with_offset(
context,
revive_llvm_context::PolkaVMAddressSpace::Heap,
@@ -725,7 +723,7 @@ where
}
InstructionName::SLOAD => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_storage::load(
context,
arguments[0].into_int_value(),
@@ -733,7 +731,7 @@ where
.map(Some)
}
InstructionName::SSTORE => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_storage::store(
context,
arguments[0].into_int_value(),
@@ -742,7 +740,7 @@ where
.map(|_| None)
}
InstructionName::TLOAD => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_storage::transient_load(
context,
arguments[0].into_int_value(),
@@ -750,7 +748,7 @@ where
.map(Some)
}
InstructionName::TSTORE => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_storage::transient_store(
context,
arguments[0].into_int_value(),
@@ -766,27 +764,28 @@ where
let offset = context
.solidity_mut()
.get_or_allocate_immutable(key.as_str());
.get_or_allocate_immutable(key.as_str())
/ revive_common::BYTE_LENGTH_WORD;
let index = context.word_const(offset as u64);
let index = context.xlen_type().const_int(offset as u64, false);
revive_llvm_context::polkavm_evm_immutable::load(context, index).map(Some)
}
InstructionName::ASSIGNIMMUTABLE => {
let mut arguments = self.pop_arguments_llvm(context);
let mut arguments = self.pop_arguments_llvm(context)?;
let key = self
.instruction
.value
.ok_or_else(|| anyhow::anyhow!("Instruction value missing"))?;
let offset = context.solidity_mut().allocate_immutable(key.as_str());
let offset = context.solidity_mut().allocate_immutable(key.as_str())
/ revive_common::BYTE_LENGTH_WORD;
let index = context.word_const(offset as u64);
let index = context.xlen_type().const_int(offset as u64, false);
let value = arguments.pop().expect("Always exists").into_int_value();
revive_llvm_context::polkavm_evm_immutable::store(context, index, value)
.map(|_| None)
}
InstructionName::CALLDATALOAD => {
match context
.code_type()
@@ -796,7 +795,7 @@ where
Ok(Some(context.word_const(0).as_basic_value_enum()))
}
revive_llvm_context::PolkaVMCodeType::Runtime => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_calldata::load(
context,
arguments[0].into_int_value(),
@@ -819,7 +818,7 @@ where
}
}
InstructionName::CALLDATACOPY => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
match context
.code_type()
@@ -862,7 +861,7 @@ where
}
}
InstructionName::CODECOPY => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
let parent = context.module().get_name().to_str().expect("Always valid");
let source = &self.stack_input.elements[1];
@@ -917,7 +916,7 @@ where
revive_llvm_context::polkavm_evm_return_data::size(context).map(Some)
}
InstructionName::RETURNDATACOPY => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_return_data::copy(
context,
arguments[0].into_int_value(),
@@ -927,7 +926,7 @@ where
.map(|_| None)
}
InstructionName::EXTCODESIZE => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_ext_code::size(
context,
Some(arguments[0].into_int_value()),
@@ -935,7 +934,7 @@ where
.map(Some)
}
InstructionName::EXTCODEHASH => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_ext_code::hash(
context,
arguments[0].into_int_value(),
@@ -944,7 +943,7 @@ where
}
InstructionName::RETURN => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_return::r#return(
context,
arguments[0].into_int_value(),
@@ -953,7 +952,7 @@ where
.map(|_| None)
}
InstructionName::REVERT => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_return::revert(
context,
arguments[0].into_int_value(),
@@ -969,7 +968,7 @@ where
}
InstructionName::LOG0 => {
let mut arguments = self.pop_arguments_llvm(context);
let mut arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_event::log(
context,
arguments.remove(0).into_int_value(),
@@ -982,7 +981,7 @@ where
.map(|_| None)
}
InstructionName::LOG1 => {
let mut arguments = self.pop_arguments_llvm(context);
let mut arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_event::log(
context,
arguments.remove(0).into_int_value(),
@@ -995,7 +994,7 @@ where
.map(|_| None)
}
InstructionName::LOG2 => {
let mut arguments = self.pop_arguments_llvm(context);
let mut arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_event::log(
context,
arguments.remove(0).into_int_value(),
@@ -1008,7 +1007,7 @@ where
.map(|_| None)
}
InstructionName::LOG3 => {
let mut arguments = self.pop_arguments_llvm(context);
let mut arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_event::log(
context,
arguments.remove(0).into_int_value(),
@@ -1021,7 +1020,7 @@ where
.map(|_| None)
}
InstructionName::LOG4 => {
let mut arguments = self.pop_arguments_llvm(context);
let mut arguments = self.pop_arguments_llvm(context)?;
revive_llvm_context::polkavm_evm_event::log(
context,
arguments.remove(0).into_int_value(),
@@ -1035,7 +1034,7 @@ where
}
InstructionName::CALL => {
let mut arguments = self.pop_arguments_llvm(context);
let mut arguments = self.pop_arguments_llvm(context)?;
let gas = arguments.remove(0).into_int_value();
let address = arguments.remove(0).into_int_value();
@@ -1060,7 +1059,7 @@ where
.map(Some)
}
InstructionName::STATICCALL => {
let mut arguments = self.pop_arguments_llvm(context);
let mut arguments = self.pop_arguments_llvm(context)?;
let gas = arguments.remove(0).into_int_value();
let address = arguments.remove(0).into_int_value();
@@ -1084,7 +1083,7 @@ where
.map(Some)
}
InstructionName::DELEGATECALL => {
let mut arguments = self.pop_arguments_llvm(context);
let mut arguments = self.pop_arguments_llvm(context)?;
let gas = arguments.remove(0).into_int_value();
let address = arguments.remove(0).into_int_value();
@@ -1108,7 +1107,7 @@ where
}
InstructionName::CREATE | InstructionName::ZK_CREATE => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
let value = arguments[0].into_int_value();
let input_offset = arguments[1].into_int_value();
@@ -1119,18 +1118,19 @@ where
value,
input_offset,
input_length,
None,
)
.map(Some)
}
InstructionName::CREATE2 | InstructionName::ZK_CREATE2 => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
let value = arguments[0].into_int_value();
let input_offset = arguments[1].into_int_value();
let input_length = arguments[2].into_int_value();
let salt = arguments[3].into_int_value();
revive_llvm_context::polkavm_evm_create::create2(
revive_llvm_context::polkavm_evm_create::create(
context,
value,
input_offset,
@@ -1154,12 +1154,14 @@ where
revive_llvm_context::polkavm_evm_ether_gas::gas(context).map(Some)
}
InstructionName::BALANCE => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
let address = arguments[0].into_int_value();
revive_llvm_context::polkavm_evm_ether_gas::balance(context, address).map(Some)
}
InstructionName::SELFBALANCE => todo!(),
InstructionName::SELFBALANCE => {
revive_llvm_context::polkavm_evm_ether_gas::self_balance(context).map(Some)
}
InstructionName::GASLIMIT => {
revive_llvm_context::polkavm_evm_contract_context::gas_limit(context).map(Some)
@@ -1181,7 +1183,7 @@ where
revive_llvm_context::polkavm_evm_contract_context::block_number(context).map(Some)
}
InstructionName::BLOCKHASH => {
let arguments = self.pop_arguments_llvm(context);
let arguments = self.pop_arguments_llvm(context)?;
let index = arguments[0].into_int_value();
revive_llvm_context::polkavm_evm_contract_context::block_hash(context, index)
@@ -1204,7 +1206,7 @@ where
anyhow::bail!("The `BLOBBASEFEE` instruction is not supported until zkVM v1.5.0");
}
InstructionName::MSIZE => {
revive_llvm_context::polkavm_evm_contract_context::msize(context).map(Some)
revive_llvm_context::polkavm_evm_memory::msize(context).map(Some)
}
InstructionName::CALLCODE => {
@@ -1219,7 +1221,7 @@ where
anyhow::bail!("The `EXTCODECOPY` instruction is not supported");
}
InstructionName::SELFDESTRUCT => {
let _arguments = self.pop_arguments_llvm(context);
let _arguments = self.pop_arguments_llvm(context)?;
anyhow::bail!("The `SELFDESTRUCT` instruction is not supported");
}
@@ -1231,7 +1233,7 @@ where
return_address,
..
} => {
let mut arguments = self.pop_arguments_llvm(context);
let mut arguments = self.pop_arguments_llvm(context)?;
arguments.pop();
arguments.reverse();
arguments.pop();
@@ -1294,7 +1296,7 @@ where
return Ok(());
}
InstructionName::RecursiveReturn { .. } => {
let mut arguments = self.pop_arguments_llvm(context);
let mut arguments = self.pop_arguments_llvm(context)?;
arguments.reverse();
arguments.pop();
@@ -1139,7 +1139,6 @@ where
.integer_type(revive_common::BIT_LENGTH_BOOLEAN)
.as_basic_type_enum()],
output_size,
false,
);
(r#type, output_size)
}
@@ -1156,7 +1155,6 @@ where
input_size
],
output_size,
false,
);
(r#type, output_size)
}
+32 -54
View File
@@ -8,6 +8,8 @@ pub(crate) mod evmla;
pub(crate) mod missing_libraries;
pub(crate) mod process;
pub(crate) mod project;
pub(crate) mod solc;
pub(crate) mod version;
pub(crate) mod warning;
pub(crate) mod yul;
@@ -46,6 +48,25 @@ 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;
pub use self::solc::pipeline::Pipeline as SolcPipeline;
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 as SolcCompiler;
pub use self::version::Version as ResolcVersion;
pub use self::warning::Warning;
#[cfg(target_os = "emscripten")]
pub mod libsolc;
@@ -61,7 +82,6 @@ pub fn yul<T: Compiler>(
input_files: &[PathBuf],
solc: &mut T,
optimizer_settings: revive_llvm_context::OptimizerSettings,
is_system_mode: bool,
include_metadata_hash: bool,
debug_config: Option<revive_llvm_context::DebugConfig>,
) -> anyhow::Result<Build> {
@@ -74,28 +94,17 @@ pub fn yul<T: Compiler>(
),
};
let solc_validator = if is_system_mode {
None
} else {
if solc.version()?.default != compiler::LAST_SUPPORTED_VERSION {
anyhow::bail!(
if solc.version()?.default != SolcCompiler::LAST_SUPPORTED_VERSION {
anyhow::bail!(
"The Yul mode is only supported with the most recent version of the Solidity compiler: {}",
compiler::LAST_SUPPORTED_VERSION,
);
}
Some(&*solc)
};
}
let solc_validator = Some(&*solc);
let project = Project::try_from_yul_path(path, solc_validator)?;
let build = project.compile(
optimizer_settings,
is_system_mode,
include_metadata_hash,
false,
debug_config,
)?;
let build = project.compile(optimizer_settings, include_metadata_hash, debug_config)?;
Ok(build)
}
@@ -104,7 +113,6 @@ pub fn yul<T: Compiler>(
pub fn llvm_ir(
input_files: &[PathBuf],
optimizer_settings: revive_llvm_context::OptimizerSettings,
is_system_mode: bool,
include_metadata_hash: bool,
debug_config: Option<revive_llvm_context::DebugConfig>,
) -> anyhow::Result<Build> {
@@ -119,13 +127,7 @@ pub fn llvm_ir(
let project = Project::try_from_llvm_ir_path(path)?;
let build = project.compile(
optimizer_settings,
is_system_mode,
include_metadata_hash,
false,
debug_config,
)?;
let build = project.compile(optimizer_settings, include_metadata_hash, debug_config)?;
Ok(build)
}
@@ -140,7 +142,6 @@ pub fn standard_output<T: Compiler>(
solc_optimizer_enabled: bool,
optimizer_settings: revive_llvm_context::OptimizerSettings,
force_evmla: bool,
is_system_mode: bool,
include_metadata_hash: bool,
base_path: Option<String>,
include_paths: Vec<String>,
@@ -164,7 +165,6 @@ pub fn standard_output<T: Compiler>(
None,
&solc_version.default,
optimizer_settings.is_fallback_to_size_enabled(),
optimizer_settings.is_system_request_memoization_disabled(),
),
None,
solc_pipeline == SolcPipeline::Yul,
@@ -210,13 +210,7 @@ pub fn standard_output<T: Compiler>(
debug_config.as_ref(),
)?;
let build = project.compile(
optimizer_settings,
is_system_mode,
include_metadata_hash,
false,
debug_config,
)?;
let build = project.compile(optimizer_settings, include_metadata_hash, debug_config)?;
Ok(build)
}
@@ -227,7 +221,6 @@ pub fn standard_json<T: Compiler>(
solc: &mut T,
detect_missing_libraries: bool,
force_evmla: bool,
is_system_mode: bool,
base_path: Option<String>,
include_paths: Vec<String>,
allow_paths: Option<String>,
@@ -235,7 +228,6 @@ pub fn standard_json<T: Compiler>(
) -> anyhow::Result<()> {
let solc_version = solc.version()?;
let solc_pipeline = SolcPipeline::new(&solc_version, force_evmla);
let resolc_version = semver::Version::parse(env!("CARGO_PKG_VERSION")).expect("Always valid");
let solc_input = SolcStandardJsonInput::try_from_stdin(solc_pipeline)?;
let source_code_files = solc_input
@@ -282,20 +274,10 @@ pub fn standard_json<T: Compiler>(
if detect_missing_libraries {
let missing_libraries = project.get_missing_libraries();
missing_libraries.write_to_standard_json(
&mut solc_output,
&solc_version,
&resolc_version,
)?;
missing_libraries.write_to_standard_json(&mut solc_output, &solc_version)?;
} else {
let build = project.compile(
optimizer_settings,
is_system_mode,
include_metadata_hash,
false,
debug_config,
)?;
build.write_to_standard_json(&mut solc_output, &solc_version, &resolc_version)?;
let build = project.compile(optimizer_settings, include_metadata_hash, debug_config)?;
build.write_to_standard_json(&mut solc_output, &solc_version)?;
}
serde_json::to_writer(std::io::stdout(), &solc_output)?;
std::process::exit(0);
@@ -312,7 +294,6 @@ pub fn combined_json<T: Compiler>(
solc_optimizer_enabled: bool,
optimizer_settings: revive_llvm_context::OptimizerSettings,
force_evmla: bool,
is_system_mode: bool,
include_metadata_hash: bool,
base_path: Option<String>,
include_paths: Vec<String>,
@@ -323,8 +304,6 @@ pub fn combined_json<T: Compiler>(
output_directory: Option<PathBuf>,
overwrite: bool,
) -> anyhow::Result<()> {
let resolc_version = semver::Version::parse(env!("CARGO_PKG_VERSION")).expect("Always valid");
let build = standard_output(
input_files,
libraries,
@@ -333,7 +312,6 @@ pub fn combined_json<T: Compiler>(
solc_optimizer_enabled,
optimizer_settings,
force_evmla,
is_system_mode,
include_metadata_hash,
base_path,
include_paths,
@@ -344,7 +322,7 @@ pub fn combined_json<T: Compiler>(
)?;
let mut combined_json = solc.combined_json(input_files, format.as_str())?;
build.write_to_combined_json(&mut combined_json, &resolc_version)?;
build.write_to_combined_json(&mut combined_json)?;
match output_directory {
Some(output_directory) => {
+4 -4
View File
@@ -3,8 +3,9 @@
use std::collections::BTreeMap;
use std::collections::HashSet;
use crate::compiler::standard_json::output::Output as StandardJsonOutput;
use crate::compiler::version::Version as SolcVersion;
use crate::solc::standard_json::output::Output as StandardJsonOutput;
use crate::solc::version::Version as SolcVersion;
use crate::ResolcVersion;
/// The missing Solidity libraries.
pub struct MissingLibraries {
@@ -23,7 +24,6 @@ impl MissingLibraries {
mut self,
standard_json: &mut StandardJsonOutput,
solc_version: &SolcVersion,
resolc_version: &semver::Version,
) -> anyhow::Result<()> {
let contracts = match standard_json.contracts.as_mut() {
Some(contracts) => contracts,
@@ -43,7 +43,7 @@ impl MissingLibraries {
standard_json.version = Some(solc_version.default.to_string());
standard_json.long_version = Some(solc_version.long.to_owned());
standard_json.zk_version = Some(resolc_version.to_string());
standard_json.revive_version = Some(ResolcVersion::default().long);
Ok(())
}
-8
View File
@@ -14,12 +14,8 @@ pub struct Input {
pub contract: Contract,
/// The project representation.
pub project: Project,
/// The system mode flag.
pub is_system_mode: bool,
/// Whether to append the metadata hash.
pub include_metadata_hash: bool,
/// Enables the test bytecode encoding.
pub enable_test_encoding: bool,
/// The optimizer settings.
pub optimizer_settings: revive_llvm_context::OptimizerSettings,
/// The debug output config.
@@ -31,18 +27,14 @@ impl Input {
pub fn new(
contract: Contract,
project: Project,
is_system_mode: bool,
include_metadata_hash: bool,
enable_test_encoding: bool,
optimizer_settings: revive_llvm_context::OptimizerSettings,
debug_config: Option<revive_llvm_context::DebugConfig>,
) -> Self {
Self {
contract,
project,
is_system_mode,
include_metadata_hash,
enable_test_encoding,
optimizer_settings,
debug_config,
}
@@ -2,6 +2,8 @@
use serde::Serialize;
use crate::ResolcVersion;
/// The Solidity contract metadata.
/// Is used to append the metadata hash to the contract bytecode.
#[derive(Debug, Serialize)]
@@ -9,11 +11,11 @@ pub struct Metadata {
/// The `solc` metadata.
pub solc_metadata: serde_json::Value,
/// The `solc` version.
pub solc_version: semver::Version,
/// The zkVM `solc` edition.
pub solc_zkvm_edition: Option<semver::Version>,
pub solc_version: String,
/// The pallet revive edition.
pub revive_pallet_version: Option<semver::Version>,
/// The PolkaVM compiler version.
pub zk_version: semver::Version,
pub revive_version: String,
/// The PolkaVM compiler optimizer settings.
pub optimizer_settings: revive_llvm_context::OptimizerSettings,
}
@@ -22,16 +24,15 @@ impl Metadata {
/// A shortcut constructor.
pub fn new(
solc_metadata: serde_json::Value,
solc_version: semver::Version,
solc_zkvm_edition: Option<semver::Version>,
zk_version: semver::Version,
solc_version: String,
revive_pallet_version: Option<semver::Version>,
optimizer_settings: revive_llvm_context::OptimizerSettings,
) -> Self {
Self {
solc_metadata,
solc_version,
solc_zkvm_edition,
zk_version,
revive_pallet_version,
revive_version: ResolcVersion::default().long,
optimizer_settings,
}
}
+2 -5
View File
@@ -78,7 +78,6 @@ impl Contract {
mut self,
project: Project,
optimizer_settings: revive_llvm_context::OptimizerSettings,
is_system_mode: bool,
include_metadata_hash: bool,
debug_config: Option<revive_llvm_context::DebugConfig>,
) -> anyhow::Result<ContractBuild> {
@@ -90,9 +89,8 @@ impl Contract {
let metadata = Metadata::new(
self.metadata_json.take(),
version.default.clone(),
version.long.clone(),
version.l2_revision.clone(),
semver::Version::parse(env!("CARGO_PKG_VERSION")).expect("Always valid"),
optimizer.settings().to_owned(),
);
let metadata_json = serde_json::to_value(&metadata).expect("Always valid");
@@ -127,8 +125,7 @@ impl Contract {
context.set_solidity_data(revive_llvm_context::PolkaVMContextSolidityData::default());
match self.ir {
IR::Yul(_) => {
let yul_data = revive_llvm_context::PolkaVMContextYulData::new(is_system_mode);
context.set_yul_data(yul_data);
context.set_yul_data(Default::default());
}
IR::EVMLA(_) => {
let evmla_data = revive_llvm_context::PolkaVMContextEVMLAData::new(version.default);
-6
View File
@@ -64,9 +64,7 @@ impl Project {
pub fn compile(
self,
optimizer_settings: revive_llvm_context::OptimizerSettings,
is_system_mode: bool,
include_metadata_hash: bool,
bytecode_encoding_testing: bool,
debug_config: Option<revive_llvm_context::DebugConfig>,
) -> anyhow::Result<Build> {
let project = self.clone();
@@ -80,9 +78,7 @@ impl Project {
let process_input = ProcessInput::new(
contract,
project.clone(),
is_system_mode,
include_metadata_hash,
bytecode_encoding_testing,
optimizer_settings.clone(),
debug_config.clone(),
);
@@ -255,7 +251,6 @@ impl revive_llvm_context::PolkaVMDependency for Project {
project: Self,
identifier: &str,
optimizer_settings: revive_llvm_context::OptimizerSettings,
is_system_mode: bool,
include_metadata_hash: bool,
debug_config: Option<revive_llvm_context::DebugConfig>,
) -> anyhow::Result<String> {
@@ -275,7 +270,6 @@ impl revive_llvm_context::PolkaVMDependency for Project {
.compile(
project,
optimizer_settings,
is_system_mode,
include_metadata_hash,
debug_config,
)
+15 -23
View File
@@ -58,10 +58,6 @@ pub struct Arguments {
#[structopt(long = "fallback-Oz")]
pub fallback_to_optimizing_for_size: bool,
/// Disable the system request memoization.
#[structopt(long = "disable-system-request-memoization")]
pub disable_system_request_memoization: bool,
/// Disable the `solc` optimizer.
/// Use it if your project uses the `MSIZE` instruction, or in other cases.
/// Beware that it will prevent libraries from being inlined.
@@ -75,7 +71,7 @@ pub struct Arguments {
pub solc: Option<String>,
/// The EVM target version to generate IR for.
/// See https://github.com/xermicus/revive/blob/main/crates/common/src/evm_version.rs for reference.
/// See https://github.com/paritytech/revive/blob/main/crates/common/src/evm_version.rs for reference.
#[structopt(long = "evm-version")]
pub evm_version: Option<String>,
@@ -119,13 +115,6 @@ pub struct Arguments {
#[structopt(long = "force-evmla")]
pub force_evmla: bool,
/// Enable system contract compilation mode.
/// In this mode PolkaVM extensions are enabled. For example, calls to addresses `0xFFFF` and below
/// are substituted by special PolkaVM instructions.
/// In the Yul mode, the `verbatim_*` instruction family is available.
#[structopt(long = "system-mode")]
pub is_system_mode: bool,
/// Set metadata hash mode.
/// The only supported value is `none` that disables appending the metadata hash.
/// Is enabled by default.
@@ -185,6 +174,20 @@ impl Arguments {
anyhow::bail!("No other options are allowed while getting the compiler version.");
}
#[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");
}
#[cfg(debug_assertions)]
if self.recursive_process
&& ((self.recursive_process_input.is_none() && std::env::args().count() > 2)
|| (self.recursive_process_input.is_some() && std::env::args().count() > 4))
{
anyhow::bail!("No other options are allowed in recursive mode.");
}
#[cfg(not(debug_assertions))]
if self.recursive_process && std::env::args().count() > 2 {
anyhow::bail!("No other options are allowed in recursive mode.");
}
@@ -243,12 +246,6 @@ impl Arguments {
if self.solc.is_some() {
anyhow::bail!("`solc` is not used in LLVM IR and PolkaVM assembly modes.");
}
if self.is_system_mode {
anyhow::bail!(
"System contract mode is not supported in LLVM IR and PolkaVM assembly modes."
);
}
}
if self.combined_json.is_some() {
@@ -295,11 +292,6 @@ impl Arguments {
"Falling back to -Oz must specified in standard JSON input settings."
);
}
if self.disable_system_request_memoization {
anyhow::bail!(
"Disabling the system request memoization must specified in standard JSON input settings."
);
}
if self.metadata_hash.is_some() {
anyhow::bail!("Metadata hash mode must specified in standard JSON input settings.");
}
+2 -11
View File
@@ -34,10 +34,9 @@ fn main_inner() -> anyhow::Result<()> {
if arguments.version {
println!(
"{} v{} (LLVM build {:?})",
"{} version {}",
env!("CARGO_PKG_DESCRIPTION"),
env!("CARGO_PKG_VERSION"),
inkwell::support::get_llvm_version()
revive_solidity::ResolcVersion::default().long
);
return Ok(());
}
@@ -106,9 +105,6 @@ fn main_inner() -> anyhow::Result<()> {
if arguments.fallback_to_optimizing_for_size {
optimizer_settings.enable_fallback_to_size();
}
if arguments.disable_system_request_memoization {
optimizer_settings.disable_system_request_memoization();
}
optimizer_settings.is_verify_each_enabled = arguments.llvm_verify_each;
optimizer_settings.is_debug_logging_enabled = arguments.llvm_debug_logging;
@@ -126,7 +122,6 @@ fn main_inner() -> anyhow::Result<()> {
input_files.as_slice(),
&mut solc,
optimizer_settings,
arguments.is_system_mode,
include_metadata_hash,
debug_config,
)
@@ -134,7 +129,6 @@ fn main_inner() -> anyhow::Result<()> {
revive_solidity::llvm_ir(
input_files.as_slice(),
optimizer_settings,
arguments.is_system_mode,
include_metadata_hash,
debug_config,
)
@@ -143,7 +137,6 @@ fn main_inner() -> anyhow::Result<()> {
&mut solc,
arguments.detect_missing_libraries,
arguments.force_evmla,
arguments.is_system_mode,
arguments.base_path,
arguments.include_paths,
arguments.allow_paths,
@@ -160,7 +153,6 @@ fn main_inner() -> anyhow::Result<()> {
!arguments.disable_solc_optimizer,
optimizer_settings,
arguments.force_evmla,
arguments.is_system_mode,
include_metadata_hash,
arguments.base_path,
arguments.include_paths,
@@ -181,7 +173,6 @@ fn main_inner() -> anyhow::Result<()> {
!arguments.disable_solc_optimizer,
optimizer_settings,
arguments.force_evmla,
arguments.is_system_mode,
include_metadata_hash,
arguments.base_path,
arguments.include_paths,
@@ -28,7 +28,7 @@ pub struct CombinedJson {
pub version: String,
/// The `resolc` compiler version.
#[serde(skip_serializing_if = "Option::is_none")]
pub zk_version: Option<String>,
pub revive_version: Option<String>,
}
impl CombinedJson {
+1 -2
View File
@@ -37,7 +37,7 @@ impl Compiler {
pub const FIRST_VIA_IR_VERSION: semver::Version = semver::Version::new(0, 8, 13);
/// The last supported version of `solc`.
pub const LAST_SUPPORTED_VERSION: semver::Version = semver::Version::new(0, 8, 26);
pub const LAST_SUPPORTED_VERSION: semver::Version = semver::Version::new(0, 8, 28);
/// A shortcut constructor.
/// Different tools may use different `executable` names. For example, the integration tester
@@ -129,7 +129,6 @@ impl Compiler {
)
})?;
output.preprocess_ast(&version, pipeline, suppressed_warnings.as_slice())?;
output.remove_evm();
Ok(output)
}
+5 -3
View File
@@ -1,10 +1,12 @@
//! The Solidity compiler pipeline type.
use crate::compiler;
use crate::compiler::version::Version as SolcVersion;
use serde::{Deserialize, Serialize};
use crate::solc::version::Version as SolcVersion;
use crate::solc::Compiler as SolcCompiler;
/// The Solidity compiler pipeline type.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[allow(non_camel_case_types)]
#[allow(clippy::upper_case_acronyms)]
pub enum Pipeline {
@@ -22,9 +22,6 @@ pub struct Optimizer {
/// Whether to try to recompile with -Oz if the bytecode is too large.
#[serde(skip_serializing)]
pub fallback_to_optimizing_for_size: Option<bool>,
/// Whether to disable the system request memoization.
#[serde(skip_serializing)]
pub disable_system_request_memoization: Option<bool>,
}
impl Optimizer {
@@ -34,14 +31,12 @@ impl Optimizer {
mode: Option<char>,
version: &semver::Version,
fallback_to_optimizing_for_size: bool,
disable_system_request_memoization: bool,
) -> Self {
Self {
enabled,
mode,
details: Some(Details::disabled(version)),
fallback_to_optimizing_for_size: Some(fallback_to_optimizing_for_size),
disable_system_request_memoization: Some(disable_system_request_memoization),
}
}
@@ -66,9 +61,6 @@ impl TryFrom<&Optimizer> for revive_llvm_context::OptimizerSettings {
if value.fallback_to_optimizing_for_size.unwrap_or_default() {
result.enable_fallback_to_size();
}
if value.disable_system_request_memoization.unwrap_or_default() {
result.disable_system_request_memoization();
}
Ok(result)
}
}
@@ -37,8 +37,13 @@ pub enum Flag {
/// The EVM legacy assembly JSON.
#[serde(rename = "evm.legacyAssembly")]
EVMLA,
#[serde(rename = "evm.bytecode")]
EVMBC,
#[serde(rename = "evm.deployedBytecode")]
EVMDBC,
/// The assembly code
#[serde(rename = "evm.assembly")]
Assembly,
}
impl From<SolcPipeline> for Flag {
@@ -62,7 +67,9 @@ impl std::fmt::Display for Flag {
Self::AST => write!(f, "ast"),
Self::Yul => write!(f, "irOptimized"),
Self::EVMLA => write!(f, "evm.legacyAssembly"),
Self::EVMBC => write!(f, "evm.bytecode"),
Self::EVMDBC => write!(f, "evm.deployedBytecode"),
Self::Assembly => write!(f, "evm.assembly"),
}
}
}
@@ -28,6 +28,7 @@ impl File {
Self {
per_file: Some(HashSet::from_iter([SelectionFlag::AST])),
per_contract: Some(HashSet::from_iter([
SelectionFlag::EVMBC,
SelectionFlag::EVMDBC,
SelectionFlag::MethodIdentifiers,
SelectionFlag::Metadata,
@@ -20,15 +20,19 @@ use self::extra_metadata::ExtraMetadata;
#[serde(rename_all = "camelCase")]
pub struct EVM {
/// The contract EVM legacy assembly code.
#[serde(rename = "legacyAssembly")]
#[serde(rename = "legacyAssembly", skip_serializing_if = "Option::is_none")]
pub assembly: Option<Assembly>,
/// The contract PolkaVM assembly code.
#[serde(rename = "assembly")]
#[serde(rename = "assembly", skip_serializing_if = "Option::is_none")]
pub assembly_text: Option<String>,
/// The contract bytecode.
/// Is reset by that of PolkaVM before yielding the compiled project artifacts.
#[serde(skip_serializing_if = "Option::is_none")]
pub bytecode: Option<Bytecode>,
/// The contract deployed bytecode.
/// The deployed bytecode of the contract.
/// It is overwritten with the PolkaVM blob before yielding the compiled project artifacts.
/// Hence it will be the same as the runtime code but we keep both for compatibility reasons.
#[serde(skip_serializing_if = "Option::is_none")]
pub deployed_bytecode: Option<DeployedBytecode>,
/// The contract function signatures.
#[serde(default, skip_serializing_if = "Option::is_none")]
@@ -42,6 +46,7 @@ impl EVM {
/// Sets the PolkaVM assembly and bytecode.
pub fn modify(&mut self, assembly_text: String, bytecode: String) {
self.assembly_text = Some(assembly_text);
self.bytecode = Some(Bytecode::new(bytecode));
self.bytecode = Some(Bytecode::new(bytecode.clone()));
self.deployed_bytecode = Some(DeployedBytecode::new(bytecode));
}
}
@@ -45,7 +45,7 @@ pub struct Output {
pub long_version: Option<String>,
/// The `resolc` compiler version.
#[serde(skip_serializing_if = "Option::is_none")]
pub zk_version: Option<String>,
pub revive_version: Option<String>,
}
impl Output {
@@ -138,19 +138,6 @@ impl Output {
))
}
/// Removes EVM artifacts to prevent their accidental usage.
pub fn remove_evm(&mut self) {
if let Some(files) = self.contracts.as_mut() {
for (_, file) in files.iter_mut() {
for (_, contract) in file.iter_mut() {
if let Some(evm) = contract.evm.as_mut() {
evm.bytecode = None;
}
}
}
}
}
/// Traverses the AST and returns the list of additional errors and warnings.
pub fn preprocess_ast(
&mut self,
+156 -40
View File
@@ -3,6 +3,9 @@ use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::Mutex;
use once_cell::sync::Lazy;
use crate::compiler::pipeline::Pipeline as SolcPipeline;
use crate::compiler::solc::SolcCompiler;
@@ -14,6 +17,27 @@ use crate::compiler::standard_json::output::Output as SolcStandardJsonOutput;
use crate::compiler::Compiler;
use crate::project::Project;
use crate::warning::Warning;
use crate::solc::pipeline::Pipeline as SolcPipeline;
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 as SolcCompiler;
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);
static EVM_RUNTIME_BLOB_CACHE: Lazy<Mutex<HashMap<CachedBlob, Vec<u8>>>> =
Lazy::new(Default::default);
#[derive(Hash, PartialEq, Eq)]
struct CachedBlob {
contract_name: String,
solc_optimizer_enabled: bool,
pipeline: SolcPipeline,
}
/// Checks if the required executables are present in `${PATH}`.
fn check_dependencies() {
@@ -80,7 +104,6 @@ pub fn build_solidity_with_options(
None,
&solc_version.default,
false,
false,
),
None,
pipeline == SolcPipeline::Yul,
@@ -91,24 +114,20 @@ pub fn build_solidity_with_options(
let project = output.try_to_project(sources, libraries, pipeline, &solc_version, None)?;
let build: crate::Build = project.compile(optimizer_settings, false, false, false, None)?;
build.write_to_standard_json(
&mut output,
&solc_version,
&semver::Version::from_str(env!("CARGO_PKG_VERSION"))?,
)?;
let build: crate::Build = project.compile(optimizer_settings, false, None)?;
build.write_to_standard_json(&mut output, &solc_version)?;
Ok(output)
}
/// Build a Solidity contract and get the EVM bin-runtime.
/// Build a Solidity contract and get the EVM code
pub fn build_solidity_with_options_evm(
sources: BTreeMap<String, String>,
libraries: BTreeMap<String, BTreeMap<String, String>>,
remappings: Option<BTreeSet<String>>,
pipeline: SolcPipeline,
solc_optimizer_enabled: bool,
) -> anyhow::Result<BTreeMap<String, DeployedBytecode>> {
) -> anyhow::Result<BTreeMap<String, (Bytecode, DeployedBytecode)>> {
check_dependencies();
inkwell::support::enable_llvm_pretty_stack_trace();
@@ -130,7 +149,6 @@ pub fn build_solidity_with_options_evm(
None,
&solc_version.default,
false,
false,
),
None,
pipeline == SolcPipeline::Yul,
@@ -144,9 +162,12 @@ pub fn build_solidity_with_options_evm(
for (_, file) in files.iter_mut() {
for (name, contract) in file.iter_mut() {
if let Some(evm) = contract.evm.as_mut() {
if let Some(deployed_bytecode) = evm.deployed_bytecode.as_ref() {
contracts.insert(name.clone(), deployed_bytecode.clone());
}
let (Some(bytecode), Some(deployed_bytecode)) =
(evm.bytecode.as_ref(), evm.deployed_bytecode.as_ref())
else {
continue;
};
contracts.insert(name.clone(), (bytecode.clone(), deployed_bytecode.clone()));
}
}
}
@@ -177,13 +198,7 @@ pub fn build_solidity_and_detect_missing_libraries(
libraries.clone(),
None,
SolcStandardJsonInputSettingsSelection::new_required(pipeline),
SolcStandardJsonInputSettingsOptimizer::new(
true,
None,
&solc_version.default,
false,
false,
),
SolcStandardJsonInputSettingsOptimizer::new(true, None, &solc_version.default, false),
None,
pipeline == SolcPipeline::Yul,
None,
@@ -194,11 +209,7 @@ pub fn build_solidity_and_detect_missing_libraries(
let project = output.try_to_project(sources, libraries, pipeline, &solc_version, None)?;
let missing_libraries = project.get_missing_libraries();
missing_libraries.write_to_standard_json(
&mut output,
&solc.version()?,
&semver::Version::from_str(env!("CARGO_PKG_VERSION"))?,
)?;
missing_libraries.write_to_standard_json(&mut output, &solc.version()?)?;
Ok(output)
}
@@ -211,12 +222,9 @@ pub fn build_yul(source_code: &str) -> anyhow::Result<()> {
revive_llvm_context::initialize_target(revive_llvm_context::Target::PVM);
let optimizer_settings = revive_llvm_context::OptimizerSettings::none();
let project = Project::try_from_yul_string::<SolcCompiler>(
PathBuf::from("test.yul").as_path(),
source_code,
None,
)?;
let _build = project.compile(optimizer_settings, false, false, false, None)?;
let project =
Project::try_from_yul_string::<SolcCompiler>(PathBuf::from("test.yul").as_path(), source_code, None)?;
let _build = project.compile(optimizer_settings, false, None)?;
Ok(())
}
@@ -227,14 +235,14 @@ pub fn check_solidity_warning(
warning_substring: &str,
libraries: BTreeMap<String, BTreeMap<String, String>>,
pipeline: SolcPipeline,
skip_for_zkvm_edition: bool,
skip_for_revive_edition: bool,
suppressed_warnings: Option<Vec<Warning>>,
) -> anyhow::Result<bool> {
check_dependencies();
let mut solc = SolcCompiler::new(SolcCompiler::DEFAULT_EXECUTABLE_NAME.to_owned())?;
let solc_version = solc.version()?;
if skip_for_zkvm_edition && solc_version.l2_revision.is_some() {
if skip_for_revive_edition && solc_version.l2_revision.is_some() {
return Ok(true);
}
@@ -246,13 +254,7 @@ pub fn check_solidity_warning(
libraries,
None,
SolcStandardJsonInputSettingsSelection::new_required(pipeline),
SolcStandardJsonInputSettingsOptimizer::new(
true,
None,
&solc_version.default,
false,
false,
),
SolcStandardJsonInputSettingsOptimizer::new(true, None, &solc_version.default, false),
None,
pipeline == SolcPipeline::Yul,
suppressed_warnings,
@@ -267,3 +269,117 @@ pub fn check_solidity_warning(
Ok(contains_warning)
}
/// 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, 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> {
compile_evm(contract_name, source_code, true, true)
}
/// Compile the EVM bin of `contract_name` found in given `source_code`.
/// The `solc` optimizer will be enabled
pub fn compile_evm_deploy_code(
contract_name: &str,
source_code: &str,
solc_optimizer_enabled: bool,
) -> Vec<u8> {
compile_evm(contract_name, source_code, solc_optimizer_enabled, false)
}
fn compile_evm(
contract_name: &str,
source_code: &str,
solc_optimizer_enabled: bool,
runtime: bool,
) -> Vec<u8> {
let pipeline = SolcPipeline::Yul;
let id = CachedBlob {
contract_name: contract_name.to_owned(),
pipeline,
solc_optimizer_enabled,
};
let cache = if runtime {
&EVM_RUNTIME_BLOB_CACHE
} else {
&EVM_BLOB_CACHE
};
if let Some(blob) = cache.lock().unwrap().get(&id) {
return blob.clone();
}
let file_name = "contract.sol";
let contracts = build_solidity_with_options_evm(
[(file_name.into(), source_code.into())].into(),
Default::default(),
None,
pipeline,
solc_optimizer_enabled,
)
.expect("source should compile");
let object = &contracts
.get(contract_name)
.unwrap_or_else(|| panic!("contract '{}' didn't produce bin-runtime", contract_name));
let code = if runtime {
object.1.object.as_str()
} else {
object.0.object.as_str()
};
let blob = hex::decode(code).expect("code shold be hex encoded");
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: SolcPipeline,
) -> Vec<u8> {
let id = CachedBlob {
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 = 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
}
@@ -3,7 +3,7 @@
"version": "1.0.0",
"title": "resolc CLI Tests",
"description": "Auto tests for verifying resolc CLI",
"repository": "https://github.com/xermicus/revive",
"repository": "https://github.com/paritytech/revive",
"main": "index.js",
"private": true,
"scripts": {
+30
View File
@@ -0,0 +1,30 @@
//! The resolc compiler version.
use serde::Deserialize;
use serde::Serialize;
/// The resolc compiler version.
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Version {
/// The long version string.
pub long: String,
/// The short `semver`.
pub default: semver::Version,
/// The LLVM version string.
pub llvm: semver::Version,
}
impl Default for Version {
fn default() -> Self {
let default = semver::Version::parse(env!("CARGO_PKG_VERSION")).expect("Always valid");
let commit = env!("GIT_COMMIT_HASH");
let (llvm_major, llvm_minor, llvm_patch) = inkwell::support::get_llvm_version();
let llvm = semver::Version::new(llvm_major as u64, llvm_minor as u64, llvm_patch as u64);
Self {
long: format!("{default}+commit.{commit}.llvm-{llvm}"),
default,
llvm,
}
}
}
@@ -125,13 +125,6 @@ impl FunctionCall {
let location = self.location;
match self.name {
Name::UserDefined(name)
if name.starts_with(
revive_llvm_context::PolkaVMFunction::ZKSYNC_NEAR_CALL_ABI_PREFIX,
) && context.is_system_mode() =>
{
unimplemented!();
}
Name::UserDefined(name) => {
let mut values = Vec::with_capacity(self.arguments.len());
for argument in self.arguments.into_iter().rev() {
@@ -501,25 +494,30 @@ impl FunctionCall {
)
.map(|_| None)
}
Name::LoadImmutable => todo!(),
Name::LoadImmutable => {
let mut arguments = self.pop_arguments::<D, 1>(context)?;
let key = arguments[0].original.take().ok_or_else(|| {
anyhow::anyhow!("{} `load_immutable` literal is missing", location)
})?;
let offset = context
.solidity_mut()
.get_or_allocate_immutable(key.as_str())
/ revive_common::BYTE_LENGTH_WORD;
let index = context.xlen_type().const_int(offset as u64, false);
revive_llvm_context::polkavm_evm_immutable::load(context, index).map(Some)
}
Name::SetImmutable => {
let mut arguments = self.pop_arguments::<D, 3>(context)?;
let key = arguments[1].original.take().ok_or_else(|| {
anyhow::anyhow!("{} `load_immutable` literal is missing", location)
})?;
if key.as_str() == "library_deploy_address" {
return Ok(None);
}
let offset = context.solidity_mut().allocate_immutable(key.as_str());
let index = context.word_const(offset as u64);
let offset = context.solidity_mut().allocate_immutable(key.as_str())
/ revive_common::BYTE_LENGTH_WORD;
let index = context.xlen_type().const_int(offset as u64, false);
let value = arguments[2].value.into_int_value();
revive_llvm_context::polkavm_evm_immutable::store(context, index, value)
.map(|_| None)
}
Name::CallDataLoad => {
let arguments = self.pop_arguments_llvm::<D, 1>(context)?;
@@ -831,6 +829,7 @@ impl FunctionCall {
value,
input_offset,
input_length,
None,
)
.map(Some)
}
@@ -842,7 +841,7 @@ impl FunctionCall {
let input_length = arguments[2].into_int_value();
let salt = arguments[3].into_int_value();
revive_llvm_context::polkavm_evm_create::create2(
revive_llvm_context::polkavm_evm_create::create(
context,
value,
input_offset,
@@ -912,7 +911,9 @@ impl FunctionCall {
let address = arguments[0].into_int_value();
revive_llvm_context::polkavm_evm_ether_gas::balance(context, address).map(Some)
}
Name::SelfBalance => todo!(),
Name::SelfBalance => {
revive_llvm_context::polkavm_evm_ether_gas::self_balance(context).map(Some)
}
Name::GasLimit => {
revive_llvm_context::polkavm_evm_contract_context::gas_limit(context).map(Some)
@@ -962,9 +963,7 @@ impl FunctionCall {
location
);
}
Name::MSize => {
revive_llvm_context::polkavm_evm_contract_context::msize(context).map(Some)
}
Name::MSize => revive_llvm_context::polkavm_evm_memory::msize(context).map(Some),
Name::Verbatim {
input_size,
@@ -92,37 +92,7 @@ impl FunctionDefinition {
}
}
let (mut arguments, next) = Identifier::parse_typed_list(lexer, None)?;
if identifier
.inner
.contains(revive_llvm_context::PolkaVMFunction::ZKSYNC_NEAR_CALL_ABI_PREFIX)
{
if arguments.is_empty() {
return Err(ParserError::InvalidNumberOfArguments {
location,
identifier: identifier.inner,
expected: 1,
found: arguments.len(),
}
.into());
}
arguments.remove(0);
}
if identifier
.inner
.contains(revive_llvm_context::PolkaVMFunction::ZKSYNC_NEAR_CALL_ABI_EXCEPTION_HANDLER)
&& !arguments.is_empty()
{
return Err(ParserError::InvalidNumberOfArguments {
location,
identifier: identifier.inner,
expected: 0,
found: arguments.len(),
}
.into());
}
let (arguments, next) = Identifier::parse_typed_list(lexer, None)?;
match crate::yul::parser::take_or_next(next, lexer)? {
Token {
lexeme: Lexeme::Symbol(Symbol::ParenthesisRight),
@@ -234,12 +204,7 @@ where
})
.collect();
let function_type = context.function_type(
argument_types,
self.result.len(),
self.identifier
.starts_with(revive_llvm_context::PolkaVMFunction::ZKSYNC_NEAR_CALL_ABI_PREFIX),
);
let function_type = context.function_type(argument_types, self.result.len());
let function = context.add_function(
self.identifier.as_str(),
@@ -310,23 +275,12 @@ where
yul_type.into_llvm(context)
})
.collect();
for (mut index, argument) in self.arguments.iter().enumerate() {
for (index, argument) in self.arguments.iter().enumerate() {
let pointer = context.build_alloca(argument_types[index], argument.inner.as_str());
context
.current_function()
.borrow_mut()
.insert_stack_pointer(argument.inner.clone(), pointer);
if self
.identifier
.starts_with(revive_llvm_context::PolkaVMFunction::ZKSYNC_NEAR_CALL_ABI_PREFIX)
&& matches!(
context.current_function().borrow().r#return(),
revive_llvm_context::PolkaVMFunctionReturn::Compound { .. }
)
&& context.is_system_mode()
{
index += 1;
}
context.build_store(
pointer,
context.current_function().borrow().get_nth_param(index),
@@ -354,13 +308,6 @@ where
let return_value = context.build_load(pointer, "return_value")?;
context.build_return(Some(&return_value));
}
revive_llvm_context::PolkaVMFunctionReturn::Compound { pointer, .. }
if context.current_function().borrow().name().starts_with(
revive_llvm_context::PolkaVMFunction::ZKSYNC_NEAR_CALL_ABI_PREFIX,
) =>
{
context.build_return(Some(&pointer.value));
}
revive_llvm_context::PolkaVMFunctionReturn::Compound { pointer, .. } => {
let return_value = context.build_load(pointer, "return_value")?;
context.build_return(Some(&return_value));
@@ -524,80 +471,6 @@ object "Test" {
);
}
#[test]
fn error_invalid_number_of_arguments_near_call_abi() {
let input = r#"
object "Test" {
code {
{
return(0, 0)
}
}
object "Test_deployed" {
code {
{
return(0, 0)
}
function ZKSYNC_NEAR_CALL_test() -> result {
result := 42
}
}
}
}
"#;
let mut lexer = Lexer::new(input.to_owned());
let result = Object::parse(&mut lexer, None);
assert_eq!(
result,
Err(Error::InvalidNumberOfArguments {
location: Location::new(14, 22),
identifier: "ZKSYNC_NEAR_CALL_test".to_owned(),
expected: 1,
found: 0,
}
.into())
);
}
#[test]
fn error_invalid_number_of_arguments_near_call_abi_catch() {
let input = r#"
object "Test" {
code {
{
return(0, 0)
}
}
object "Test_deployed" {
code {
{
return(0, 0)
}
function ZKSYNC_CATCH_NEAR_CALL(length) {
revert(0, length)
}
}
}
}
"#;
let mut lexer = Lexer::new(input.to_owned());
let result = Object::parse(&mut lexer, None);
assert_eq!(
result,
Err(Error::InvalidNumberOfArguments {
location: Location::new(14, 22),
identifier: "ZKSYNC_CATCH_NEAR_CALL".to_owned(),
expected: 0,
found: 1,
}
.into())
);
}
#[test]
fn error_reserved_identifier() {
let input = r#"
@@ -183,6 +183,7 @@ where
&mut self,
context: &mut revive_llvm_context::PolkaVMContext<D>,
) -> anyhow::Result<()> {
revive_llvm_context::PolkaVMImmutableDataLoadFunction.declare(context)?;
let mut entry = revive_llvm_context::PolkaVMEntryFunction::default();
entry.declare(context)?;
@@ -199,6 +200,7 @@ where
revive_llvm_context::PolkaVMFunctionDeployCode,
revive_llvm_context::PolkaVMFunctionRuntimeCode,
revive_llvm_context::PolkaVMFunctionEntry,
revive_llvm_context::PolkaVMFunctionImmutableDataLoad,
]
.into_iter()
{
@@ -216,6 +218,7 @@ where
fn into_llvm(self, context: &mut revive_llvm_context::PolkaVMContext<D>) -> anyhow::Result<()> {
if self.identifier.ends_with("_deployed") {
revive_llvm_context::PolkaVMImmutableDataLoadFunction.into_llvm(context)?;
revive_llvm_context::PolkaVMRuntimeCodeFunction::new(self.code).into_llvm(context)?;
} else {
revive_llvm_context::PolkaVMDeployCodeFunction::new(self.code).into_llvm(context)?;