Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
be4d2f2e
Unverified
Commit
be4d2f2e
authored
Aug 18, 2022
by
Mark Tyneway
Committed by
GitHub
Aug 18, 2022
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3254 from ethereum-optimism/state-surger/bytes32
state-surgery: implement bytes32 handling
parents
815b6779
2d933448
Changes
4
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
168 additions
and
3 deletions
+168
-3
encoding.go
state-surgery/state/encoding.go
+42
-0
state_test.go
state-surgery/state/state_test.go
+36
-1
contract.go
state-surgery/state/testdata/contract.go
+64
-2
layout.json
state-surgery/state/testdata/layout.json
+26
-0
No files found.
state-surgery/state/encoding.go
View file @
be4d2f2e
...
@@ -41,6 +41,12 @@ func EncodeStorageKeyValue(value any, entry solc.StorageLayoutEntry, storageType
...
@@ -41,6 +41,12 @@ func EncodeStorageKeyValue(value any, entry solc.StorageLayoutEntry, storageType
encoded
=
append
(
encoded
,
&
EncodedStorage
{
key
,
val
})
encoded
=
append
(
encoded
,
&
EncodedStorage
{
key
,
val
})
case
"bytes"
:
case
"bytes"
:
return
nil
,
fmt
.
Errorf
(
"%w: %s"
,
errUnimplemented
,
label
)
return
nil
,
fmt
.
Errorf
(
"%w: %s"
,
errUnimplemented
,
label
)
case
"bytes32"
:
val
,
err
:=
EncodeBytes32Value
(
value
,
entry
.
Offset
)
if
err
!=
nil
{
return
nil
,
err
}
encoded
=
append
(
encoded
,
&
EncodedStorage
{
key
,
val
})
default
:
default
:
switch
true
{
switch
true
{
case
strings
.
HasPrefix
(
label
,
"contract"
)
:
case
strings
.
HasPrefix
(
label
,
"contract"
)
:
...
@@ -137,6 +143,42 @@ func getElementEncoder(kind string) (ElementEncoder, error) {
...
@@ -137,6 +143,42 @@ func getElementEncoder(kind string) (ElementEncoder, error) {
return
nil
,
fmt
.
Errorf
(
"unsupported type: %s"
,
kind
)
return
nil
,
fmt
.
Errorf
(
"unsupported type: %s"
,
kind
)
}
}
// EncodeBytes32Value will encode a bytes32 value. The offset
// is included so that it can implement the ElementEncoder
// interface, but the offset must always be 0.
func
EncodeBytes32Value
(
value
any
,
offset
uint
)
(
common
.
Hash
,
error
)
{
if
offset
!=
0
{
return
common
.
Hash
{},
errors
.
New
(
"offset must be 0"
)
}
return
encodeBytes32Value
(
value
)
}
// encodeBytes32Value implements the encoding of a bytes32
// value into a common.Hash that is suitable for storage.
func
encodeBytes32Value
(
value
any
)
(
common
.
Hash
,
error
)
{
name
:=
reflect
.
TypeOf
(
value
)
.
Name
()
switch
name
{
case
"string"
:
str
,
ok
:=
value
.
(
string
)
if
!
ok
{
return
common
.
Hash
{},
errInvalidType
}
val
,
err
:=
hexutil
.
Decode
(
str
)
if
err
!=
nil
{
return
common
.
Hash
{},
err
}
return
common
.
BytesToHash
(
val
),
nil
case
"Hash"
:
hash
,
ok
:=
value
.
(
common
.
Hash
)
if
!
ok
{
return
common
.
Hash
{},
errInvalidType
}
return
hash
,
nil
default
:
return
common
.
Hash
{},
errInvalidType
}
}
// EncodeBoolValue will encode a boolean value given a storage
// EncodeBoolValue will encode a boolean value given a storage
// offset.
// offset.
func
EncodeBoolValue
(
value
any
,
offset
uint
)
(
common
.
Hash
,
error
)
{
func
EncodeBoolValue
(
value
any
,
offset
uint
)
(
common
.
Hash
,
error
)
{
...
...
state-surgery/state/state_test.go
View file @
be4d2f2e
...
@@ -2,6 +2,7 @@ package state_test
...
@@ -2,6 +2,7 @@ package state_test
import
(
import
(
"encoding/json"
"encoding/json"
"fmt"
"math/big"
"math/big"
"os"
"os"
"testing"
"testing"
...
@@ -51,6 +52,7 @@ func TestSetAndGetStorageSlots(t *testing.T) {
...
@@ -51,6 +52,7 @@ func TestSetAndGetStorageSlots(t *testing.T) {
values
[
"offset3"
]
=
uint32
(
0xf33d35
)
values
[
"offset3"
]
=
uint32
(
0xf33d35
)
values
[
"offset4"
]
=
uint64
(
0xd34dd34d00
)
values
[
"offset4"
]
=
uint64
(
0xd34dd34d00
)
values
[
"offset5"
]
=
new
(
big
.
Int
)
.
SetUint64
(
0x43ad0043ad0043ad
)
values
[
"offset5"
]
=
new
(
big
.
Int
)
.
SetUint64
(
0x43ad0043ad0043ad
)
values
[
"_bytes32"
]
=
common
.
Hash
{
0xff
}
addresses
:=
make
(
map
[
any
]
any
)
addresses
:=
make
(
map
[
any
]
any
)
addresses
[
big
.
NewInt
(
1
)]
=
common
.
Address
{
19
:
0xff
}
addresses
[
big
.
NewInt
(
1
)]
=
common
.
Address
{
19
:
0xff
}
...
@@ -120,6 +122,13 @@ OUTER:
...
@@ -120,6 +122,13 @@ OUTER:
res
,
err
=
contract
.
Offset4
(
&
bind
.
CallOpts
{})
res
,
err
=
contract
.
Offset4
(
&
bind
.
CallOpts
{})
case
"offset5"
:
case
"offset5"
:
res
,
err
=
contract
.
Offset5
(
&
bind
.
CallOpts
{})
res
,
err
=
contract
.
Offset5
(
&
bind
.
CallOpts
{})
case
"_bytes32"
:
res
,
err
=
contract
.
Bytes32
(
&
bind
.
CallOpts
{})
result
,
ok
:=
res
.
([
32
]
uint8
)
require
.
Equal
(
t
,
ok
,
true
)
require
.
Nil
(
t
,
err
)
require
.
Equal
(
t
,
common
.
BytesToHash
(
result
[
:
]),
value
)
continue
OUTER
case
"addresses"
:
case
"addresses"
:
addrs
,
ok
:=
value
.
(
map
[
any
]
any
)
addrs
,
ok
:=
value
.
(
map
[
any
]
any
)
require
.
Equal
(
t
,
ok
,
true
)
require
.
Equal
(
t
,
ok
,
true
)
...
@@ -130,7 +139,7 @@ OUTER:
...
@@ -130,7 +139,7 @@ OUTER:
continue
OUTER
continue
OUTER
}
}
default
:
default
:
require
.
Fail
(
t
,
"Unknown variable label"
,
key
)
require
.
Fail
(
t
,
fmt
.
Sprintf
(
"Unknown variable label: %s"
,
key
)
)
}
}
require
.
Nil
(
t
,
err
)
require
.
Nil
(
t
,
err
)
require
.
Equal
(
t
,
res
,
value
)
require
.
Equal
(
t
,
res
,
value
)
...
@@ -173,6 +182,10 @@ func testContractStateValuesAreEmpty(t *testing.T, contract *testdata.Testdata)
...
@@ -173,6 +182,10 @@ func testContractStateValuesAreEmpty(t *testing.T, contract *testdata.Testdata)
offset5
,
err
:=
contract
.
Offset5
(
&
bind
.
CallOpts
{})
offset5
,
err
:=
contract
.
Offset5
(
&
bind
.
CallOpts
{})
require
.
Nil
(
t
,
err
)
require
.
Nil
(
t
,
err
)
require
.
Equal
(
t
,
offset5
.
Uint64
(),
uint64
(
0
))
require
.
Equal
(
t
,
offset5
.
Uint64
(),
uint64
(
0
))
bytes32
,
err
:=
contract
.
Bytes32
(
&
bind
.
CallOpts
{})
require
.
Nil
(
t
,
err
)
require
.
Equal
(
t
,
common
.
BytesToHash
(
bytes32
[
:
]),
common
.
Hash
{})
}
}
func
TestMergeStorage
(
t
*
testing
.
T
)
{
func
TestMergeStorage
(
t
*
testing
.
T
)
{
...
@@ -403,3 +416,25 @@ func TestEncodeAddressValue(t *testing.T) {
...
@@ -403,3 +416,25 @@ func TestEncodeAddressValue(t *testing.T) {
require
.
Equal
(
t
,
got
,
test
.
expect
)
require
.
Equal
(
t
,
got
,
test
.
expect
)
}
}
}
}
func
TestEncodeBytes32Value
(
t
*
testing
.
T
)
{
cases
:=
[]
struct
{
bytes32
any
expect
common
.
Hash
}{
{
bytes32
:
common
.
Hash
{
0xff
},
expect
:
common
.
Hash
{
0xff
},
},
{
bytes32
:
"0x11ffffff00000000000000000000000000000000000000000000000000000000"
,
expect
:
common
.
HexToHash
(
"0x11ffffff00000000000000000000000000000000000000000000000000000000"
),
},
}
for
_
,
test
:=
range
cases
{
got
,
err
:=
state
.
EncodeBytes32Value
(
test
.
bytes32
,
0
)
require
.
Nil
(
t
,
err
)
require
.
Equal
(
t
,
got
,
test
.
expect
)
}
}
state-surgery/state/testdata/contract.go
View file @
be4d2f2e
This diff is collapsed.
Click to expand it.
state-surgery/state/testdata/layout.json
View file @
be4d2f2e
...
@@ -79,6 +79,22 @@
...
@@ -79,6 +79,22 @@
"offset"
:
16
,
"offset"
:
16
,
"slot"
:
"4"
,
"slot"
:
"4"
,
"type"
:
"t_uint128"
"type"
:
"t_uint128"
},
{
"astId"
:
25
,
"contract"
:
"contracts/HelloWorld.sol:HelloWorld"
,
"label"
:
"_bytes32"
,
"offset"
:
0
,
"slot"
:
"5"
,
"type"
:
"t_bytes32"
},
{
"astId"
:
27
,
"contract"
:
"contracts/HelloWorld.sol:HelloWorld"
,
"label"
:
"_string"
,
"offset"
:
0
,
"slot"
:
"6"
,
"type"
:
"t_string_storage"
}
}
],
],
"types"
:
{
"types"
:
{
...
@@ -92,6 +108,11 @@
...
@@ -92,6 +108,11 @@
"label"
:
"bool"
,
"label"
:
"bool"
,
"numberOfBytes"
:
"1"
"numberOfBytes"
:
"1"
},
},
"t_bytes32"
:
{
"encoding"
:
"inplace"
,
"label"
:
"bytes32"
,
"numberOfBytes"
:
"32"
},
"t_mapping(t_uint256,t_address)"
:
{
"t_mapping(t_uint256,t_address)"
:
{
"encoding"
:
"mapping"
,
"encoding"
:
"mapping"
,
"key"
:
"t_uint256"
,
"key"
:
"t_uint256"
,
...
@@ -99,6 +120,11 @@
...
@@ -99,6 +120,11 @@
"numberOfBytes"
:
"32"
,
"numberOfBytes"
:
"32"
,
"value"
:
"t_address"
"value"
:
"t_address"
},
},
"t_string_storage"
:
{
"encoding"
:
"bytes"
,
"label"
:
"string"
,
"numberOfBytes"
:
"32"
},
"t_uint128"
:
{
"t_uint128"
:
{
"encoding"
:
"inplace"
,
"encoding"
:
"inplace"
,
"label"
:
"uint128"
,
"label"
:
"uint128"
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment