add transfers

This commit is contained in:
Sina Mahmoodi 2023-06-08 16:47:55 +02:00
parent 4478f20135
commit 2ae2fe50d0
3 changed files with 72 additions and 13 deletions

View file

@ -1105,6 +1105,7 @@ type CallBatch struct {
type callResult struct {
ReturnValue hexutil.Bytes `json:"return"`
Logs []*types.Log `json:"logs"`
Transfers []transfer `json:"transfers,omitempty"`
GasUsed hexutil.Uint64 `json:"gasUsed"`
Error string `json:"error"`
}
@ -1116,12 +1117,11 @@ type callResult struct {
//
// Note, this function doesn't make any changes in the state/blockchain and is
// useful to execute and retrieve values.
func (s *BlockChainAPI) Multicall(ctx context.Context, blocks []CallBatch, blockNrOrHash rpc.BlockNumberOrHash) ([][]callResult, error) {
func (s *BlockChainAPI) Multicall(ctx context.Context, blocks []CallBatch, blockNrOrHash rpc.BlockNumberOrHash, includeTransfers *bool) ([][]callResult, error) {
state, header, err := s.b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
if state == nil || err != nil {
return nil, err
}
// Setup context so it may be cancelled before the calls completed
// or, in case of unmetered gas, setup a context with a timeout.
var (
@ -1166,7 +1166,14 @@ func (s *BlockChainAPI) Multicall(ctx context.Context, blocks []CallBatch, block
// Hack to get logs from statedb which stores logs by txhash.
txhash := common.BigToHash(big.NewInt(int64(i)))
state.SetTxContext(txhash, i)
result, err := doCall(ctx, s.b, call, state, header, timeout, gp, &blockContext, &vm.Config{NoBaseFee: true, DisableECRecover: true})
vmConfig := &vm.Config{NoBaseFee: true}
if block.ECRecoverOverride != nil {
vmConfig.DisableECRecover = true
}
if includeTransfers != nil && *includeTransfers {
vmConfig.Tracer = newTracer()
}
result, err := doCall(ctx, s.b, call, state, header, timeout, gp, &blockContext, vmConfig)
if err != nil {
results[bi][i] = callResult{Error: err.Error()}
continue
@ -1180,7 +1187,11 @@ func (s *BlockChainAPI) Multicall(ctx context.Context, blocks []CallBatch, block
for _, l := range logs {
l.TxHash = common.Hash{}
}
callRes := callResult{ReturnValue: result.Return(), Logs: logs, GasUsed: hexutil.Uint64(result.UsedGas)}
var transfers []transfer
if includeTransfers != nil && *includeTransfers {
transfers = vmConfig.Tracer.(*tracer).Transfers()
}
callRes := callResult{ReturnValue: result.Return(), Logs: logs, Transfers: transfers, GasUsed: hexutil.Uint64(result.UsedGas)}
if result.Err != nil {
callRes.Error = result.Err.Error()
}

View file

@ -629,20 +629,23 @@ func TestMulticall(t *testing.T) {
b.AddTx(tx)
}))
var (
randomAccounts = newAccounts(4)
latest = rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
randomAccounts = newAccounts(4)
latest = rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber)
includeTransfers = true
)
type res struct {
ReturnValue string `json:"return"`
Error string
Logs []types.Log
GasUsed string
Transfers []transfer
}
var testSuite = []struct {
blocks []CallBatch
tag rpc.BlockNumberOrHash
expectErr error
want [][]res
blocks []CallBatch
tag rpc.BlockNumberOrHash
includeTransfers *bool
expectErr error
want [][]res
}{
// State build-up over calls:
// First value transfer OK after state override.
@ -919,10 +922,55 @@ func TestMulticall(t *testing.T) {
GasUsed: "0x52f6",
}}},
},
// Test ether transfers.
{
tag: latest,
blocks: []CallBatch{{
StateOverrides: &StateOverride{
randomAccounts[0].addr: OverrideAccount{
Balance: newRPCBalance(big.NewInt(100)),
// Yul code that transfers 100 wei to address passed in calldata:
// object "Test" {
// code {
// let recipient := shr(96, calldataload(0))
// let value := 100
// let success := call(gas(), recipient, value, 0, 0, 0, 0)
// if eq(success, 0) {
// revert(0, 0)
// }
// }
// }
Code: hex2Bytes("60003560601c606460008060008084865af160008103601d57600080fd5b505050"),
},
},
Calls: []TransactionArgs{{
From: &accounts[0].addr,
To: &randomAccounts[0].addr,
Value: (*hexutil.Big)(big.NewInt(50)),
Input: hex2Bytes(strings.TrimPrefix(randomAccounts[1].addr.String(), "0x")),
}},
}},
includeTransfers: &includeTransfers,
want: [][]res{{{
ReturnValue: "0x",
GasUsed: "0xd984",
Transfers: []transfer{
{
From: accounts[0].addr,
To: randomAccounts[0].addr,
Value: big.NewInt(50),
}, {
From: randomAccounts[0].addr,
To: randomAccounts[1].addr,
Value: big.NewInt(100),
},
},
}}},
},
}
for i, tc := range testSuite {
result, err := api.Multicall(context.Background(), tc.blocks, tc.tag)
result, err := api.Multicall(context.Background(), tc.blocks, tc.tag, tc.includeTransfers)
if tc.expectErr != nil {
if err == nil {
t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr)

View file

@ -614,8 +614,8 @@ web3._extend({
new web3._extend.Method({
name: 'multicall',
call: 'eth_multicall',
params: 2,
inputFormatter: [null, web3._extend.formatters.inputDefaultBlockNumberFormatter],
params: 3,
inputFormatter: [null, web3._extend.formatters.inputDefaultBlockNumberFormatter, null],
}),
],
properties: [