Skip to content

Commit

Permalink
support full storage key space (#100)
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
ermalkaleci authored Oct 28, 2024
1 parent cc38c37 commit aae2510
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 70 deletions.
4 changes: 2 additions & 2 deletions crates/integration/codesize.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"Baseline": 989,
"Computation": 4153,
"DivisionArithmetics": 40614,
"ERC20": 47343,
"ERC20": 47348,
"Events": 1781,
"FibonacciIterative": 3035,
"Flipper": 3393,
"Flipper": 3448,
"SHA1": 33553
}
49 changes: 45 additions & 4 deletions crates/integration/contracts/ERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,27 @@ pragma solidity ^0.8;

/* runner.json
{
"differential": true,
"actions": [
{
"Instantiate": {}
}
]
{
"Upload": {
"code": {
"Solidity": {
"contract": "ERC20"
}
}
}
},
{
"Instantiate": {
"code": {
"Solidity": {
"contract": "ERC20Tester"
}
}
}
}
]
}
*/

Expand Down Expand Up @@ -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);
}
}
18 changes: 17 additions & 1 deletion crates/integration/contracts/Storage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ pragma solidity ^0.8;
},
"data": "fabc9efaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
}
},
{
"Call": {
"dest": {
"Instantiated": 0
},
"data": "558b9f9bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
}
}
]
}
Expand All @@ -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)
}
}
}
34 changes: 4 additions & 30 deletions crates/llvm-context/src/polkavm/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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(),
Expand Down Expand Up @@ -767,27 +755,13 @@ 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,
self.xlen_type(),
"storage_value_pointer_casted",
)?;

self.builder()
.build_store(storage_key_pointer.value, storage_key_value)?;
self.builder()
.build_store(storage_value_pointer.value, value)?;

Expand All @@ -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(),
Expand Down
49 changes: 16 additions & 33 deletions crates/llvm-context/src/polkavm/evm/storage.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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.
Expand All @@ -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(())
}

Expand All @@ -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.
Expand All @@ -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(())
}

0 comments on commit aae2510

Please sign in to comment.