mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-05-09 23:28:00 +00:00
support full storage key space (#100)
- The storage pointer values will no longer be truncated to the register size, allowing for the use of arbitrary storage keys - Failed storage value reads will now guarantee to return the zero value
This commit is contained in:
@@ -2,9 +2,9 @@
|
||||
"Baseline": 989,
|
||||
"Computation": 4153,
|
||||
"DivisionArithmetics": 40614,
|
||||
"ERC20": 47343,
|
||||
"ERC20": 47348,
|
||||
"Events": 1781,
|
||||
"FibonacciIterative": 3035,
|
||||
"Flipper": 3393,
|
||||
"Flipper": 3448,
|
||||
"SHA1": 33553
|
||||
}
|
||||
@@ -4,11 +4,27 @@ pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"differential": true,
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {}
|
||||
}
|
||||
]
|
||||
{
|
||||
"Upload": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "ERC20"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Instantiate": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "ERC20Tester"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -82,3 +98,28 @@ contract ERC20 is IERC20 {
|
||||
emit Transfer(msg.sender, address(0), amount);
|
||||
}
|
||||
}
|
||||
|
||||
contract ERC20Tester {
|
||||
constructor() {
|
||||
address BOB = address(0xffffffffffffffffffffffffffffffffffffff);
|
||||
ERC20 token = new ERC20();
|
||||
assert(token.decimals() == 18);
|
||||
|
||||
// use call directly when code_size is implemented on pallet-revive
|
||||
|
||||
address(token).call(abi.encodeWithSignature("mint(uint256)", 300));
|
||||
assert(token.balanceOf(address(this)) == 300);
|
||||
token.transfer(BOB, 100);
|
||||
assert(token.balanceOf(address(this)) == 200);
|
||||
assert(token.balanceOf(BOB) == 100);
|
||||
|
||||
token.approve(address(this), 100);
|
||||
|
||||
token.transferFrom(address(this), BOB, 100);
|
||||
assert(token.balanceOf(BOB) == 200);
|
||||
assert(token.balanceOf(address(this)) == 100);
|
||||
|
||||
address(token).call(abi.encodeWithSignature("burn(uint256)", 100));
|
||||
assert(token.balanceOf(address(this)) == 0);
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,14 @@ pragma solidity ^0.8;
|
||||
},
|
||||
"data": "fabc9efaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "558b9f9bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -30,10 +38,18 @@ pragma solidity ^0.8;
|
||||
contract Storage {
|
||||
function transient(uint value) public returns (uint ret) {
|
||||
assembly {
|
||||
let slot := 123
|
||||
let slot := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
|
||||
tstore(slot, value)
|
||||
let success := call(0, 0, 0, 0, 0, 0, 0)
|
||||
ret := tload(slot)
|
||||
}
|
||||
}
|
||||
|
||||
function persistent(uint value) public returns (uint ret) {
|
||||
assembly {
|
||||
let slot := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
|
||||
sstore(slot, value)
|
||||
ret := sload(slot)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -669,22 +669,10 @@ where
|
||||
self.build_byte_swap(value)
|
||||
}
|
||||
AddressSpace::Storage | AddressSpace::TransientStorage => {
|
||||
let storage_key_value = self.builder().build_ptr_to_int(
|
||||
pointer.value,
|
||||
self.word_type(),
|
||||
"storage_ptr_to_int",
|
||||
)?;
|
||||
let storage_key_pointer = self.build_alloca(self.word_type(), "storage_key");
|
||||
let storage_key_pointer_casted = self.builder().build_ptr_to_int(
|
||||
storage_key_pointer.value,
|
||||
self.xlen_type(),
|
||||
"storage_key_pointer_casted",
|
||||
)?;
|
||||
self.builder()
|
||||
.build_store(storage_key_pointer.value, storage_key_value)?;
|
||||
|
||||
let storage_value_pointer =
|
||||
self.build_alloca(self.word_type(), "storage_value_pointer");
|
||||
self.build_store(storage_value_pointer, self.word_const(0))?;
|
||||
|
||||
let storage_value_length_pointer =
|
||||
self.build_alloca(self.xlen_type(), "storage_value_length_pointer");
|
||||
self.build_store(
|
||||
@@ -698,7 +686,7 @@ where
|
||||
revive_runtime_api::polkavm_imports::GET_STORAGE,
|
||||
&[
|
||||
self.xlen_type().const_int(transient as u64, false).into(),
|
||||
storage_key_pointer_casted.into(),
|
||||
pointer.to_int(self).into(),
|
||||
self.xlen_type().const_all_ones().into(),
|
||||
storage_value_pointer.to_int(self).into(),
|
||||
storage_value_length_pointer.to_int(self).into(),
|
||||
@@ -767,18 +755,6 @@ where
|
||||
self.word_type().as_basic_type_enum()
|
||||
);
|
||||
|
||||
let storage_key_value = self.builder().build_ptr_to_int(
|
||||
pointer.value,
|
||||
self.word_type(),
|
||||
"storage_ptr_to_int",
|
||||
)?;
|
||||
let storage_key_pointer = self.build_alloca(self.word_type(), "storage_key");
|
||||
let storage_key_pointer_casted = self.builder().build_ptr_to_int(
|
||||
storage_key_pointer.value,
|
||||
self.xlen_type(),
|
||||
"storage_key_pointer_casted",
|
||||
)?;
|
||||
|
||||
let storage_value_pointer = self.build_alloca(self.word_type(), "storage_value");
|
||||
let storage_value_pointer_casted = self.builder().build_ptr_to_int(
|
||||
storage_value_pointer.value,
|
||||
@@ -786,8 +762,6 @@ where
|
||||
"storage_value_pointer_casted",
|
||||
)?;
|
||||
|
||||
self.builder()
|
||||
.build_store(storage_key_pointer.value, storage_key_value)?;
|
||||
self.builder()
|
||||
.build_store(storage_value_pointer.value, value)?;
|
||||
|
||||
@@ -797,7 +771,7 @@ where
|
||||
revive_runtime_api::polkavm_imports::SET_STORAGE,
|
||||
&[
|
||||
self.xlen_type().const_int(transient as u64, false).into(),
|
||||
storage_key_pointer_casted.into(),
|
||||
pointer.to_int(self).into(),
|
||||
self.xlen_type().const_all_ones().into(),
|
||||
storage_value_pointer_casted.into(),
|
||||
self.integer_const(crate::polkavm::XLEN, 32).into(),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//! Translates the storage operations.
|
||||
|
||||
use crate::polkavm::context::address_space::AddressSpace;
|
||||
use crate::polkavm::context::pointer::Pointer;
|
||||
use crate::polkavm::context::Context;
|
||||
use crate::polkavm::Dependency;
|
||||
|
||||
@@ -13,14 +12,10 @@ pub fn load<'ctx, D>(
|
||||
where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
let position_pointer = Pointer::new_with_offset(
|
||||
context,
|
||||
AddressSpace::Storage,
|
||||
context.word_type(),
|
||||
position,
|
||||
"storage_load_position_pointer",
|
||||
);
|
||||
context.build_load(position_pointer, "storage_load_value")
|
||||
let mut slot_ptr = context.build_alloca_at_entry(context.word_type(), "slot_pointer");
|
||||
slot_ptr.address_space = AddressSpace::Storage;
|
||||
context.builder().build_store(slot_ptr.value, position)?;
|
||||
context.build_load(slot_ptr, "storage_load_value")
|
||||
}
|
||||
|
||||
/// Translates the storage store.
|
||||
@@ -32,14 +27,10 @@ pub fn store<'ctx, D>(
|
||||
where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
let position_pointer = Pointer::new_with_offset(
|
||||
context,
|
||||
AddressSpace::Storage,
|
||||
context.word_type(),
|
||||
position,
|
||||
"storage_store_position_pointer",
|
||||
);
|
||||
context.build_store(position_pointer, value)?;
|
||||
let mut slot_ptr = context.build_alloca_at_entry(context.word_type(), "slot_pointer");
|
||||
slot_ptr.address_space = AddressSpace::Storage;
|
||||
context.builder().build_store(slot_ptr.value, position)?;
|
||||
context.build_store(slot_ptr, value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -51,14 +42,10 @@ pub fn transient_load<'ctx, D>(
|
||||
where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
let position_pointer = Pointer::new_with_offset(
|
||||
context,
|
||||
AddressSpace::TransientStorage,
|
||||
context.word_type(),
|
||||
position,
|
||||
"transient_storage_load_position_pointer",
|
||||
);
|
||||
context.build_load(position_pointer, "transient_storage_load_value")
|
||||
let mut slot_ptr = context.build_alloca_at_entry(context.word_type(), "slot_pointer");
|
||||
slot_ptr.address_space = AddressSpace::TransientStorage;
|
||||
context.builder().build_store(slot_ptr.value, position)?;
|
||||
context.build_load(slot_ptr, "transient_storage_load_value")
|
||||
}
|
||||
|
||||
/// Translates the transient storage store.
|
||||
@@ -70,13 +57,9 @@ pub fn transient_store<'ctx, D>(
|
||||
where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
let position_pointer = Pointer::new_with_offset(
|
||||
context,
|
||||
AddressSpace::TransientStorage,
|
||||
context.word_type(),
|
||||
position,
|
||||
"transient_storage_store_position_pointer",
|
||||
);
|
||||
context.build_store(position_pointer, value)?;
|
||||
let mut slot_ptr = context.build_alloca_at_entry(context.word_type(), "slot_pointer");
|
||||
slot_ptr.address_space = AddressSpace::TransientStorage;
|
||||
context.builder().build_store(slot_ptr.value, position)?;
|
||||
context.build_store(slot_ptr, value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user