feature: support generate parse transaction input bytes codes in
`abigen`.
It's easy to use abigen to generate code that help you parse the event
log and call the payable method with the transactor.
But parsing the transaction call data is missing. You can only send a
transaction with a transactor. This PR aims to generate codes that help
developer parse transaction calldata.
abigen can generate code to parse the transaction call data.
With this PR, transaction parse codes are generated like this:
```go
// CollectParams is an auto generated read-only Go binding of transcaction calldata params
type CollectParams struct {
Param_params INonfungiblePositionManagerCollectParams
}
// Parse Collect method from calldata of a transaction
//
// Solidity: function collect((uint256,address,uint128,uint128) params) payable returns(uint256 amount0, uint256 amount1)
func ParseCollect(calldata []byte) (*CollectParams, error) {
if len(calldata) <= 4 {
return nil, fmt.Errorf("invalid calldata input")
}
_abi, err := abi.JSON(strings.NewReader(UniswapABI))
if err != nil {
return nil, fmt.Errorf("failed to get abi of registry metadata: %w", err)
}
out, err := _abi.Methods["collect"].Inputs.Unpack(calldata[4:])
if err != nil {
return nil, fmt.Errorf("failed to unpack collect params data: %w", err)
}
var paramsResult = new(CollectParams)
value := reflect.ValueOf(paramsResult).Elem()
if value.NumField() != len(out) {
return nil, fmt.Errorf("failed to match calldata with param field number")
}
out0 := *abi.ConvertType(out[0], new(INonfungiblePositionManagerCollectParams)).(*INonfungiblePositionManagerCollectParams)
return &CollectParams{
Param_params: out0,
}, nil
}
```
Example of using `Parse` Function above:
```go
package bin
import (
"context"
"fmt"
"testing"
"github.com/ledgerwatch/erigon/common/hexutil"
"github.com/ledgerwatch/erigon/rpc"
"github.com/ledgerwatch/log/v3"
)
func TestOnParse(t *testing.T) {
cli, err := rpc.Dial("https://rpc.ankr.com/polygon", log.New(context.Background()))
if err != nil {
t.Fatal(err)
}
var collectTx struct {
Input string `json:"input"`
}
err = cli.CallContext(context.Background(), &collectTx, "eth_getTransactionByHash", "0x741146cce64d873cfe82ade413651de355a6db92f992e5bfc4e1c58d92f5dd5b")
if err != nil {
t.Fatal(err)
}
var increaseLiquidityTx struct {
Input string `json:"input"`
}
err = cli.CallContext(context.Background(), &increaseLiquidityTx, "eth_getTransactionByHash", "0x645ff650d7bfb9a74f573af474b9ebee48c3fadc7dac67257a8da6b55c71f338")
if err != nil {
t.Fatal(err)
}
fmt.Println(collectTx.Input)
fmt.Println(increaseLiquidityTx.Input)
collectBytes, _ := hexutil.Decode(collectTx.Input)
increaseLiquidityBytes, _ := hexutil.Decode(increaseLiquidityTx.Input)
collectInfo, err := ParseCollect(collectBytes)
if err != nil {
t.Fatal(err)
}
increaseLiquidityInfo, err := ParseIncreaseLiquidity(increaseLiquidityBytes)
if err != nil {
t.Fatal(err)
}
fmt.Printf("%+v\n", collectInfo)
fmt.Printf("%+v\n", increaseLiquidityInfo)
}
```
Output of code above:
&{Param_params:{TokenId:+894123
Recipient:0x48B8e4ed457da9B64c33Ee50Fd5490614833A37D
Amount0Max:+340282366920938463463374607431768211455
Amount1Max:+340282366920938463463374607431768211455}}
&{Param_params:{TokenId:+891904 Amount0Desired:+331092 Amount1Desired:+0
Amount0Min:+331092 Amount1Min:+0 Deadline:+1685112789}}
- always RLock all snapshots - to guarantee consistency
- introduce class View (analog of RoTx and MakeContext)
- move read methods to View object
- View object will be managed by temporal_tx
---------
Co-authored-by: Alex Sharp <alexsharp@Alexs-MacBook-Pro-2.local>
In this PR Header's ExcessDataGas is set to the actual value, but it's
still unused. It will be used to compute data fee for eip-4844 data
blobs, logic of which will be added in later PRs. Also eip-4844 header
verification logic added.
`excessDataGas` has been partially made eip-4844 ready, so instead of
passing nils to functions, now it actually assigned to some value (it is
expected to be nil until cancun update).
Small change in core.NewEVMBlockContext and now it expects
excessDataGas. This will be used in state transition to compute data fee
for eip-4844 data blobs. The logic that computes it will be added in the
next PRs.
Cherry-pick https://github.com/ethereum/go-ethereum/pull/24017.
* core/vm: Define 0xfe opcode as INVALID
* core/vm: Remove opInvalid as opUndefined handles it
Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>
Co-authored-by: Andrei Maiboroda <andrei@ethereum.org>
Co-authored-by: Alex Beregszaszi <alex@rtfs.hu>
Works around a flaw in the upgrade logic of the system contracts. Since
they are updated directly, without first being self-destructed and then
re-created, the usual incarnation logic does not get activated, and all
historical records of the code of these contracts are retrieved as the
most recent version. This problem will not exist in erigon3, but until
then, a workaround will be used to access code of such contracts through
a special structure, `SystemContractCodeLookup`
Fixes https://github.com/ledgerwatch/erigon/issues/5865
Co-authored-by: Alexey Sharp <alexeysharp@Alexeys-iMac.local>
So there is an issue with tracing certain blocks/transactions on
Polygon, for example:
```
> '{"method": "trace_transaction","params":["0xb198d93f640343a98f90d93aa2b74b4fc5c64f3a649f1608d2bfd1004f9dee0e"],"id":1,"jsonrpc":"2.0"}'
```
gives the error `first run for txIndex 1 error: insufficient funds for
gas * price + value: address 0x10AD27A96CDBffC90ab3b83bF695911426A69f5E
have 16927727762862809 want 17594166808296934`
The reason is that this transaction is from the author of the block,
which doesn't have enough ETH to pay for the gas fee + tx value if he's
not the block author receiving transactions fees.
The issue is that currently the APIs are using `ethash.NewFaker()`
Engine for running traces, etc. which doesn't know how to get the author
for a specific block (which is consensus dependant); as it was noting in
several TODO comments.
The fix is to pass the Engine to the BaseAPI, which can then be used to
create the right Block Context. I chose to split the current Engine
interface in 2, with Reader and Writer, so that the BaseAPI only
receives the Reader one, which might be safer (even though it's only
used for getting the block Author).