@@ -6,9 +6,11 @@ import (
66 "context"
77 "crypto/sha512"
88 "database/sql"
9+ "encoding/hex"
910 "errors"
1011 "fmt"
1112 "math/big"
13+ "strings"
1214
1315 "github.com/ethereum/go-ethereum/common"
1416 "github.com/ethereum/go-ethereum/common/hexutil"
@@ -58,7 +60,7 @@ type API interface {
5860 // GetBlockTransactionCountByNumber returns the number of transactions in the block.
5961 GetBlockTransactionCountByNumber (ctx context.Context , blockNum ethrpc.BlockNumber ) (hexutil.Uint , error )
6062 // GetStorageAt returns the storage value at the provided position.
61- GetStorageAt (ctx context.Context , address common.Address , position hexutil. Big , blockNrOrHash ethrpc.BlockNumberOrHash ) (hexutil.Big , error )
63+ GetStorageAt (ctx context.Context , address common.Address , slot string , blockNrOrHash ethrpc.BlockNumberOrHash ) (hexutil.Bytes , error )
6264 // GetBalance returns the provided account's balance up to the provided block number.
6365 GetBalance (ctx context.Context , address common.Address , blockNrOrHash ethrpc.BlockNumberOrHash ) (* hexutil.Big , error )
6466 // ChainId return the EIP-155 chain id for the current network.
@@ -232,33 +234,48 @@ func (api *publicAPI) GetBlockTransactionCountByNumber(ctx context.Context, bloc
232234 return hexutil .Uint (n ), nil
233235}
234236
235- func (api * publicAPI ) GetStorageAt (ctx context.Context , address common.Address , position hexutil.Big , blockNrOrHash ethrpc.BlockNumberOrHash ) (hexutil.Big , error ) {
236- logger := api .Logger .With ("method" , "eth_getStorageAt" , "address" , address , "position" , position , "block_or_hash" , blockNrOrHash )
237+ // These matches most other eth-compatible gateways, which are very lax about the slot hex encoding.
238+ func decodeHash (s string ) (common.Hash , error ) {
239+ if strings .HasPrefix (s , "0x" ) || strings .HasPrefix (s , "0X" ) {
240+ s = s [2 :]
241+ }
242+ if (len (s ) & 1 ) > 0 {
243+ s = "0" + s
244+ }
245+ b , err := hex .DecodeString (s )
246+ if err != nil {
247+ return common.Hash {}, fmt .Errorf ("hex string invalid" )
248+ }
249+ if len (b ) > 32 {
250+ return common.Hash {}, fmt .Errorf ("hex string too long, want at most 32 bytes" )
251+ }
252+ return common .BytesToHash (b ), nil
253+ }
254+
255+ func (api * publicAPI ) GetStorageAt (ctx context.Context , address common.Address , slotHex string , blockNrOrHash ethrpc.BlockNumberOrHash ) (hexutil.Bytes , error ) {
256+ logger := api .Logger .With ("method" , "eth_getStorageAt" , "address" , address , "slot" , slotHex , "block_or_hash" , blockNrOrHash )
237257 logger .Debug ("request" )
238258
259+ slot , err := decodeHash (slotHex )
260+ if err != nil {
261+ return hexutil.Bytes {}, fmt .Errorf ("invalid slot: %w" , err )
262+ }
263+
239264 round , err := api .getBlockRound (ctx , logger , blockNrOrHash )
240265 if err != nil {
241- return hexutil.Big {}, err
266+ return hexutil.Bytes {}, err
242267 }
243268 if api .shouldQueryArchive (round ) {
244- return api .archiveClient .GetStorageAt (ctx , address , position , round )
269+ return api .archiveClient .GetStorageAt (ctx , address , slot , round )
245270 }
246271
247- // EVM module takes index as H256, which needs leading zeros.
248- position256 := make ([]byte , 32 )
249- // Unmarshalling to hexutil.Big rejects overlong inputs. Verify in `TestRejectOverlong`.
250- position .ToInt ().FillBytes (position256 )
251-
252272 ethmod := evm .NewV1 (api .client )
253- res , err := ethmod .Storage (ctx , round , address [:], position256 )
273+ res , err := ethmod .Storage (ctx , round , address [:], slot [:] )
254274 if err != nil {
255275 logger .Error ("failed to query storage" , "err" , err )
256- return hexutil. Big {} , ErrInternalError
276+ return nil , ErrInternalError
257277 }
258- // Some apps expect no leading zeros, so output as big integer.
259- var resultBI big.Int
260- resultBI .SetBytes (res )
261- return hexutil .Big (resultBI ), nil
278+ return res [:], nil
262279}
263280
264281func (api * publicAPI ) GetBalance (ctx context.Context , address common.Address , blockNrOrHash ethrpc.BlockNumberOrHash ) (* hexutil.Big , error ) {
0 commit comments