switch to the new storage API (#396)

This PR switches to the new `get_storage_or_zero` and
`set_storage_or_clear` syscalls which are more tailored towards
Solidity.

Signed-off-by: Cyrill Leutwiler <bigcyrill@hotmail.com>
This commit is contained in:
xermicus
2025-10-30 14:13:37 +01:00
committed by GitHub
parent 42cac55be8
commit 84018c18ae
5 changed files with 20 additions and 38 deletions
+2 -2
View File
@@ -2,9 +2,9 @@
"Baseline": 914,
"Computation": 2295,
"DivisionArithmetics": 14510,
"ERC20": 17499,
"ERC20": 17482,
"Events": 1674,
"FibonacciIterative": 1490,
"Flipper": 2102,
"Flipper": 2086,
"SHA1": 8158
}
@@ -157,6 +157,10 @@ fn emit_load<'ctx>(
key: BasicValueEnum<'ctx>,
transient: bool,
) -> anyhow::Result<BasicValueEnum<'ctx>> {
let is_transient = context.xlen_type().const_int(transient as u64, false);
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
let mut key = context.build_load(
super::Pointer::new(
context.word_type(),
@@ -168,33 +172,17 @@ fn emit_load<'ctx>(
if !transient {
key = context.build_byte_swap(key)?;
}
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
let length_pointer = context.build_alloca_at_entry(context.xlen_type(), "length_pointer");
context.builder().build_store(key_pointer.value, key)?;
context.build_store(value_pointer, context.word_const(0))?;
context.build_store(
length_pointer,
context
.xlen_type()
.const_int(revive_common::BYTE_LENGTH_WORD as u64, false),
)?;
let is_transient = context.xlen_type().const_int(transient as u64, false);
let arguments = [
is_transient.into(),
key_pointer.to_int(context).into(),
context.xlen_type().const_all_ones().into(),
value_pointer.to_int(context).into(),
length_pointer.to_int(context).into(),
];
context.build_runtime_call(revive_runtime_api::polkavm_imports::GET_STORAGE, &arguments);
// We do not to check the return value: Solidity assumes infallible loads.
// If a key doesn't exist the "zero" value is returned (ensured by above write).
// If a key doesn't exist the syscall returns zero.
let value = context.build_load(value_pointer, "storage_value")?;
Ok(if transient {
@@ -210,6 +198,10 @@ fn emit_store<'ctx>(
value: BasicValueEnum<'ctx>,
transient: bool,
) -> anyhow::Result<()> {
let is_transient = context.xlen_type().const_int(transient as u64, false);
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
let mut key = context.build_load(
super::Pointer::new(
context.word_type(),
@@ -224,27 +216,20 @@ fn emit_store<'ctx>(
Default::default(),
value.into_pointer_value(),
),
"key",
"value",
)?;
if !transient {
key = context.build_byte_swap(key)?;
value = context.build_byte_swap(value)?;
}
let key_pointer = context.build_alloca_at_entry(context.word_type(), "key_pointer");
let value_pointer = context.build_alloca_at_entry(context.word_type(), "value_pointer");
context.build_store(key_pointer, key)?;
context.build_store(value_pointer, value)?;
let is_transient = context.xlen_type().const_int(transient as u64, false);
let arguments = [
is_transient.into(),
key_pointer.to_int(context).into(),
context.xlen_type().const_all_ones().into(),
value_pointer.to_int(context).into(),
context.integer_const(crate::polkavm::XLEN, 32).into(),
];
context.build_runtime_call(revive_runtime_api::polkavm_imports::SET_STORAGE, &arguments);
+4 -7
View File
@@ -510,13 +510,10 @@ impl Specs {
expected,
} => {
let address = contract.to_eth_addr(&results);
let Ok(value) = Contracts::get_storage(address, key) else {
panic!("error reading storage for address {address}");
};
let Some(value) = value else {
panic!("no value at {address} key 0x{}", hex::encode(key));
};
assert_eq!(value, expected, "at key 0x{}", hex::encode(key));
let value = Contracts::get_storage(address, key)
.unwrap_or_else(|error| panic!("at {address}: {error:?}"))
.unwrap_or_else(|| vec![0; 32]);
assert_eq!(value, expected, "at {address} key 0x{}", hex::encode(key));
}
}
}
+2 -2
View File
@@ -79,7 +79,7 @@ POLKAVM_IMPORT(uint64_t, gas_price);
POLKAVM_IMPORT(void, get_immutable_data, uint32_t, uint32_t);
POLKAVM_IMPORT(uint64_t, get_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, get_storage_or_zero, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(void, hash_keccak_256, uint32_t, uint32_t, uint32_t)
@@ -99,7 +99,7 @@ POLKAVM_IMPORT(uint64_t, return_data_size)
POLKAVM_IMPORT(void, set_immutable_data, uint32_t, uint32_t);
POLKAVM_IMPORT(uint64_t, set_storage, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(uint64_t, set_storage_or_clear, uint32_t, uint32_t, uint32_t)
POLKAVM_IMPORT(void, value_transferred, uint32_t)
+2 -2
View File
@@ -42,7 +42,7 @@ pub static GAS_PRICE: &str = "gas_price";
pub static GET_IMMUTABLE_DATA: &str = "get_immutable_data";
pub static GET_STORAGE: &str = "get_storage";
pub static GET_STORAGE: &str = "get_storage_or_zero";
pub static HASH_KECCAK_256: &str = "hash_keccak_256";
@@ -62,7 +62,7 @@ pub static RETURNDATASIZE: &str = "return_data_size";
pub static SET_IMMUTABLE_DATA: &str = "set_immutable_data";
pub static SET_STORAGE: &str = "set_storage";
pub static SET_STORAGE: &str = "set_storage_or_clear";
pub static VALUE_TRANSFERRED: &str = "value_transferred";