mirror of
https://github.com/forta-network/go-multicall.git
synced 2026-05-28 18:54:01 +00:00
fix: multiple bug fixes and safety improvements
- call.go: safe type assertion in UnpackResult() to prevent panic - call.go: warn when ABI returns more values than struct fields - caller.go: use len() check instead of nil check for variadic multicallAddr - caller.go: return allCalls (partial results) on CallChunked error - caller_test.go: strip 4-byte method selector from stub return data Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
ff027d0059
commit
c6cbb984a3
3 changed files with 12 additions and 4 deletions
10
call.go
10
call.go
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
|
|
@ -77,7 +78,11 @@ func (call *Call) UnpackResult() []interface{} {
|
|||
if call.Outputs == nil {
|
||||
return nil
|
||||
}
|
||||
return call.Outputs.([]interface{})
|
||||
result, ok := call.Outputs.([]interface{})
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// AllowFailure sets if the call is allowed to fail. This helps avoiding a revert
|
||||
|
|
@ -111,6 +116,9 @@ func (call *Call) Unpack(b []byte) error {
|
|||
if fieldCount > len(out) {
|
||||
return fmt.Errorf("struct has %d fields but ABI returned %d values", fieldCount, len(out))
|
||||
}
|
||||
if len(out) > fieldCount {
|
||||
log.Printf("warning: method '%s' returned %d values but struct only has %d fields; extra values ignored", call.Method, len(out), fieldCount)
|
||||
}
|
||||
for i := 0; i < fieldCount; i++ {
|
||||
field := t.Field(i)
|
||||
if !field.CanSet() {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ type Caller struct {
|
|||
// New creates a new caller.
|
||||
func New(client bind.ContractCaller, multicallAddr ...string) (*Caller, error) {
|
||||
addr := DefaultAddress
|
||||
if multicallAddr != nil {
|
||||
if len(multicallAddr) > 0 {
|
||||
addr = multicallAddr[0]
|
||||
}
|
||||
contract, err := contract_multicall.NewMulticallCaller(common.HexToAddress(addr), client)
|
||||
|
|
@ -107,7 +107,7 @@ func (caller *Caller) CallChunked(opts *bind.CallOpts, chunkSize int, cooldown t
|
|||
|
||||
chunk, err := caller.calls(opts, chunk...)
|
||||
if err != nil {
|
||||
return calls, fmt.Errorf("call chunk [%d] failed: %v", i, err)
|
||||
return allCalls, fmt.Errorf("call chunk [%d] failed: %v", i, err)
|
||||
}
|
||||
allCalls = append(allCalls, chunk...)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ func TestCaller_WrongOutputsType(t *testing.T) {
|
|||
contract: &multicallStub{
|
||||
returnData: func(calls []contract_multicall.Multicall3Call3) [][]byte {
|
||||
return [][]byte{
|
||||
packedOutput,
|
||||
packedOutput[4:], // strip 4-byte method selector; return data is ABI-encoded outputs only
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue