mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-04-22 02:07:55 +00:00
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:
@@ -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);
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user