add ecrecover override

This commit is contained in:
Sina Mahmoodi 2023-06-06 11:16:37 +02:00
parent 80df50db7e
commit c3f149425a
2 changed files with 67 additions and 7 deletions

View file

@ -1012,16 +1012,16 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash
// Make sure the context is cancelled when the call has completed
// this makes sure resources are cleaned up.
defer cancel()
return doCall(ctx, b, args, state, header, timeout, new(core.GasPool).AddGas(globalGasCap), &blockCtx)
return doCall(ctx, b, args, state, header, timeout, new(core.GasPool).AddGas(globalGasCap), &blockCtx, &vm.Config{NoBaseFee: true})
}
func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, timeout time.Duration, gp *core.GasPool, blockContext *vm.BlockContext) (*core.ExecutionResult, error) {
func doCall(ctx context.Context, b Backend, args TransactionArgs, state *state.StateDB, header *types.Header, timeout time.Duration, gp *core.GasPool, blockContext *vm.BlockContext, vmConfig *vm.Config) (*core.ExecutionResult, error) {
// Get a new instance of the EVM.
msg, err := args.ToMessage(gp.Gas(), header.BaseFee)
if err != nil {
return nil, err
}
evm, vmError := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, blockContext)
evm, vmError := b.GetEVM(ctx, msg, state, header, vmConfig, blockContext)
// Wait for the context to be done and cancel the evm. Even if the
// EVM has finished, cancelling may be done (repeatedly)
@ -1098,6 +1098,7 @@ func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrO
type CallBatch struct {
BlockOverrides *BlockOverrides
StateOverrides *StateOverride
ECRecoverOverride *hexutil.Bytes // Override bytecode for ecrecover precompile.
Calls []TransactionArgs
}
@ -1146,6 +1147,10 @@ func (s *BlockChainAPI) Multicall(ctx context.Context, blocks []CallBatch, block
if err := block.StateOverrides.Apply(state); err != nil {
return nil, err
}
// ECRecover replacement code will be fetched from statedb and executed as a normal EVM bytecode.
if block.ECRecoverOverride != nil {
state.SetCode(common.BytesToAddress([]byte{1}), *block.ECRecoverOverride)
}
blockContext := core.NewEVMBlockContext(header, NewChainContext(ctx, s.b), nil)
if block.BlockOverrides != nil {
block.BlockOverrides.Apply(&blockContext)
@ -1155,7 +1160,7 @@ 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)
result, err := doCall(ctx, s.b, call, state, header, timeout, gp, &blockContext, &vm.Config{NoBaseFee: true, DisableECRecover: true})
if err != nil {
return nil, err
}

View file

@ -26,6 +26,7 @@ import (
"math/big"
"reflect"
"sort"
"strings"
"testing"
"time"
@ -776,6 +777,60 @@ func TestMulticall(t *testing.T) {
GasUsed: "0x5508",
}}},
},
// Test ecrecover override
{
tag: latest,
blocks: []CallBatch{{
StateOverrides: &StateOverride{
randomAccounts[2].addr: OverrideAccount{
// Yul code that returns ecrecover(0, 0, 0, 0).
// object "Test" {
// code {
// // Free memory pointer
// let free_ptr := mload(0x40)
//
// // Initialize inputs with zeros
// mstore(free_ptr, 0) // Hash
// mstore(add(free_ptr, 0x20), 0) // v
// mstore(add(free_ptr, 0x40), 0) // r
// mstore(add(free_ptr, 0x60), 0) // s
//
// // Call ecrecover precompile (at address 1) with all 0 inputs
// let success := staticcall(gas(), 1, free_ptr, 0x80, free_ptr, 0x20)
//
// // Check if the call was successful
// if eq(success, 0) {
// revert(0, 0)
// }
//
// // Return the recovered address
// return(free_ptr, 0x14)
// }
// }
Code: hex2Bytes("6040516000815260006020820152600060408201526000606082015260208160808360015afa60008103603157600080fd5b601482f3"),
},
},
BlockOverrides: &BlockOverrides{},
// Yul code that returns the address of the caller.
// object "Test" {
// code {
// let c := caller()
// mstore(0, c)
// return(0xc, 0x14)
// }
// }
ECRecoverOverride: hex2Bytes("33806000526014600cf3"),
Calls: []TransactionArgs{{
From: &randomAccounts[0].addr,
To: &randomAccounts[2].addr,
}},
}},
want: [][]res{{{
// Caller is in this case the contract that invokes ecrecover.
ReturnValue: strings.ToLower(randomAccounts[2].addr.String()),
GasUsed: "0x52f6",
}}},
},
}
for i, tc := range testSuite {