UserDefinedValueType.storageBytes() is correctly set

Previously it returned 32 bytes for all types, which was wasteful. This commit changes it to return
the storage bytes of the underlying type.
This commit is contained in:
hrkrshnn 2021-09-28 10:52:09 +02:00
parent ee0e3e9377
commit 62010d0ebd
8 changed files with 267 additions and 1 deletions

View File

@ -8,7 +8,7 @@ Compiler Features:
Bugfixes:
* User Defined Value Type: Fix storage layout of user defined value types for underlying types shorter than 32 bytes.
### 0.8.8 (2021-09-27)

View File

@ -1108,6 +1108,8 @@ public:
bool leftAligned() const override { return underlyingType().leftAligned(); }
bool canBeStored() const override { return underlyingType().canBeStored(); }
u256 storageSize() const override { return underlyingType().storageSize(); }
unsigned storageBytes() const override { return underlyingType().storageBytes(); }
bool isValueType() const override
{
solAssert(underlyingType().isValueType(), "");

View File

@ -0,0 +1 @@
--storage-layout

View File

@ -0,0 +1,2 @@
Warning: Source file does not specify required compiler version!
--> storage_layout_user_defined/input.sol

View File

@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL v3
type MyInt128 is int128;
type MyInt8 is int8;
contract C {
// slot 0
MyInt128 a;
MyInt128 b;
// slot 1
MyInt128 c;
MyInt8 d;
MyInt8 e;
MyInt8 f;
MyInt8 g;
// slot 2
MyInt8 h;
}

View File

@ -0,0 +1,4 @@
======= storage_layout_user_defined/input.sol:C =======
Contract Storage Layout:
{"storage":[{"astId":7,"contract":"storage_layout_user_defined/input.sol:C","label":"a","offset":0,"slot":"0","type":"t_userDefinedValueType(MyInt128)2"},{"astId":10,"contract":"storage_layout_user_defined/input.sol:C","label":"b","offset":16,"slot":"0","type":"t_userDefinedValueType(MyInt128)2"},{"astId":13,"contract":"storage_layout_user_defined/input.sol:C","label":"c","offset":0,"slot":"1","type":"t_userDefinedValueType(MyInt128)2"},{"astId":16,"contract":"storage_layout_user_defined/input.sol:C","label":"d","offset":16,"slot":"1","type":"t_userDefinedValueType(MyInt8)4"},{"astId":19,"contract":"storage_layout_user_defined/input.sol:C","label":"e","offset":17,"slot":"1","type":"t_userDefinedValueType(MyInt8)4"},{"astId":22,"contract":"storage_layout_user_defined/input.sol:C","label":"f","offset":18,"slot":"1","type":"t_userDefinedValueType(MyInt8)4"},{"astId":25,"contract":"storage_layout_user_defined/input.sol:C","label":"g","offset":19,"slot":"1","type":"t_userDefinedValueType(MyInt8)4"},{"astId":28,"contract":"storage_layout_user_defined/input.sol:C","label":"h","offset":20,"slot":"1","type":"t_userDefinedValueType(MyInt8)4"}],"types":{"t_userDefinedValueType(MyInt128)2":{"encoding":"inplace","label":"MyInt128","numberOfBytes":"16"},"t_userDefinedValueType(MyInt8)4":{"encoding":"inplace","label":"MyInt8","numberOfBytes":"1"}}}

View File

@ -0,0 +1,74 @@
type MyInt8 is int8;
type MyAddress is address;
type MyInt96 is int96;
contract C {
MyInt8 a;
MyInt8 b;
MyInt8 c;
MyAddress d;
MyAddress e;
MyAddress f;
MyInt96 g;
function storage_a() pure external returns(uint slot, uint offset) {
assembly {
slot := a.slot
offset := a.offset
}
}
function storage_b() pure external returns(uint slot, uint offset) {
assembly {
slot := b.slot
offset := b.offset
}
}
function storage_c() pure external returns(uint slot, uint offset) {
assembly {
slot := d.slot
offset := c.offset
}
}
function storage_d() pure external returns(uint slot, uint offset) {
assembly {
slot := d.slot
offset := d.offset
}
}
function storage_e() pure external returns(uint slot, uint offset) {
assembly {
slot := e.slot
offset := e.offset
}
}
function storage_f() pure external returns(uint slot, uint offset) {
assembly {
slot := f.slot
offset := f.offset
}
}
function storage_g() pure external returns(uint slot, uint offset) {
assembly {
slot := g.slot
offset := g.offset
}
}
}
// ====
// compileViaYul: also
// ----
// storage_a() -> 0, 0
// storage_b() -> 0, 1
// storage_c() -> 0, 2
// storage_d() -> 0, 3
// storage_e() -> 1, 0
// storage_f() -> 2, 0
// storage_g() -> 2, 0x14

View File

@ -0,0 +1,167 @@
type MyInt64 is int64;
struct HalfSlot {
MyInt64 a;
MyInt64 b;
}
struct RegularHalfSlot {
int64 a;
int64 b;
}
type MyAddress is address;
type MyInt96 is int96;
struct FullSlot {
MyInt96 a;
MyAddress b;
}
struct RegularFullSlot {
int96 a;
address b;
}
contract C {
HalfSlot public a;
RegularHalfSlot public ra;
HalfSlot public b;
RegularHalfSlot public rb;
HalfSlot public c;
RegularHalfSlot public rc;
FullSlot public d;
RegularFullSlot public rd;
function storage_a() pure external returns(uint slot, uint offset) {
assembly {
slot := a.slot
offset := a.offset
}
}
function storage_ra() pure external returns(uint slot, uint offset) {
assembly {
slot := ra.slot
offset := ra.offset
}
}
function storage_b() pure external returns(uint slot, uint offset) {
assembly {
slot := b.slot
offset := b.offset
}
}
function storage_rb() pure external returns(uint slot, uint offset) {
assembly {
slot := rb.slot
offset := rb.offset
}
}
function storage_c() pure external returns(uint slot, uint offset) {
assembly {
slot := c.slot
offset := c.offset
}
}
function storage_rc() pure external returns(uint slot, uint offset) {
assembly {
slot := rc.slot
offset := rc.offset
}
}
function storage_d() pure external returns(uint slot, uint offset) {
assembly {
slot := d.slot
offset := d.offset
}
}
function storage_rd() pure external returns(uint slot, uint offset) {
assembly {
slot := rd.slot
offset := rd.offset
}
}
function set_a(MyInt64 _a, MyInt64 _b) external {
a.a = _a;
a.b = _b;
}
function set_ra(int64 _a, int64 _b) external {
ra.a = _a;
ra.b = _b;
}
function set_b(MyInt64 _a, MyInt64 _b) external {
b.a = _a;
b.b = _b;
}
function set_rb(int64 _a, int64 _b) external {
rb.a = _a;
rb.b = _b;
}
function set_c(MyInt64 _a, MyInt64 _b) external {
c.a = _a;
c.b = _b;
}
function set_rc(int64 _a, int64 _b) external {
rc.a = _a;
rc.b = _b;
}
function set_d(MyInt96 _a, MyAddress _b) external {
d.a = _a;
d.b = _b;
}
function set_rd(int96 _a, address _b) external {
rd.a = _a;
rd.b = _b;
}
function read_slot(uint slot) view external returns (uint value) {
assembly {
value := sload(slot)
}
}
}
// ====
// compileViaYul: also
// ----
// storage_a() -> 0, 0
// set_a(int64,int64): 100, 200 ->
// read_slot(uint256): 0 -> 0xc80000000000000064
// storage_ra() -> 1, 0
// set_ra(int64,int64): 100, 200 ->
// read_slot(uint256): 1 -> 0xc80000000000000064
// storage_b() -> 2, 0
// set_b(int64,int64): 0, 200 ->
// read_slot(uint256): 2 -> 3689348814741910323200
// storage_rb() -> 3, 0
// set_rb(int64,int64): 0, 200 ->
// read_slot(uint256): 3 -> 3689348814741910323200
// storage_c() -> 4, 0
// set_c(int64,int64): 100, 0 ->
// read_slot(uint256): 4 -> 0x64
// storage_rc() -> 5, 0
// set_rc(int64,int64): 100, 0 ->
// read_slot(uint256): 5 -> 0x64
// storage_d() -> 6, 0
// set_d(int96,address): 39614081257132168796771975167, 1461501637330902918203684832716283019655932542975 ->
// read_slot(uint256): 6 -> -39614081257132168796771975169
// storage_rd() -> 7, 0
// set_rd(int96,address): 39614081257132168796771975167, 1461501637330902918203684832716283019655932542975 ->
// read_slot(uint256): 7 -> -39614081257132168796771975169