Commit 59d4fbb2 authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

op-chain-ops: delete dead code (#10298)

Now that genesis generation is in solidity, delete
dead code. This code serialized solidity types suitable
for storage. Very similar to abi encoding but not always
the same, big difference was dynamic types, this library
only supported dynamic types <= 31 bytes to not handle the
chunking. This impacted the sorts of types that could
be in the genesis storage.
parent 12a72abf
package state
import (
"errors"
"fmt"
"math/big"
"reflect"
"regexp"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum-optimism/optimism/op-bindings/solc"
"github.com/ethereum-optimism/optimism/op-service/eth"
)
// EncodeStorageKeyValue encodes the key value pair that is stored in state
// given a StorageLayoutEntry and StorageLayoutType. A single input may result
// in multiple outputs. Unknown or unimplemented types will return an error.
// Note that encoding uints is *not* overflow safe, so be sure to check
// the ABI before setting very large values
func EncodeStorageKeyValue(value any, entry solc.StorageLayoutEntry, storageType solc.StorageLayoutType) ([]*EncodedStorage, error) {
label := storageType.Label
encoded := make([]*EncodedStorage, 0)
key := encodeSlotKey(entry)
switch storageType.Encoding {
case "inplace":
switch label {
case "bool":
val, err := EncodeBoolValue(value, entry.Offset)
if err != nil {
return nil, fmt.Errorf("cannot encode %s: %w", storageType.Encoding, err)
}
encoded = append(encoded, &EncodedStorage{key, val})
case "address":
val, err := EncodeAddressValue(value, entry.Offset)
if err != nil {
return nil, fmt.Errorf("cannot encode %s: %w", storageType.Encoding, err)
}
encoded = append(encoded, &EncodedStorage{key, val})
case "bytes":
return nil, fmt.Errorf("%w: %s", errUnimplemented, label)
case "bytes32":
val, err := EncodeBytes32Value(value, entry.Offset)
if err != nil {
return nil, fmt.Errorf("cannot encode %s: %w", storageType.Encoding, err)
}
encoded = append(encoded, &EncodedStorage{key, val})
default:
switch true {
case strings.HasPrefix(label, "contract"):
val, err := EncodeAddressValue(value, entry.Offset)
if err != nil {
return nil, fmt.Errorf("cannot encode %s: %w", storageType.Encoding, err)
}
encoded = append(encoded, &EncodedStorage{key, val})
case strings.HasPrefix(label, "uint"):
val, err := EncodeUintValue(value, entry.Offset)
if err != nil {
return nil, fmt.Errorf("cannot encode %s: %w", storageType.Encoding, err)
}
encoded = append(encoded, &EncodedStorage{key, val})
default:
// structs are not supported
return nil, fmt.Errorf("cannot encode %s: %w", storageType.Encoding, errUnimplemented)
}
}
case "dynamic_array":
case "bytes":
switch label {
case "string":
val, err := EncodeStringValue(value, entry.Offset)
if err != nil {
return nil, fmt.Errorf("cannot encode %s: %w", storageType.Encoding, errUnimplemented)
}
encoded = append(encoded, &EncodedStorage{key, val})
default:
return nil, fmt.Errorf("%w: %s", errUnimplemented, label)
}
case "mapping":
if strings.HasPrefix(storageType.Value, "mapping") {
return nil, fmt.Errorf("%w: %s", errUnimplemented, "nested mappings")
}
values, ok := value.(map[any]any)
if !ok {
return nil, fmt.Errorf("mapping must be map[any]any")
}
keyEncoder, err := getElementEncoder(storageType, "key")
if err != nil {
return nil, err
}
valueEncoder, err := getElementEncoder(storageType, "value")
if err != nil {
return nil, err
}
// Mapping values have 0 offset
for rawKey, rawVal := range values {
encodedKey, err := keyEncoder(rawKey, 0)
if err != nil {
return nil, err
}
encodedSlot := encodeSlotKey(entry)
preimage := [64]byte{}
copy(preimage[0:32], encodedKey.Bytes())
copy(preimage[32:64], encodedSlot.Bytes())
hash := crypto.Keccak256(preimage[:])
key := common.BytesToHash(hash)
val, err := valueEncoder(rawVal, 0)
if err != nil {
return nil, err
}
encoded = append(encoded, &EncodedStorage{key, val})
}
default:
return nil, fmt.Errorf("unknown encoding %s: %w", storageType.Encoding, errUnimplemented)
}
return encoded, nil
}
// encodeSlotKey will encode the storage slot key. This does not
// support mappings.
func encodeSlotKey(entry solc.StorageLayoutEntry) common.Hash {
slot := new(big.Int).SetUint64(uint64(entry.Slot))
return common.BigToHash(slot)
}
// ElementEncoder is a function that can encode an element
// based on a solidity type
type ElementEncoder func(value any, offset uint) (common.Hash, error)
// getElementEncoder will return the correct ElementEncoder
// given a solidity type. The kind refers to the key or the value
// when getting an encoder for a mapping. This is only useful
// if the key itself is not populated for some reason.
func getElementEncoder(storageType solc.StorageLayoutType, kind string) (ElementEncoder, error) {
var target string
if kind == "key" {
target = storageType.Key
} else if kind == "value" {
target = storageType.Value
} else {
return nil, fmt.Errorf("unknown storage %s", kind)
}
switch target {
case "t_address":
return EncodeAddressValue, nil
case "t_bool":
return EncodeBoolValue, nil
case "t_bytes32":
return EncodeBytes32Value, nil
default:
if strings.HasPrefix(target, "t_uint") {
return EncodeUintValue, nil
}
}
// Special case fallback if the target is empty, pull it
// from the label. This requires knowledge of whether we want
// the key or the value in the label.
if target == "" {
r := regexp.MustCompile(`mapping\((?P<key>[[:alnum:]]*) => (?P<value>[[:alnum:]]*)\)`)
result := r.FindStringSubmatch(storageType.Label)
for i, key := range r.SubexpNames() {
if kind == key {
res := "t_" + result[i]
layout := solc.StorageLayoutType{}
if kind == "key" {
layout.Key = res
} else if kind == "value" {
layout.Value = res
} else {
return nil, fmt.Errorf("unknown storage %s", kind)
}
return getElementEncoder(layout, kind)
}
}
}
return nil, fmt.Errorf("unsupported type: %s", target)
}
// 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
}
}
// EncodeStringValue will encode a string to a type suitable
// for storage in state. The offset must be 0.
func EncodeStringValue(value any, offset uint) (common.Hash, error) {
if offset != 0 {
return common.Hash{}, errors.New("offset must be 0")
}
return encodeStringValue(value)
}
// encodeStringValue implements the string encoding. Values larger
// than 31 bytes are not supported because they will be stored
// in multiple storage slots.
func encodeStringValue(value any) (common.Hash, error) {
name := reflect.TypeOf(value).Name()
switch name {
case "string":
str, ok := value.(string)
if !ok {
return common.Hash{}, errInvalidType
}
data := []byte(str)
// Values that are 32 bytes or longer are not supported
if len(data) >= 32 {
return common.Hash{}, errors.New("string value too long")
}
// The data is right padded with 2 * the length
// of the data in the final byte
padded := common.RightPadBytes(data, 32)
padded[len(padded)-1] = byte(len(data) * 2)
return common.BytesToHash(padded), nil
default:
return common.Hash{}, errInvalidType
}
}
// EncodeBoolValue will encode a boolean value given a storage
// offset.
func EncodeBoolValue(value any, offset uint) (common.Hash, error) {
val, err := encodeBoolValue(value)
if err != nil {
return common.Hash{}, fmt.Errorf("invalid bool: %w", err)
}
return handleOffset(val, offset), nil
}
// encodeBoolValue will encode a boolean value into a type
// suitable for solidity storage.
func encodeBoolValue(value any) (common.Hash, error) {
name := reflect.TypeOf(value).Name()
switch name {
case "bool":
boolean, ok := value.(bool)
if !ok {
return common.Hash{}, errInvalidType
}
if boolean {
return common.BigToHash(common.Big1), nil
} else {
return common.Hash{}, nil
}
case "string":
boolean, ok := value.(string)
if !ok {
return common.Hash{}, errInvalidType
}
if boolean == "true" {
return common.BigToHash(common.Big1), nil
} else {
return common.Hash{}, nil
}
default:
return common.Hash{}, errInvalidType
}
}
// EncodeAddressValue will encode an address like value given a
// storage offset.
func EncodeAddressValue(value any, offset uint) (common.Hash, error) {
val, err := encodeAddressValue(value)
if err != nil {
return common.Hash{}, fmt.Errorf("invalid address: %w", err)
}
return handleOffset(val, offset), nil
}
// encodeAddressValue will encode an address value into
// a type suitable for solidity storage.
func encodeAddressValue(value any) (common.Hash, error) {
typ := reflect.TypeOf(value)
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
name := typ.Name()
switch name {
case "Address":
if reflect.TypeOf(value).Kind() == reflect.Ptr {
address, ok := value.(*common.Address)
if !ok {
return common.Hash{}, errInvalidType
}
return eth.AddressAsLeftPaddedHash(*address), nil
} else {
address, ok := value.(common.Address)
if !ok {
return common.Hash{}, errInvalidType
}
return eth.AddressAsLeftPaddedHash(address), nil
}
case "string":
address, ok := value.(string)
if !ok {
return common.Hash{}, errInvalidType
}
return eth.AddressAsLeftPaddedHash(common.HexToAddress(address)), nil
default:
return common.Hash{}, errInvalidType
}
}
// EncodeUintValue will encode a uint value given a storage offset
func EncodeUintValue(value any, offset uint) (common.Hash, error) {
val, err := encodeUintValue(value)
if err != nil {
return common.Hash{}, fmt.Errorf("invalid uint: %w", err)
}
return handleOffset(val, offset), nil
}
// encodeUintValue will encode a uint like type into a
// type suitable for solidity storage.
func encodeUintValue(value any) (common.Hash, error) {
val := reflect.ValueOf(value)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
name := val.Type().Name()
switch name {
case "uint":
val, ok := value.(uint)
if !ok {
return common.Hash{}, errInvalidType
}
result := new(big.Int).SetUint64((uint64(val)))
return common.BigToHash(result), nil
case "int":
val, ok := value.(int)
if !ok {
return common.Hash{}, errInvalidType
}
result := new(big.Int).SetUint64(uint64(val))
return common.BigToHash(result), nil
case "uint64":
val, ok := value.(uint64)
if !ok {
return common.Hash{}, errInvalidType
}
result := new(big.Int).SetUint64(val)
return common.BigToHash(result), nil
case "uint32":
val, ok := value.(uint32)
if !ok {
return common.Hash{}, errInvalidType
}
result := new(big.Int).SetUint64(uint64(val))
return common.BigToHash(result), nil
case "uint16":
val, ok := value.(uint16)
if !ok {
return common.Hash{}, errInvalidType
}
result := new(big.Int).SetUint64(uint64(val))
return common.BigToHash(result), nil
case "uint8":
val, ok := value.(uint8)
if !ok {
return common.Hash{}, errInvalidType
}
result := new(big.Int).SetUint64(uint64(val))
return common.BigToHash(result), nil
case "string":
val, ok := value.(string)
if !ok {
return common.Hash{}, errInvalidType
}
number, err := hexutil.DecodeBig(val)
if err != nil {
if errors.Is(err, hexutil.ErrMissingPrefix) {
number, ok = new(big.Int).SetString(val, 10)
if !ok {
return common.Hash{}, errInvalidType
}
} else if errors.Is(err, hexutil.ErrLeadingZero) {
number, ok = new(big.Int).SetString(val[2:], 16)
if !ok {
return common.Hash{}, errInvalidType
}
}
}
return common.BigToHash(number), nil
case "bool":
val, ok := value.(bool)
if !ok {
return common.Hash{}, errInvalidType
}
if val {
return common.Hash{31: 0x01}, nil
} else {
return common.Hash{}, nil
}
case "Int":
val, ok := value.(*big.Int)
if !ok {
return common.Hash{}, errInvalidType
}
return common.BigToHash(val), nil
default:
return common.Hash{}, errInvalidType
}
}
// handleOffset will offset a value in storage by shifting
// it to the left. This is useful for when multiple variables
// are tightly packed in a storage slot.
func handleOffset(hash common.Hash, offset uint) common.Hash {
if offset == 0 {
return hash
}
number := hash.Big()
shifted := new(big.Int).Lsh(number, offset*8)
return common.BigToHash(shifted)
}
package state
import (
"errors"
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-bindings/solc"
"github.com/ethereum/go-ethereum/common"
)
var (
errInvalidType = errors.New("invalid type")
errUnimplemented = errors.New("type unimplemented")
)
// StorageValues represents the values to be set in storage.
// The key is the name of the storage variable and the value
// is the value to set in storage.
type StorageValues map[string]any
// StorageConfig represents the storage configuration for the L2 predeploy
// contracts.
type StorageConfig map[string]StorageValues
// EncodedStorage represents the storage key and value serialized
// to be placed in Ethereum state.
type EncodedStorage struct {
Key common.Hash
Value common.Hash
}
// EncodeStorage will encode a storage layout
func EncodeStorage(entry solc.StorageLayoutEntry, value any, storageType solc.StorageLayoutType) ([]*EncodedStorage, error) {
if storageType.NumberOfBytes > 32 {
return nil, fmt.Errorf("%s is larger than 32 bytes", storageType.Encoding)
}
encoded, err := EncodeStorageKeyValue(value, entry, storageType)
if err != nil {
return nil, err
}
return encoded, nil
}
// ComputeStorageSlots will compute the storage slots for a given contract.
func ComputeStorageSlots(layout *solc.StorageLayout, values StorageValues) ([]*EncodedStorage, error) {
encodedStorage := make([]*EncodedStorage, 0)
for label, value := range values {
var target solc.StorageLayoutEntry
for _, entry := range layout.Storage {
if label == entry.Label {
target = entry
break
}
}
if target.Label == "" {
return nil, fmt.Errorf("storage layout entry for %s not found", label)
}
storageType := layout.Types[target.Type]
if storageType.Label == "" {
return nil, fmt.Errorf("storage type for %s not found", label)
}
storage, err := EncodeStorage(target, value, storageType)
if err != nil {
return nil, fmt.Errorf("cannot encode storage for %s: %w", target.Label, err)
}
encodedStorage = append(encodedStorage, storage...)
}
results := MergeStorage(encodedStorage)
return results, nil
}
// MergeStorage will combine any overlapping storage slots for
// when values are tightly packed. Do this by checking to see if any
// of the produced storage slots have a matching key, if so use a
// binary or to add the storage values together
func MergeStorage(storage []*EncodedStorage) []*EncodedStorage {
encodedKV := make(map[common.Hash]common.Hash)
var encodedKeys []common.Hash // for deterministic result order
for _, storage := range storage {
if prev, ok := encodedKV[storage.Key]; ok {
combined := new(big.Int).Or(prev.Big(), storage.Value.Big())
encodedKV[storage.Key] = common.BigToHash(combined)
} else {
encodedKV[storage.Key] = storage.Value
encodedKeys = append(encodedKeys, storage.Key)
}
}
results := make([]*EncodedStorage, 0)
for _, key := range encodedKeys {
val := encodedKV[key]
results = append(results, &EncodedStorage{key, val})
}
return results
}
package state_test
import (
"encoding/json"
"fmt"
"math/big"
"os"
"testing"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum-optimism/optimism/op-bindings/solc"
"github.com/ethereum-optimism/optimism/op-chain-ops/state"
"github.com/ethereum-optimism/optimism/op-chain-ops/state/testdata"
"github.com/stretchr/testify/require"
)
var (
// layout is the storage layout used in tests
layout solc.StorageLayout
// testKey is the same test key that geth uses
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
// chainID is the chain id used for simulated backends
chainID = big.NewInt(1337)
)
// Read the test data from disk asap
func init() {
data, err := os.ReadFile("./testdata/layout.json")
if err != nil {
panic("layout.json not found")
}
if err := json.Unmarshal(data, &layout); err != nil {
panic("cannot unmarshal storage layout")
}
}
func TestSetAndGetStorageSlots(t *testing.T) {
values := state.StorageValues{}
values["_uint256"] = new(big.Int).SetUint64(0xafff_ffff_ffff_ffff)
values["_address"] = common.HexToAddress("0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8")
values["_bool"] = true
values["offset0"] = uint8(0xaa)
values["offset1"] = uint8(0xbb)
values["offset2"] = uint16(0x0c0c)
values["offset3"] = uint32(0xf33d35)
values["offset4"] = uint64(0xd34dd34d00)
values["offset5"] = new(big.Int).SetUint64(0x43ad0043ad0043ad)
values["_bytes32"] = common.Hash{0xff}
values["_string"] = "foobar"
addresses := make(map[any]any)
addresses[big.NewInt(1)] = common.Address{19: 0xff}
values["addresses"] = addresses
slots, err := state.ComputeStorageSlots(&layout, values)
require.Nil(t, err)
backend := backends.NewSimulatedBackend( // nolint:staticcheck
core.GenesisAlloc{
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000000000)},
},
15000000,
)
opts, err := bind.NewKeyedTransactorWithChainID(testKey, chainID)
require.Nil(t, err)
_, _, contract, err := testdata.DeployTestdata(opts, backend)
require.Nil(t, err)
backend.Commit()
// Call each of the methods to make sure that they are set to their 0 values
testContractStateValuesAreEmpty(t, contract)
// Send transactions through the set storage API on the contract
for _, slot := range slots {
_, err := contract.SetStorage(opts, slot.Key, slot.Value)
require.Nil(t, err)
}
backend.Commit()
testContractStateValuesAreSet(t, contract, values)
// Call the get storage API on the contract to double check
// that the storage slots have been set correctly
for _, slot := range slots {
value, err := contract.GetStorage(&bind.CallOpts{}, slot.Key)
require.Nil(t, err)
require.Equal(t, value[:], slot.Value.Bytes())
}
}
// Ensure that all the storage variables are set after setting storage
// through the contract
func testContractStateValuesAreSet(t *testing.T, contract *testdata.Testdata, values state.StorageValues) {
OUTER:
for key, value := range values {
var res any
var err error
switch key {
case "_uint256":
res, err = contract.Uint256(&bind.CallOpts{})
case "_address":
res, err = contract.Address(&bind.CallOpts{})
case "_bool":
res, err = contract.Bool(&bind.CallOpts{})
case "offset0":
res, err = contract.Offset0(&bind.CallOpts{})
case "offset1":
res, err = contract.Offset1(&bind.CallOpts{})
case "offset2":
res, err = contract.Offset2(&bind.CallOpts{})
case "offset3":
res, err = contract.Offset3(&bind.CallOpts{})
case "offset4":
res, err = contract.Offset4(&bind.CallOpts{})
case "offset5":
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 "_string":
res, err = contract.String(&bind.CallOpts{})
case "addresses":
addrs, ok := value.(map[any]any)
require.Equal(t, ok, true)
for mapKey, mapVal := range addrs {
res, err = contract.Addresses(&bind.CallOpts{}, mapKey.(*big.Int))
require.Nil(t, err)
require.Equal(t, mapVal, res)
continue OUTER
}
default:
require.Fail(t, fmt.Sprintf("Unknown variable label: %s", key))
}
require.Nil(t, err)
require.Equal(t, res, value)
}
}
func testContractStateValuesAreEmpty(t *testing.T, contract *testdata.Testdata) {
addr, err := contract.Address(&bind.CallOpts{})
require.Nil(t, err)
require.Equal(t, addr, common.Address{})
boolean, err := contract.Bool(&bind.CallOpts{})
require.Nil(t, err)
require.Equal(t, boolean, false)
uint256, err := contract.Uint256(&bind.CallOpts{})
require.Nil(t, err)
require.Equal(t, uint256.Uint64(), uint64(0))
offset0, err := contract.Offset0(&bind.CallOpts{})
require.Nil(t, err)
require.Equal(t, offset0, uint8(0))
offset1, err := contract.Offset1(&bind.CallOpts{})
require.Nil(t, err)
require.Equal(t, offset1, uint8(0))
offset2, err := contract.Offset2(&bind.CallOpts{})
require.Nil(t, err)
require.Equal(t, offset2, uint16(0))
offset3, err := contract.Offset3(&bind.CallOpts{})
require.Nil(t, err)
require.Equal(t, offset3, uint32(0))
offset4, err := contract.Offset4(&bind.CallOpts{})
require.Nil(t, err)
require.Equal(t, offset4, uint64(0))
offset5, err := contract.Offset5(&bind.CallOpts{})
require.Nil(t, err)
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) {
cases := []struct {
input []*state.EncodedStorage
expect []*state.EncodedStorage
}{
{
// One input should be the same result
input: []*state.EncodedStorage{
{
Key: common.Hash{},
Value: common.Hash{},
},
},
expect: []*state.EncodedStorage{
{
Key: common.Hash{},
Value: common.Hash{},
},
},
},
{
// Two duplicate inputs should be merged
input: []*state.EncodedStorage{
{
Key: common.Hash{1},
Value: common.Hash{},
},
{
Key: common.Hash{1},
Value: common.Hash{},
},
},
expect: []*state.EncodedStorage{
{
Key: common.Hash{1},
Value: common.Hash{},
},
},
},
{
// Two different inputs should be the same result
input: []*state.EncodedStorage{
{
Key: common.Hash{1},
Value: common.Hash{},
},
{
Key: common.Hash{2},
Value: common.Hash{},
},
},
expect: []*state.EncodedStorage{
{
Key: common.Hash{1},
Value: common.Hash{},
},
{
Key: common.Hash{2},
Value: common.Hash{},
},
},
},
{
// Two matching keys should be merged bitwise
input: []*state.EncodedStorage{
{
Key: common.Hash{},
Value: common.Hash{0x00, 0x01},
},
{
Key: common.Hash{},
Value: common.Hash{0x02, 0x00},
},
},
expect: []*state.EncodedStorage{
{
Key: common.Hash{},
Value: common.Hash{0x02, 0x01},
},
},
},
}
for _, test := range cases {
got := state.MergeStorage(test.input)
require.Equal(t, test.expect, got)
}
}
func TestEncodeUintValue(t *testing.T) {
cases := []struct {
number any
offset uint
expect common.Hash
}{
{
number: 0,
offset: 0,
expect: common.Hash{},
},
{
number: big.NewInt(1),
offset: 0,
expect: common.Hash{31: 0x01},
},
{
number: uint64(2),
offset: 0,
expect: common.Hash{31: 0x02},
},
{
number: uint8(3),
offset: 0,
expect: common.Hash{31: 0x03},
},
{
number: uint16(4),
offset: 0,
expect: common.Hash{31: 0x04},
},
{
number: uint32(5),
offset: 0,
expect: common.Hash{31: 0x05},
},
{
number: int(6),
offset: 0,
expect: common.Hash{31: 0x06},
},
{
number: 1,
offset: 1,
expect: common.Hash{30: 0x01},
},
{
number: 1,
offset: 10,
expect: common.Hash{21: 0x01},
},
}
for _, test := range cases {
got, err := state.EncodeUintValue(test.number, test.offset)
require.Nil(t, err)
require.Equal(t, got, test.expect)
}
}
func TestEncodeBoolValue(t *testing.T) {
cases := []struct {
boolean any
offset uint
expect common.Hash
}{
{
boolean: true,
offset: 0,
expect: common.Hash{31: 0x01},
},
{
boolean: false,
offset: 0,
expect: common.Hash{},
},
{
boolean: true,
offset: 1,
expect: common.Hash{30: 0x01},
},
{
boolean: false,
offset: 1,
expect: common.Hash{},
},
{
boolean: "true",
offset: 0,
expect: common.Hash{31: 0x01},
},
{
boolean: "false",
offset: 0,
expect: common.Hash{},
},
}
for _, test := range cases {
got, err := state.EncodeBoolValue(test.boolean, test.offset)
require.Nil(t, err)
require.Equal(t, got, test.expect)
}
}
func TestEncodeAddressValue(t *testing.T) {
cases := []struct {
addr any
offset uint
expect common.Hash
}{
{
addr: common.Address{},
offset: 0,
expect: common.Hash{},
},
{
addr: common.Address{0x01},
offset: 0,
expect: common.Hash{12: 0x01},
},
{
addr: "0x829BD824B016326A401d083B33D092293333A830",
offset: 0,
expect: common.HexToHash("0x829BD824B016326A401d083B33D092293333A830"),
},
{
addr: common.Address{19: 0x01},
offset: 1,
expect: common.Hash{30: 0x01},
},
{
addr: &common.Address{},
offset: 0,
expect: common.Hash{},
},
}
for _, test := range cases {
got, err := state.EncodeAddressValue(test.addr, test.offset)
require.Nil(t, err)
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)
}
}
func TestEncodeStringValue(t *testing.T) {
cases := []struct {
str any
expect common.Hash
}{
{
str: "foo",
expect: common.Hash{0x66, 0x6f, 0x6f, 31: 6},
},
// Taken from mainnet WETH at 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
{
str: "Wrapped Ether",
expect: common.HexToHash("0x577261707065642045746865720000000000000000000000000000000000001a"),
},
{
str: "WETH",
expect: common.HexToHash("0x5745544800000000000000000000000000000000000000000000000000000008"),
},
}
for _, test := range cases {
got, err := state.EncodeStringValue(test.str, 0)
require.Nil(t, err)
require.Equal(t, got, test.expect)
}
}
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package testdata
import (
"errors"
"math/big"
"strings"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = errors.New
_ = big.NewInt
_ = strings.NewReader
_ = ethereum.NotFound
_ = bind.Bind
_ = common.Big1
_ = types.BloomLookup
_ = event.NewSubscription
)
// TestdataMetaData contains all meta data concerning the Testdata contract.
var TestdataMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[],\"name\":\"_address\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_bool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_bytes32\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_string\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"_uint256\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"addresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"}],\"name\":\"getStorage\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"offset0\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"offset1\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"offset2\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"offset3\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"offset4\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"offset5\",\"outputs\":[{\"internalType\":\"uint128\",\"name\":\"\",\"type\":\"uint128\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"key\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"value\",\"type\":\"bytes32\"}],\"name\":\"setStorage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
Bin: "0x608060405234801561001057600080fd5b50610415806100206000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80635e0068591161008c5780639b267f09116100665780639b267f09146102285780639e6ba9c21461023d578063a753307d1461025a578063edf26d9b1461028757600080fd5b80635e0068591461020257806393f2b3981461020b5780639b0b0fda1461021457600080fd5b806332da25e1116100c857806332da25e114610150578063350e81cc146101895780634ba664e7146101b0578063502a6c5e146101d057600080fd5b8063099ea180146100ef57806309f395f11461011357806318bad21714610125575b600080fd5b6004546100fc9060ff1681565b60405160ff90911681526020015b60405180910390f35b6004546100fc90610100900460ff1681565b600054610138906001600160a01b031681565b6040516001600160a01b03909116815260200161010a565b6004546101709068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161010a565b60045461019d9062010000900461ffff1681565b60405161ffff909116815260200161010a565b6101c26101be36600461033e565b5490565b60405190815260200161010a565b6004546101ea90600160801b90046001600160801b031681565b6040516001600160801b03909116815260200161010a565b6101c260035481565b6101c260055481565b610226610222366004610357565b9055565b005b6102306102b0565b60405161010a9190610379565b60025461024a9060ff1681565b604051901515815260200161010a565b60045461027290640100000000900463ffffffff1681565b60405163ffffffff909116815260200161010a565b61013861029536600461033e565b6001602052600090815260409020546001600160a01b031681565b600680546102bd906103ce565b80601f01602080910402602001604051908101604052809291908181526020018280546102e9906103ce565b80156103365780601f1061030b57610100808354040283529160200191610336565b820191906000526020600020905b81548152906001019060200180831161031957829003601f168201915b505050505081565b60006020828403121561035057600080fd5b5035919050565b6000806040838503121561036a57600080fd5b50508035926020909101359150565b600060208083528351808285015260005b818110156103a65785810183015185820160400152820161038a565b818111156103b8576000604083870101525b50601f01601f1916929092016040019392505050565b600181811c908216806103e257607f821691505b60208210810361040257634e487b7160e01b600052602260045260246000fd5b5091905056fea164736f6c634300080f000a",
}
// TestdataABI is the input ABI used to generate the binding from.
// Deprecated: Use TestdataMetaData.ABI instead.
var TestdataABI = TestdataMetaData.ABI
// TestdataBin is the compiled bytecode used for deploying new contracts.
// Deprecated: Use TestdataMetaData.Bin instead.
var TestdataBin = TestdataMetaData.Bin
// DeployTestdata deploys a new Ethereum contract, binding an instance of Testdata to it.
func DeployTestdata(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Testdata, error) {
parsed, err := TestdataMetaData.GetAbi()
if err != nil {
return common.Address{}, nil, nil, err
}
if parsed == nil {
return common.Address{}, nil, nil, errors.New("GetABI returned nil")
}
address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(TestdataBin), backend)
if err != nil {
return common.Address{}, nil, nil, err
}
return address, tx, &Testdata{TestdataCaller: TestdataCaller{contract: contract}, TestdataTransactor: TestdataTransactor{contract: contract}, TestdataFilterer: TestdataFilterer{contract: contract}}, nil
}
// Testdata is an auto generated Go binding around an Ethereum contract.
type Testdata struct {
TestdataCaller // Read-only binding to the contract
TestdataTransactor // Write-only binding to the contract
TestdataFilterer // Log filterer for contract events
}
// TestdataCaller is an auto generated read-only Go binding around an Ethereum contract.
type TestdataCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// TestdataTransactor is an auto generated write-only Go binding around an Ethereum contract.
type TestdataTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// TestdataFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
type TestdataFilterer struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// TestdataSession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type TestdataSession struct {
Contract *Testdata // Generic contract binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// TestdataCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type TestdataCallerSession struct {
Contract *TestdataCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// TestdataTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type TestdataTransactorSession struct {
Contract *TestdataTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// TestdataRaw is an auto generated low-level Go binding around an Ethereum contract.
type TestdataRaw struct {
Contract *Testdata // Generic contract binding to access the raw methods on
}
// TestdataCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type TestdataCallerRaw struct {
Contract *TestdataCaller // Generic read-only contract binding to access the raw methods on
}
// TestdataTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type TestdataTransactorRaw struct {
Contract *TestdataTransactor // Generic write-only contract binding to access the raw methods on
}
// NewTestdata creates a new instance of Testdata, bound to a specific deployed contract.
func NewTestdata(address common.Address, backend bind.ContractBackend) (*Testdata, error) {
contract, err := bindTestdata(address, backend, backend, backend)
if err != nil {
return nil, err
}
return &Testdata{TestdataCaller: TestdataCaller{contract: contract}, TestdataTransactor: TestdataTransactor{contract: contract}, TestdataFilterer: TestdataFilterer{contract: contract}}, nil
}
// NewTestdataCaller creates a new read-only instance of Testdata, bound to a specific deployed contract.
func NewTestdataCaller(address common.Address, caller bind.ContractCaller) (*TestdataCaller, error) {
contract, err := bindTestdata(address, caller, nil, nil)
if err != nil {
return nil, err
}
return &TestdataCaller{contract: contract}, nil
}
// NewTestdataTransactor creates a new write-only instance of Testdata, bound to a specific deployed contract.
func NewTestdataTransactor(address common.Address, transactor bind.ContractTransactor) (*TestdataTransactor, error) {
contract, err := bindTestdata(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &TestdataTransactor{contract: contract}, nil
}
// NewTestdataFilterer creates a new log filterer instance of Testdata, bound to a specific deployed contract.
func NewTestdataFilterer(address common.Address, filterer bind.ContractFilterer) (*TestdataFilterer, error) {
contract, err := bindTestdata(address, nil, nil, filterer)
if err != nil {
return nil, err
}
return &TestdataFilterer{contract: contract}, nil
}
// bindTestdata binds a generic wrapper to an already deployed contract.
func bindTestdata(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(TestdataABI))
if err != nil {
return nil, err
}
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_Testdata *TestdataRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _Testdata.Contract.TestdataCaller.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_Testdata *TestdataRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _Testdata.Contract.TestdataTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_Testdata *TestdataRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _Testdata.Contract.TestdataTransactor.contract.Transact(opts, method, params...)
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_Testdata *TestdataCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _Testdata.Contract.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_Testdata *TestdataTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _Testdata.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_Testdata *TestdataTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _Testdata.Contract.contract.Transact(opts, method, params...)
}
// Address is a free data retrieval call binding the contract method 0x18bad217.
//
// Solidity: function _address() view returns(address)
func (_Testdata *TestdataCaller) Address(opts *bind.CallOpts) (common.Address, error) {
var out []interface{}
err := _Testdata.contract.Call(opts, &out, "_address")
if err != nil {
return *new(common.Address), err
}
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
return out0, err
}
// Address is a free data retrieval call binding the contract method 0x18bad217.
//
// Solidity: function _address() view returns(address)
func (_Testdata *TestdataSession) Address() (common.Address, error) {
return _Testdata.Contract.Address(&_Testdata.CallOpts)
}
// Address is a free data retrieval call binding the contract method 0x18bad217.
//
// Solidity: function _address() view returns(address)
func (_Testdata *TestdataCallerSession) Address() (common.Address, error) {
return _Testdata.Contract.Address(&_Testdata.CallOpts)
}
// Bool is a free data retrieval call binding the contract method 0x9e6ba9c2.
//
// Solidity: function _bool() view returns(bool)
func (_Testdata *TestdataCaller) Bool(opts *bind.CallOpts) (bool, error) {
var out []interface{}
err := _Testdata.contract.Call(opts, &out, "_bool")
if err != nil {
return *new(bool), err
}
out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
return out0, err
}
// Bool is a free data retrieval call binding the contract method 0x9e6ba9c2.
//
// Solidity: function _bool() view returns(bool)
func (_Testdata *TestdataSession) Bool() (bool, error) {
return _Testdata.Contract.Bool(&_Testdata.CallOpts)
}
// Bool is a free data retrieval call binding the contract method 0x9e6ba9c2.
//
// Solidity: function _bool() view returns(bool)
func (_Testdata *TestdataCallerSession) Bool() (bool, error) {
return _Testdata.Contract.Bool(&_Testdata.CallOpts)
}
// Bytes32 is a free data retrieval call binding the contract method 0x93f2b398.
//
// Solidity: function _bytes32() view returns(bytes32)
func (_Testdata *TestdataCaller) Bytes32(opts *bind.CallOpts) ([32]byte, error) {
var out []interface{}
err := _Testdata.contract.Call(opts, &out, "_bytes32")
if err != nil {
return *new([32]byte), err
}
out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
return out0, err
}
// Bytes32 is a free data retrieval call binding the contract method 0x93f2b398.
//
// Solidity: function _bytes32() view returns(bytes32)
func (_Testdata *TestdataSession) Bytes32() ([32]byte, error) {
return _Testdata.Contract.Bytes32(&_Testdata.CallOpts)
}
// Bytes32 is a free data retrieval call binding the contract method 0x93f2b398.
//
// Solidity: function _bytes32() view returns(bytes32)
func (_Testdata *TestdataCallerSession) Bytes32() ([32]byte, error) {
return _Testdata.Contract.Bytes32(&_Testdata.CallOpts)
}
// String is a free data retrieval call binding the contract method 0x9b267f09.
//
// Solidity: function _string() view returns(string)
func (_Testdata *TestdataCaller) String(opts *bind.CallOpts) (string, error) {
var out []interface{}
err := _Testdata.contract.Call(opts, &out, "_string")
if err != nil {
return *new(string), err
}
out0 := *abi.ConvertType(out[0], new(string)).(*string)
return out0, err
}
// String is a free data retrieval call binding the contract method 0x9b267f09.
//
// Solidity: function _string() view returns(string)
func (_Testdata *TestdataSession) String() (string, error) {
return _Testdata.Contract.String(&_Testdata.CallOpts)
}
// String is a free data retrieval call binding the contract method 0x9b267f09.
//
// Solidity: function _string() view returns(string)
func (_Testdata *TestdataCallerSession) String() (string, error) {
return _Testdata.Contract.String(&_Testdata.CallOpts)
}
// Uint256 is a free data retrieval call binding the contract method 0x5e006859.
//
// Solidity: function _uint256() view returns(uint256)
func (_Testdata *TestdataCaller) Uint256(opts *bind.CallOpts) (*big.Int, error) {
var out []interface{}
err := _Testdata.contract.Call(opts, &out, "_uint256")
if err != nil {
return *new(*big.Int), err
}
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
return out0, err
}
// Uint256 is a free data retrieval call binding the contract method 0x5e006859.
//
// Solidity: function _uint256() view returns(uint256)
func (_Testdata *TestdataSession) Uint256() (*big.Int, error) {
return _Testdata.Contract.Uint256(&_Testdata.CallOpts)
}
// Uint256 is a free data retrieval call binding the contract method 0x5e006859.
//
// Solidity: function _uint256() view returns(uint256)
func (_Testdata *TestdataCallerSession) Uint256() (*big.Int, error) {
return _Testdata.Contract.Uint256(&_Testdata.CallOpts)
}
// Addresses is a free data retrieval call binding the contract method 0xedf26d9b.
//
// Solidity: function addresses(uint256 ) view returns(address)
func (_Testdata *TestdataCaller) Addresses(opts *bind.CallOpts, arg0 *big.Int) (common.Address, error) {
var out []interface{}
err := _Testdata.contract.Call(opts, &out, "addresses", arg0)
if err != nil {
return *new(common.Address), err
}
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
return out0, err
}
// Addresses is a free data retrieval call binding the contract method 0xedf26d9b.
//
// Solidity: function addresses(uint256 ) view returns(address)
func (_Testdata *TestdataSession) Addresses(arg0 *big.Int) (common.Address, error) {
return _Testdata.Contract.Addresses(&_Testdata.CallOpts, arg0)
}
// Addresses is a free data retrieval call binding the contract method 0xedf26d9b.
//
// Solidity: function addresses(uint256 ) view returns(address)
func (_Testdata *TestdataCallerSession) Addresses(arg0 *big.Int) (common.Address, error) {
return _Testdata.Contract.Addresses(&_Testdata.CallOpts, arg0)
}
// GetStorage is a free data retrieval call binding the contract method 0x4ba664e7.
//
// Solidity: function getStorage(bytes32 key) view returns(bytes32)
func (_Testdata *TestdataCaller) GetStorage(opts *bind.CallOpts, key [32]byte) ([32]byte, error) {
var out []interface{}
err := _Testdata.contract.Call(opts, &out, "getStorage", key)
if err != nil {
return *new([32]byte), err
}
out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
return out0, err
}
// GetStorage is a free data retrieval call binding the contract method 0x4ba664e7.
//
// Solidity: function getStorage(bytes32 key) view returns(bytes32)
func (_Testdata *TestdataSession) GetStorage(key [32]byte) ([32]byte, error) {
return _Testdata.Contract.GetStorage(&_Testdata.CallOpts, key)
}
// GetStorage is a free data retrieval call binding the contract method 0x4ba664e7.
//
// Solidity: function getStorage(bytes32 key) view returns(bytes32)
func (_Testdata *TestdataCallerSession) GetStorage(key [32]byte) ([32]byte, error) {
return _Testdata.Contract.GetStorage(&_Testdata.CallOpts, key)
}
// Offset0 is a free data retrieval call binding the contract method 0x099ea180.
//
// Solidity: function offset0() view returns(uint8)
func (_Testdata *TestdataCaller) Offset0(opts *bind.CallOpts) (uint8, error) {
var out []interface{}
err := _Testdata.contract.Call(opts, &out, "offset0")
if err != nil {
return *new(uint8), err
}
out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8)
return out0, err
}
// Offset0 is a free data retrieval call binding the contract method 0x099ea180.
//
// Solidity: function offset0() view returns(uint8)
func (_Testdata *TestdataSession) Offset0() (uint8, error) {
return _Testdata.Contract.Offset0(&_Testdata.CallOpts)
}
// Offset0 is a free data retrieval call binding the contract method 0x099ea180.
//
// Solidity: function offset0() view returns(uint8)
func (_Testdata *TestdataCallerSession) Offset0() (uint8, error) {
return _Testdata.Contract.Offset0(&_Testdata.CallOpts)
}
// Offset1 is a free data retrieval call binding the contract method 0x09f395f1.
//
// Solidity: function offset1() view returns(uint8)
func (_Testdata *TestdataCaller) Offset1(opts *bind.CallOpts) (uint8, error) {
var out []interface{}
err := _Testdata.contract.Call(opts, &out, "offset1")
if err != nil {
return *new(uint8), err
}
out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8)
return out0, err
}
// Offset1 is a free data retrieval call binding the contract method 0x09f395f1.
//
// Solidity: function offset1() view returns(uint8)
func (_Testdata *TestdataSession) Offset1() (uint8, error) {
return _Testdata.Contract.Offset1(&_Testdata.CallOpts)
}
// Offset1 is a free data retrieval call binding the contract method 0x09f395f1.
//
// Solidity: function offset1() view returns(uint8)
func (_Testdata *TestdataCallerSession) Offset1() (uint8, error) {
return _Testdata.Contract.Offset1(&_Testdata.CallOpts)
}
// Offset2 is a free data retrieval call binding the contract method 0x350e81cc.
//
// Solidity: function offset2() view returns(uint16)
func (_Testdata *TestdataCaller) Offset2(opts *bind.CallOpts) (uint16, error) {
var out []interface{}
err := _Testdata.contract.Call(opts, &out, "offset2")
if err != nil {
return *new(uint16), err
}
out0 := *abi.ConvertType(out[0], new(uint16)).(*uint16)
return out0, err
}
// Offset2 is a free data retrieval call binding the contract method 0x350e81cc.
//
// Solidity: function offset2() view returns(uint16)
func (_Testdata *TestdataSession) Offset2() (uint16, error) {
return _Testdata.Contract.Offset2(&_Testdata.CallOpts)
}
// Offset2 is a free data retrieval call binding the contract method 0x350e81cc.
//
// Solidity: function offset2() view returns(uint16)
func (_Testdata *TestdataCallerSession) Offset2() (uint16, error) {
return _Testdata.Contract.Offset2(&_Testdata.CallOpts)
}
// Offset3 is a free data retrieval call binding the contract method 0xa753307d.
//
// Solidity: function offset3() view returns(uint32)
func (_Testdata *TestdataCaller) Offset3(opts *bind.CallOpts) (uint32, error) {
var out []interface{}
err := _Testdata.contract.Call(opts, &out, "offset3")
if err != nil {
return *new(uint32), err
}
out0 := *abi.ConvertType(out[0], new(uint32)).(*uint32)
return out0, err
}
// Offset3 is a free data retrieval call binding the contract method 0xa753307d.
//
// Solidity: function offset3() view returns(uint32)
func (_Testdata *TestdataSession) Offset3() (uint32, error) {
return _Testdata.Contract.Offset3(&_Testdata.CallOpts)
}
// Offset3 is a free data retrieval call binding the contract method 0xa753307d.
//
// Solidity: function offset3() view returns(uint32)
func (_Testdata *TestdataCallerSession) Offset3() (uint32, error) {
return _Testdata.Contract.Offset3(&_Testdata.CallOpts)
}
// Offset4 is a free data retrieval call binding the contract method 0x32da25e1.
//
// Solidity: function offset4() view returns(uint64)
func (_Testdata *TestdataCaller) Offset4(opts *bind.CallOpts) (uint64, error) {
var out []interface{}
err := _Testdata.contract.Call(opts, &out, "offset4")
if err != nil {
return *new(uint64), err
}
out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64)
return out0, err
}
// Offset4 is a free data retrieval call binding the contract method 0x32da25e1.
//
// Solidity: function offset4() view returns(uint64)
func (_Testdata *TestdataSession) Offset4() (uint64, error) {
return _Testdata.Contract.Offset4(&_Testdata.CallOpts)
}
// Offset4 is a free data retrieval call binding the contract method 0x32da25e1.
//
// Solidity: function offset4() view returns(uint64)
func (_Testdata *TestdataCallerSession) Offset4() (uint64, error) {
return _Testdata.Contract.Offset4(&_Testdata.CallOpts)
}
// Offset5 is a free data retrieval call binding the contract method 0x502a6c5e.
//
// Solidity: function offset5() view returns(uint128)
func (_Testdata *TestdataCaller) Offset5(opts *bind.CallOpts) (*big.Int, error) {
var out []interface{}
err := _Testdata.contract.Call(opts, &out, "offset5")
if err != nil {
return *new(*big.Int), err
}
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
return out0, err
}
// Offset5 is a free data retrieval call binding the contract method 0x502a6c5e.
//
// Solidity: function offset5() view returns(uint128)
func (_Testdata *TestdataSession) Offset5() (*big.Int, error) {
return _Testdata.Contract.Offset5(&_Testdata.CallOpts)
}
// Offset5 is a free data retrieval call binding the contract method 0x502a6c5e.
//
// Solidity: function offset5() view returns(uint128)
func (_Testdata *TestdataCallerSession) Offset5() (*big.Int, error) {
return _Testdata.Contract.Offset5(&_Testdata.CallOpts)
}
// SetStorage is a paid mutator transaction binding the contract method 0x9b0b0fda.
//
// Solidity: function setStorage(bytes32 key, bytes32 value) returns()
func (_Testdata *TestdataTransactor) SetStorage(opts *bind.TransactOpts, key [32]byte, value [32]byte) (*types.Transaction, error) {
return _Testdata.contract.Transact(opts, "setStorage", key, value)
}
// SetStorage is a paid mutator transaction binding the contract method 0x9b0b0fda.
//
// Solidity: function setStorage(bytes32 key, bytes32 value) returns()
func (_Testdata *TestdataSession) SetStorage(key [32]byte, value [32]byte) (*types.Transaction, error) {
return _Testdata.Contract.SetStorage(&_Testdata.TransactOpts, key, value)
}
// SetStorage is a paid mutator transaction binding the contract method 0x9b0b0fda.
//
// Solidity: function setStorage(bytes32 key, bytes32 value) returns()
func (_Testdata *TestdataTransactorSession) SetStorage(key [32]byte, value [32]byte) (*types.Transaction, error) {
return _Testdata.Contract.SetStorage(&_Testdata.TransactOpts, key, value)
}
{
"storage": [
{
"astId": 3,
"contract": "contracts/HelloWorld.sol:HelloWorld",
"label": "_address",
"offset": 0,
"slot": "0",
"type": "t_address"
},
{
"astId": 7,
"contract": "contracts/HelloWorld.sol:HelloWorld",
"label": "addresses",
"offset": 0,
"slot": "1",
"type": "t_mapping(t_uint256,t_address)"
},
{
"astId": 9,
"contract": "contracts/HelloWorld.sol:HelloWorld",
"label": "_bool",
"offset": 0,
"slot": "2",
"type": "t_bool"
},
{
"astId": 11,
"contract": "contracts/HelloWorld.sol:HelloWorld",
"label": "_uint256",
"offset": 0,
"slot": "3",
"type": "t_uint256"
},
{
"astId": 13,
"contract": "contracts/HelloWorld.sol:HelloWorld",
"label": "offset0",
"offset": 0,
"slot": "4",
"type": "t_uint8"
},
{
"astId": 15,
"contract": "contracts/HelloWorld.sol:HelloWorld",
"label": "offset1",
"offset": 1,
"slot": "4",
"type": "t_uint8"
},
{
"astId": 17,
"contract": "contracts/HelloWorld.sol:HelloWorld",
"label": "offset2",
"offset": 2,
"slot": "4",
"type": "t_uint16"
},
{
"astId": 19,
"contract": "contracts/HelloWorld.sol:HelloWorld",
"label": "offset3",
"offset": 4,
"slot": "4",
"type": "t_uint32"
},
{
"astId": 21,
"contract": "contracts/HelloWorld.sol:HelloWorld",
"label": "offset4",
"offset": 8,
"slot": "4",
"type": "t_uint64"
},
{
"astId": 23,
"contract": "contracts/HelloWorld.sol:HelloWorld",
"label": "offset5",
"offset": 16,
"slot": "4",
"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": {
"t_address": {
"encoding": "inplace",
"label": "address",
"numberOfBytes": "20"
},
"t_bool": {
"encoding": "inplace",
"label": "bool",
"numberOfBytes": "1"
},
"t_bytes32": {
"encoding": "inplace",
"label": "bytes32",
"numberOfBytes": "32"
},
"t_mapping(t_uint256,t_address)": {
"encoding": "mapping",
"key": "t_uint256",
"label": "mapping(uint256 => address)",
"numberOfBytes": "32",
"value": "t_address"
},
"t_string_storage": {
"encoding": "bytes",
"label": "string",
"numberOfBytes": "32"
},
"t_uint128": {
"encoding": "inplace",
"label": "uint128",
"numberOfBytes": "16"
},
"t_uint16": {
"encoding": "inplace",
"label": "uint16",
"numberOfBytes": "2"
},
"t_uint256": {
"encoding": "inplace",
"label": "uint256",
"numberOfBytes": "32"
},
"t_uint32": {
"encoding": "inplace",
"label": "uint32",
"numberOfBytes": "4"
},
"t_uint64": {
"encoding": "inplace",
"label": "uint64",
"numberOfBytes": "8"
},
"t_uint8": {
"encoding": "inplace",
"label": "uint8",
"numberOfBytes": "1"
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment