remove superfluous byte swap in linkersymbol builtin translation (#455)

- Remove the superfluous byte swap in the `linkersymbol` builtin
translation.
- Support testing the `linkersymbol` builtin translation in the runner
specs.

---------

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
This commit is contained in:
xermicus authored and GitHub committed 2026-01-15 12:43:46 +01:00
1 parent 2d85ca9755
commit 289af875db
12 files changed
+498 -345

No files matched your search

+1
View File
@@ -11,6 +11,7 @@ Supported `polkadot-sdk` rev: `unstable2507`
### Fixed
- OOB access in `calldataload` and `calldatacopy` should always produce zero values instead of consuming all gas.
- The superfluous byte swap in `linkersymbol`.
## v0.6.0
Generated
+377 -334
View File
File diff suppressed because it is too large. Load diff
+9
View File
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;
library L {
function f() public returns(uint r) {
r = 10;
}
}
+59
View File
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;
import "contracts/Library.sol";
/* runner.json
{
"differential": false,
"actions": [
{
"Instantiate": {
"origin": "Bob",
"code": {
"Solidity": {
"contract": "L",
"path": "contracts/Library.sol"
}
}
}
},
{
"Instantiate": {
"code": {
"Solidity": {
"contract": "Linked",
"path": "contracts/Linked.sol",
"libraries": {
"contracts/Library.sol": {
"L": "0x17bb6d1a8161a52422f86e4460600bdbefc1becd"
}
}
}
}
}
},
{
"Call": {
"dest": {
"Instantiated": 1
},
"data": "dffeadd0"
}
},
{
"VerifyCall": {
"success": true,
"output": "000000000000000000000000000000000000000000000000000000000000000a"
}
}
]
}
*/
contract Linked {
function main() public returns (uint) {
return L.f();
}
}
+9 -3
View File
@@ -17,7 +17,7 @@ impl Contract {
pub fn build(calldata: Vec<u8>, name: &'static str, code: &str) -> Self {
Self {
name,
evm_runtime: compile_evm_bin_runtime(name, code),
evm_runtime: compile_evm_bin_runtime(name, code, Default::default()),
pvm_runtime: compile_blob(name, code),
calldata,
yul: compile_to_yul(name, code, true),
@@ -27,8 +27,14 @@ impl Contract {
pub fn build_size_opt(calldata: Vec<u8>, name: &'static str, code: &str) -> Self {
Self {
name,
evm_runtime: compile_evm_bin_runtime(name, code),
pvm_runtime: compile_blob_with_options(name, code, true, OptimizerSettings::size()),
evm_runtime: compile_evm_bin_runtime(name, code, Default::default()),
pvm_runtime: compile_blob_with_options(
name,
code,
true,
OptimizerSettings::size(),
Default::default(),
),
calldata,
yul: compile_to_yul(name, code, true),
}
+3
View File
@@ -67,6 +67,7 @@ test_spec!(memory_bounds, "MemoryBounds", "MemoryBounds.sol");
test_spec!(selfdestruct, "Selfdestruct", "Selfdestruct.sol");
test_spec!(clz, "CountLeadingZeros", "CountLeadingZeros.sol");
test_spec!(call_gas, "CallGas", "CallGas.sol");
test_spec!(linker_symbol, "Linked", "Linked.sol");
fn instantiate(path: &str, contract: &str) -> Vec<SpecsAction> {
vec![Instantiate {
@@ -78,6 +79,7 @@ fn instantiate(path: &str, contract: &str) -> Vec<SpecsAction> {
path: Some(path.into()),
contract: contract.to_string(),
solc_optimizer: None,
libraries: Default::default(),
},
data: vec![],
salt: OptionalHex::default(),
@@ -372,6 +374,7 @@ fn ext_code_size() {
path: Some("contracts/Baseline.sol".into()),
contract: "Baseline".to_string(),
solc_optimizer: None,
libraries: Default::default(),
},
data: vec![],
salt: OptionalHex::from([0; 32]),
@@ -748,7 +748,7 @@ impl<'ctx> Context<'ctx> {
&self,
pointer: Pointer<'ctx>,
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>> {
let address = self.build_byte_swap(self.build_load(pointer, "address_pointer")?)?;
let address = self.build_byte_swap(self.build_load(pointer, "address_value")?)?;
Ok(self
.builder()
.build_int_z_extend(address.into_int_value(), self.word_type(), "address_zext")?
+10 -1
View File
@@ -163,7 +163,16 @@ pub fn linker_symbol<'ctx>(
context.integer_type(revive_common::BIT_LENGTH_ETH_ADDRESS),
Default::default(),
);
context.build_load_address(context.get_global(path)?.into())
let symbol = context.get_global(path)?;
let value = context.build_load(symbol.into(), path)?;
let value = context.builder().build_int_z_extend(
value.into_int_value(),
context.word_type(),
&format!("{path}_zext"),
)?;
Ok(value.into())
}
/// The runtime implements gas as `u64` so we clip the stipend to `u64::MAX`.
+19 -5
View File
@@ -337,6 +337,7 @@ pub fn compile_blob(contract_name: &str, source_code: &str) -> Vec<u8> {
source_code,
true,
OptimizerSettings::cycles(),
Default::default(),
)
}
@@ -346,6 +347,7 @@ pub fn compile_blob_with_options(
source_code: &str,
solc_optimizer_enabled: bool,
optimizer_settings: OptimizerSettings,
libraries: SolcStandardJsonInputSettingsLibraries,
) -> Vec<u8> {
let id = CachedBlob {
contract_name: contract_name.to_owned(),
@@ -364,7 +366,7 @@ pub fn compile_blob_with_options(
file_name.to_owned(),
SolcStandardJsonInputSource::from(source_code.to_owned()),
)]),
Default::default(),
libraries,
Default::default(),
optimizer_settings,
solc_optimizer_enabled,
@@ -391,8 +393,12 @@ pub fn compile_blob_with_options(
/// 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)
pub fn compile_evm_bin_runtime(
contract_name: &str,
source_code: &str,
libraries: SolcStandardJsonInputSettingsLibraries,
) -> Vec<u8> {
compile_evm(contract_name, source_code, true, true, libraries)
}
/// Compile the EVM bin of `contract_name` found in given `source_code`.
@@ -400,8 +406,15 @@ pub fn compile_evm_deploy_code(
contract_name: &str,
source_code: &str,
solc_optimizer_enabled: bool,
libraries: SolcStandardJsonInputSettingsLibraries,
) -> Vec<u8> {
compile_evm(contract_name, source_code, solc_optimizer_enabled, false)
compile_evm(
contract_name,
source_code,
solc_optimizer_enabled,
false,
libraries,
)
}
/// Convert `(path, solidity)` tuples to a standard JSON input source.
@@ -434,6 +447,7 @@ fn compile_evm(
source_code: &str,
solc_optimizer_enabled: bool,
runtime: bool,
libraries: SolcStandardJsonInputSettingsLibraries,
) -> Vec<u8> {
let id = CachedBlob {
contract_name: contract_name.to_owned(),
@@ -457,7 +471,7 @@ fn compile_evm(
file_name.into(),
SolcStandardJsonInputSource::from(source_code.to_owned()),
)]),
Default::default(),
libraries,
Default::default(),
solc_optimizer_enabled,
)
+2 -1
View File
@@ -17,7 +17,7 @@ path = "src/main.rs"
[features]
std = ["polkadot-sdk/std"]
default = ["solidity"]
solidity = ["resolc", "revive-differential", "revive-llvm-context"]
solidity = ["resolc", "revive-differential", "revive-llvm-context", "revive-solc-json-interface"]
[dependencies]
env_logger = { workspace = true }
@@ -42,3 +42,4 @@ polkadot-sdk.features = [
resolc = { workspace = true, optional = true }
revive-differential = { workspace = true, optional = true }
revive-llvm-context = { workspace = true, optional = true }
revive-solc-json-interface = { workspace = true, optional = true }
+6
View File
@@ -38,6 +38,8 @@ use polkadot_sdk::{
sp_keystore::{testing::MemoryKeystore, KeystoreExt},
sp_runtime::AccountId32,
};
#[cfg(feature = "resolc")]
use revive_solc_json_interface::SolcStandardJsonInputSettingsLibraries;
use serde::{Deserialize, Serialize};
use crate::runtime::*;
@@ -271,6 +273,8 @@ pub enum Code {
path: Option<std::path::PathBuf>,
solc_optimizer: Option<bool>,
contract: String,
#[serde(default)]
libraries: SolcStandardJsonInputSettingsLibraries,
},
/// Read the contract blob from disk
Path(std::path::PathBuf),
@@ -294,6 +298,7 @@ impl From<Code> for pallet_revive::Code {
path,
contract,
solc_optimizer,
libraries,
} => {
let Some(path) = path else {
panic!("Solidity source of contract '{contract}' missing path");
@@ -306,6 +311,7 @@ impl From<Code> for pallet_revive::Code {
&source_code,
solc_optimizer.unwrap_or(true),
revive_llvm_context::OptimizerSettings::cycles(),
libraries,
))
}
Code::Path(path) => pallet_revive::Code::Upload(std::fs::read(path).unwrap()),
+2
View File
@@ -316,6 +316,7 @@ impl Specs {
path: Some(path),
solc_optimizer,
contract,
libraries,
} = code
else {
panic!("the differential runner requires Code::Solidity source");
@@ -335,6 +336,7 @@ impl Specs {
&contract,
&solidity_source,
solc_optimizer.unwrap_or(true),
libraries,
)),
Err(err) => panic!(
"failed to read solidity source\n . path: '{}'\n . error: {:?}",