diff --git a/clients/base_client.go b/clients/base_client.go index 730ec05..6a9dcef 100644 --- a/clients/base_client.go +++ b/clients/base_client.go @@ -754,3 +754,13 @@ func (c *BaseClient) getBlock(ctx context.Context, method string, args ...interf L1BatchTimestamp: block.L1BatchTimestamp.ToInt(), }, nil } + +// Proof Returns Merkle proofs for one or more storage values at the specified account along with a Merkle proof of their authenticity. +func (c *BaseClient) Proof(ctx context.Context, address common.Address, keys []common.Hash, l1BatchNumber *big.Int) (*zkTypes.StorageProof, error) { + var res zkTypes.StorageProof + err := c.rpcClient.CallContext(ctx, &res, "zks_getProof", address, keys, l1BatchNumber) + if err != nil { + return nil, fmt.Errorf("failed to query zks_getProof: %w", err) + } + return &res, nil +} diff --git a/test/base_client_test.go b/test/base_client_test.go index 574fdc1..c7efef2 100644 --- a/test/base_client_test.go +++ b/test/base_client_test.go @@ -899,17 +899,6 @@ func TestIntegrationBaseClient_TransactionDetails(t *testing.T) { assert.NotNil(t, txDetails, "TransactionDetails should return a non-nil block details") } -//func TestIntegrationBaseClient_LogProof(t *testing.T) { -// client, err := clients.Dial(ZkSyncEraProvider) -// defer client.Close() -// assert.NoError(t, err, "clients.Dial should not return an error") -// -// logProof, err := client.LogProof(context.Background()) -// -// assert.NoError(t, err, "LogProof should not return an error") -// assert.NotNil(t, logProof, "LogProof should return a non-nil block range") -//} - func TestIntegrationBaseClient_L2TransactionFromPriorityOp(t *testing.T) { client, err := clients.Dial(ZkSyncEraProvider) defer client.Close() @@ -1047,3 +1036,34 @@ func TestIntegrationBaseClient_EstimateL1ToL2Execute(t *testing.T) { assert.NoError(t, err, "EstimateL1ToL2Execute should not return an error") assert.Greater(t, gas, uint64(0), "EstimateL1ToL2Execute should return a positive number") } + +//func TestIntegrationBaseClient_Proof(t *testing.T) { +// client, err := clients.Dial(ZkSyncEraProvider) +// defer client.Close() +// assert.NoError(t, err, "clients.Dial should not return an error") +// +// baseClient, ok := client.(*clients.BaseClient) +// assert.True(t, ok, "Casting should not return error") +// +// addressPadded := common.LeftPadBytes(Address.Bytes(), 32) +// +// // Convert the slot number to a hex string and pad it to 32 bytes +// slotBytes := common.Hex2Bytes("0x00") // slot with index 0 +// slotPadded := common.LeftPadBytes(slotBytes, 32) +// +// // Concatenate the padded address and slot number +// concatenated := append(addressPadded, slotPadded...) +// storageKey := crypto.Keccak256(concatenated) +// +// l1BatchNumber, err := client.L1BatchNumber(context.Background()) +// assert.NoError(t, err, "L1BatchNumber should not return an error") +// +// storageProof, err := baseClient.Proof( +// context.Background(), +// utils.NonceHolderAddress, +// []common.Hash{common.BytesToHash(storageKey)}, +// l1BatchNumber) +// +// assert.NoError(t, err, "Proof should not return an error") +// assert.NotNil(t, storageProof, "Proof should return a non-nil value") +//} diff --git a/types/proof.go b/types/proof.go index 70dd54f..209ce6a 100644 --- a/types/proof.go +++ b/types/proof.go @@ -8,3 +8,14 @@ type MessageProof struct { Proof []common.Hash `json:"proof"` Root common.Hash `json:"root"` } + +// StorageProof Merkle proofs for one or more storage values at the specified account +type StorageProof struct { + Address string `json:"address"` + Proofs []struct { + Key string `json:"key"` + Proof []string `json:"proof"` + Value string `json:"value"` + Index int `json:"index"` + } `json:"storageProof"` +}