|
package eth
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math/big"
|
|
"strings"
|
|
|
|
"github.com/ethereum/go-ethereum"
|
|
"github.com/ethereum/go-ethereum/accounts/abi"
|
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
|
ethCommon "github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/crypto"
|
|
"github.com/ethereum/go-ethereum/ethclient"
|
|
"github.com/hermeznetwork/hermez-node/common"
|
|
WithdrawalDelayer "github.com/hermeznetwork/hermez-node/eth/contracts/withdrawdelayer"
|
|
"github.com/hermeznetwork/hermez-node/log"
|
|
"github.com/hermeznetwork/tracerr"
|
|
)
|
|
|
|
// DepositState is the state of Deposit
|
|
type DepositState struct {
|
|
Amount *big.Int
|
|
DepositTimestamp uint64
|
|
}
|
|
|
|
// WDelayerEventDeposit is an event of the WithdrawalDelayer Smart Contract
|
|
type WDelayerEventDeposit struct {
|
|
Owner ethCommon.Address
|
|
Token ethCommon.Address
|
|
Amount *big.Int
|
|
DepositTimestamp uint64
|
|
TxHash ethCommon.Hash // Hash of the transaction that generated this event
|
|
}
|
|
|
|
// WDelayerEventWithdraw is an event of the WithdrawalDelayer Smart Contract
|
|
type WDelayerEventWithdraw struct {
|
|
Owner ethCommon.Address
|
|
Token ethCommon.Address
|
|
Amount *big.Int
|
|
}
|
|
|
|
// WDelayerEventEmergencyModeEnabled an event of the WithdrawalDelayer Smart Contract
|
|
type WDelayerEventEmergencyModeEnabled struct {
|
|
}
|
|
|
|
// WDelayerEventNewWithdrawalDelay an event of the WithdrawalDelayer Smart Contract
|
|
type WDelayerEventNewWithdrawalDelay struct {
|
|
WithdrawalDelay uint64
|
|
}
|
|
|
|
// WDelayerEventEscapeHatchWithdrawal an event of the WithdrawalDelayer Smart Contract
|
|
type WDelayerEventEscapeHatchWithdrawal struct {
|
|
Who ethCommon.Address
|
|
To ethCommon.Address
|
|
Token ethCommon.Address
|
|
Amount *big.Int
|
|
}
|
|
|
|
// WDelayerEventNewEmergencyCouncil an event of the WithdrawalDelayer Smart Contract
|
|
type WDelayerEventNewEmergencyCouncil struct {
|
|
NewEmergencyCouncil ethCommon.Address
|
|
}
|
|
|
|
// WDelayerEventNewHermezGovernanceAddress an event of the WithdrawalDelayer Smart Contract
|
|
type WDelayerEventNewHermezGovernanceAddress struct {
|
|
NewHermezGovernanceAddress ethCommon.Address
|
|
}
|
|
|
|
// WDelayerEvents is the lis of events in a block of the WithdrawalDelayer Smart Contract
|
|
type WDelayerEvents struct {
|
|
Deposit []WDelayerEventDeposit
|
|
Withdraw []WDelayerEventWithdraw
|
|
EmergencyModeEnabled []WDelayerEventEmergencyModeEnabled
|
|
NewWithdrawalDelay []WDelayerEventNewWithdrawalDelay
|
|
EscapeHatchWithdrawal []WDelayerEventEscapeHatchWithdrawal
|
|
NewEmergencyCouncil []WDelayerEventNewEmergencyCouncil
|
|
NewHermezGovernanceAddress []WDelayerEventNewHermezGovernanceAddress
|
|
}
|
|
|
|
// NewWDelayerEvents creates an empty WDelayerEvents with the slices initialized.
|
|
func NewWDelayerEvents() WDelayerEvents {
|
|
return WDelayerEvents{
|
|
Deposit: make([]WDelayerEventDeposit, 0),
|
|
Withdraw: make([]WDelayerEventWithdraw, 0),
|
|
EmergencyModeEnabled: make([]WDelayerEventEmergencyModeEnabled, 0),
|
|
NewWithdrawalDelay: make([]WDelayerEventNewWithdrawalDelay, 0),
|
|
EscapeHatchWithdrawal: make([]WDelayerEventEscapeHatchWithdrawal, 0),
|
|
NewEmergencyCouncil: make([]WDelayerEventNewEmergencyCouncil, 0),
|
|
NewHermezGovernanceAddress: make([]WDelayerEventNewHermezGovernanceAddress, 0),
|
|
}
|
|
}
|
|
|
|
// WDelayerInterface is the inteface to WithdrawalDelayer Smart Contract
|
|
type WDelayerInterface interface {
|
|
//
|
|
// Smart Contract Methods
|
|
//
|
|
|
|
WDelayerGetHermezGovernanceAddress() (*ethCommon.Address, error)
|
|
WDelayerTransferGovernance(newAddress ethCommon.Address) (*types.Transaction, error)
|
|
WDelayerClaimGovernance() (*types.Transaction, error)
|
|
WDelayerGetEmergencyCouncil() (*ethCommon.Address, error)
|
|
WDelayerTransferEmergencyCouncil(newAddress ethCommon.Address) (*types.Transaction, error)
|
|
WDelayerClaimEmergencyCouncil() (*types.Transaction, error)
|
|
WDelayerIsEmergencyMode() (bool, error)
|
|
WDelayerGetWithdrawalDelay() (*big.Int, error)
|
|
WDelayerGetEmergencyModeStartingTime() (*big.Int, error)
|
|
WDelayerEnableEmergencyMode() (*types.Transaction, error)
|
|
WDelayerChangeWithdrawalDelay(newWithdrawalDelay uint64) (*types.Transaction, error)
|
|
WDelayerDepositInfo(owner, token ethCommon.Address) (depositInfo DepositState, err error)
|
|
WDelayerDeposit(onwer, token ethCommon.Address, amount *big.Int) (*types.Transaction, error)
|
|
WDelayerWithdrawal(owner, token ethCommon.Address) (*types.Transaction, error)
|
|
WDelayerEscapeHatchWithdrawal(to, token ethCommon.Address, amount *big.Int) (*types.Transaction, error)
|
|
|
|
WDelayerEventsByBlock(blockNum int64) (*WDelayerEvents, *ethCommon.Hash, error)
|
|
WDelayerConstants() (*common.WDelayerConstants, error)
|
|
}
|
|
|
|
//
|
|
// Implementation
|
|
//
|
|
|
|
// WDelayerClient is the implementation of the interface to the WithdrawDelayer Smart Contract in ethereum.
|
|
type WDelayerClient struct {
|
|
client *EthereumClient
|
|
address ethCommon.Address
|
|
wdelayer *WithdrawalDelayer.WithdrawalDelayer
|
|
contractAbi abi.ABI
|
|
}
|
|
|
|
// NewWDelayerClient creates a new WDelayerClient
|
|
func NewWDelayerClient(client *EthereumClient, address ethCommon.Address) (*WDelayerClient, error) {
|
|
contractAbi, err := abi.JSON(strings.NewReader(string(WithdrawalDelayer.WithdrawalDelayerABI)))
|
|
if err != nil {
|
|
return nil, tracerr.Wrap(err)
|
|
}
|
|
wdelayer, err := WithdrawalDelayer.NewWithdrawalDelayer(address, client.Client())
|
|
if err != nil {
|
|
return nil, tracerr.Wrap(err)
|
|
}
|
|
return &WDelayerClient{
|
|
client: client,
|
|
address: address,
|
|
wdelayer: wdelayer,
|
|
contractAbi: contractAbi,
|
|
}, nil
|
|
}
|
|
|
|
// WDelayerGetHermezGovernanceAddress is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerGetHermezGovernanceAddress() (hermezGovernanceAddress *ethCommon.Address, err error) {
|
|
var _hermezGovernanceAddress ethCommon.Address
|
|
if err := c.client.Call(func(ec *ethclient.Client) error {
|
|
_hermezGovernanceAddress, err = c.wdelayer.GetHermezGovernanceAddress(nil)
|
|
return tracerr.Wrap(err)
|
|
}); err != nil {
|
|
return nil, tracerr.Wrap(err)
|
|
}
|
|
return &_hermezGovernanceAddress, nil
|
|
}
|
|
|
|
// WDelayerTransferGovernance is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerTransferGovernance(newAddress ethCommon.Address) (tx *types.Transaction, err error) {
|
|
if tx, err = c.client.CallAuth(
|
|
0,
|
|
func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
|
|
return c.wdelayer.TransferGovernance(auth, newAddress)
|
|
},
|
|
); err != nil {
|
|
return nil, tracerr.Wrap(fmt.Errorf("Failed transfer hermezGovernanceAddress: %w", err))
|
|
}
|
|
return tx, nil
|
|
}
|
|
|
|
// WDelayerClaimGovernance is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerClaimGovernance() (tx *types.Transaction, err error) {
|
|
if tx, err = c.client.CallAuth(
|
|
0,
|
|
func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
|
|
return c.wdelayer.ClaimGovernance(auth)
|
|
},
|
|
); err != nil {
|
|
return nil, tracerr.Wrap(fmt.Errorf("Failed claim hermezGovernanceAddress: %w", err))
|
|
}
|
|
return tx, nil
|
|
}
|
|
|
|
// WDelayerGetEmergencyCouncil is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerGetEmergencyCouncil() (emergencyCouncilAddress *ethCommon.Address, err error) {
|
|
var _emergencyCouncilAddress ethCommon.Address
|
|
if err := c.client.Call(func(ec *ethclient.Client) error {
|
|
_emergencyCouncilAddress, err = c.wdelayer.GetEmergencyCouncil(nil)
|
|
return tracerr.Wrap(err)
|
|
}); err != nil {
|
|
return nil, tracerr.Wrap(err)
|
|
}
|
|
return &_emergencyCouncilAddress, nil
|
|
}
|
|
|
|
// WDelayerTransferEmergencyCouncil is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerTransferEmergencyCouncil(newAddress ethCommon.Address) (tx *types.Transaction, err error) {
|
|
if tx, err = c.client.CallAuth(
|
|
0,
|
|
func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
|
|
return c.wdelayer.TransferEmergencyCouncil(auth, newAddress)
|
|
},
|
|
); err != nil {
|
|
return nil, tracerr.Wrap(fmt.Errorf("Failed transfer EmergencyCouncil: %w", err))
|
|
}
|
|
return tx, nil
|
|
}
|
|
|
|
// WDelayerClaimEmergencyCouncil is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerClaimEmergencyCouncil() (tx *types.Transaction, err error) {
|
|
if tx, err = c.client.CallAuth(
|
|
0,
|
|
func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
|
|
return c.wdelayer.ClaimEmergencyCouncil(auth)
|
|
},
|
|
); err != nil {
|
|
return nil, tracerr.Wrap(fmt.Errorf("Failed claim EmergencyCouncil: %w", err))
|
|
}
|
|
return tx, nil
|
|
}
|
|
|
|
// WDelayerIsEmergencyMode is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerIsEmergencyMode() (ermergencyMode bool, err error) {
|
|
if err := c.client.Call(func(ec *ethclient.Client) error {
|
|
ermergencyMode, err = c.wdelayer.IsEmergencyMode(nil)
|
|
return tracerr.Wrap(err)
|
|
}); err != nil {
|
|
return false, tracerr.Wrap(err)
|
|
}
|
|
return ermergencyMode, nil
|
|
}
|
|
|
|
// WDelayerGetWithdrawalDelay is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerGetWithdrawalDelay() (withdrawalDelay *big.Int, err error) {
|
|
if err := c.client.Call(func(ec *ethclient.Client) error {
|
|
withdrawalDelay, err = c.wdelayer.GetWithdrawalDelay(nil)
|
|
return tracerr.Wrap(err)
|
|
}); err != nil {
|
|
return nil, tracerr.Wrap(err)
|
|
}
|
|
return withdrawalDelay, nil
|
|
}
|
|
|
|
// WDelayerGetEmergencyModeStartingTime is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerGetEmergencyModeStartingTime() (emergencyModeStartingTime *big.Int, err error) {
|
|
if err := c.client.Call(func(ec *ethclient.Client) error {
|
|
emergencyModeStartingTime, err = c.wdelayer.GetEmergencyModeStartingTime(nil)
|
|
return tracerr.Wrap(err)
|
|
}); err != nil {
|
|
return nil, tracerr.Wrap(err)
|
|
}
|
|
return emergencyModeStartingTime, nil
|
|
}
|
|
|
|
// WDelayerEnableEmergencyMode is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerEnableEmergencyMode() (tx *types.Transaction, err error) {
|
|
if tx, err = c.client.CallAuth(
|
|
0,
|
|
func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
|
|
return c.wdelayer.EnableEmergencyMode(auth)
|
|
},
|
|
); err != nil {
|
|
return nil, tracerr.Wrap(fmt.Errorf("Failed setting enable emergency mode: %w", err))
|
|
}
|
|
return tx, nil
|
|
}
|
|
|
|
// WDelayerChangeWithdrawalDelay is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerChangeWithdrawalDelay(newWithdrawalDelay uint64) (tx *types.Transaction, err error) {
|
|
if tx, err = c.client.CallAuth(
|
|
0,
|
|
func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
|
|
return c.wdelayer.ChangeWithdrawalDelay(auth, newWithdrawalDelay)
|
|
},
|
|
); err != nil {
|
|
return nil, tracerr.Wrap(fmt.Errorf("Failed setting withdrawal delay: %w", err))
|
|
}
|
|
return tx, nil
|
|
}
|
|
|
|
// WDelayerDepositInfo is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerDepositInfo(owner, token ethCommon.Address) (depositInfo DepositState, err error) {
|
|
if err := c.client.Call(func(ec *ethclient.Client) error {
|
|
amount, depositTimestamp, err := c.wdelayer.DepositInfo(nil, owner, token)
|
|
depositInfo.Amount = amount
|
|
depositInfo.DepositTimestamp = depositTimestamp
|
|
return tracerr.Wrap(err)
|
|
}); err != nil {
|
|
return depositInfo, tracerr.Wrap(err)
|
|
}
|
|
return depositInfo, nil
|
|
}
|
|
|
|
// WDelayerDeposit is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerDeposit(owner, token ethCommon.Address, amount *big.Int) (tx *types.Transaction, err error) {
|
|
if tx, err = c.client.CallAuth(
|
|
0,
|
|
func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
|
|
return c.wdelayer.Deposit(auth, owner, token, amount)
|
|
},
|
|
); err != nil {
|
|
return nil, tracerr.Wrap(fmt.Errorf("Failed deposit: %w", err))
|
|
}
|
|
return tx, nil
|
|
}
|
|
|
|
// WDelayerWithdrawal is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerWithdrawal(owner, token ethCommon.Address) (tx *types.Transaction, err error) {
|
|
if tx, err = c.client.CallAuth(
|
|
0,
|
|
func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
|
|
return c.wdelayer.Withdrawal(auth, owner, token)
|
|
},
|
|
); err != nil {
|
|
return nil, tracerr.Wrap(fmt.Errorf("Failed withdrawal: %w", err))
|
|
}
|
|
return tx, nil
|
|
}
|
|
|
|
// WDelayerEscapeHatchWithdrawal is the interface to call the smart contract function
|
|
func (c *WDelayerClient) WDelayerEscapeHatchWithdrawal(to, token ethCommon.Address, amount *big.Int) (tx *types.Transaction, err error) {
|
|
if tx, err = c.client.CallAuth(
|
|
0,
|
|
func(ec *ethclient.Client, auth *bind.TransactOpts) (*types.Transaction, error) {
|
|
return c.wdelayer.EscapeHatchWithdrawal(auth, to, token, amount)
|
|
},
|
|
); err != nil {
|
|
return nil, tracerr.Wrap(fmt.Errorf("Failed escapeHatchWithdrawal: %w", err))
|
|
}
|
|
return tx, nil
|
|
}
|
|
|
|
// WDelayerConstants returns the Constants of the WDelayer Smart Contract
|
|
func (c *WDelayerClient) WDelayerConstants() (constants *common.WDelayerConstants, err error) {
|
|
constants = new(common.WDelayerConstants)
|
|
if err := c.client.Call(func(ec *ethclient.Client) error {
|
|
constants.MaxWithdrawalDelay, err = c.wdelayer.MAXWITHDRAWALDELAY(nil)
|
|
if err != nil {
|
|
return tracerr.Wrap(err)
|
|
}
|
|
constants.MaxEmergencyModeTime, err = c.wdelayer.MAXEMERGENCYMODETIME(nil)
|
|
if err != nil {
|
|
return tracerr.Wrap(err)
|
|
}
|
|
constants.HermezRollup, err = c.wdelayer.HermezRollupAddress(nil)
|
|
if err != nil {
|
|
return tracerr.Wrap(err)
|
|
}
|
|
return tracerr.Wrap(err)
|
|
}); err != nil {
|
|
return constants, tracerr.Wrap(err)
|
|
}
|
|
return constants, nil
|
|
}
|
|
|
|
var (
|
|
logWDelayerDeposit = crypto.Keccak256Hash([]byte("Deposit(address,address,uint192,uint64)"))
|
|
logWDelayerWithdraw = crypto.Keccak256Hash([]byte("Withdraw(address,address,uint192)"))
|
|
logWDelayerEmergencyModeEnabled = crypto.Keccak256Hash([]byte("EmergencyModeEnabled()"))
|
|
logWDelayerNewWithdrawalDelay = crypto.Keccak256Hash([]byte("NewWithdrawalDelay(uint64)"))
|
|
logWDelayerEscapeHatchWithdrawal = crypto.Keccak256Hash([]byte("EscapeHatchWithdrawal(address,address,address,uint256)"))
|
|
logWDelayerNewEmergencyCouncil = crypto.Keccak256Hash([]byte("NewEmergencyCouncil(address)"))
|
|
logWDelayerNewHermezGovernanceAddress = crypto.Keccak256Hash([]byte("NewHermezGovernanceAddress(address)"))
|
|
)
|
|
|
|
// WDelayerEventsByBlock returns the events in a block that happened in the
|
|
// WDelayer Smart Contract and the blockHash where the eents happened. If
|
|
// there are no events in that block, blockHash is nil.
|
|
func (c *WDelayerClient) WDelayerEventsByBlock(blockNum int64) (*WDelayerEvents, *ethCommon.Hash, error) {
|
|
var wdelayerEvents WDelayerEvents
|
|
var blockHash *ethCommon.Hash
|
|
|
|
query := ethereum.FilterQuery{
|
|
FromBlock: big.NewInt(blockNum),
|
|
ToBlock: big.NewInt(blockNum),
|
|
Addresses: []ethCommon.Address{
|
|
c.address,
|
|
},
|
|
BlockHash: nil,
|
|
Topics: [][]ethCommon.Hash{},
|
|
}
|
|
|
|
logs, err := c.client.client.FilterLogs(context.Background(), query)
|
|
if err != nil {
|
|
return nil, nil, tracerr.Wrap(err)
|
|
}
|
|
if len(logs) > 0 {
|
|
blockHash = &logs[0].BlockHash
|
|
}
|
|
for _, vLog := range logs {
|
|
if vLog.BlockHash != *blockHash {
|
|
log.Errorw("Block hash mismatch", "expected", blockHash.String(), "got", vLog.BlockHash.String())
|
|
return nil, nil, tracerr.Wrap(ErrBlockHashMismatchEvent)
|
|
}
|
|
switch vLog.Topics[0] {
|
|
case logWDelayerDeposit:
|
|
var deposit WDelayerEventDeposit
|
|
err := c.contractAbi.Unpack(&deposit, "Deposit", vLog.Data)
|
|
if err != nil {
|
|
return nil, nil, tracerr.Wrap(err)
|
|
}
|
|
deposit.Owner = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
|
|
deposit.Token = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
|
|
deposit.TxHash = vLog.TxHash
|
|
wdelayerEvents.Deposit = append(wdelayerEvents.Deposit, deposit)
|
|
|
|
case logWDelayerWithdraw:
|
|
var withdraw WDelayerEventWithdraw
|
|
err := c.contractAbi.Unpack(&withdraw, "Withdraw", vLog.Data)
|
|
if err != nil {
|
|
return nil, nil, tracerr.Wrap(err)
|
|
}
|
|
withdraw.Token = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
|
|
withdraw.Owner = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
|
|
wdelayerEvents.Withdraw = append(wdelayerEvents.Withdraw, withdraw)
|
|
|
|
case logWDelayerEmergencyModeEnabled:
|
|
var emergencyModeEnabled WDelayerEventEmergencyModeEnabled
|
|
wdelayerEvents.EmergencyModeEnabled = append(wdelayerEvents.EmergencyModeEnabled, emergencyModeEnabled)
|
|
|
|
case logWDelayerNewWithdrawalDelay:
|
|
var withdrawalDelay WDelayerEventNewWithdrawalDelay
|
|
err := c.contractAbi.Unpack(&withdrawalDelay, "NewWithdrawalDelay", vLog.Data)
|
|
if err != nil {
|
|
return nil, nil, tracerr.Wrap(err)
|
|
}
|
|
wdelayerEvents.NewWithdrawalDelay = append(wdelayerEvents.NewWithdrawalDelay, withdrawalDelay)
|
|
|
|
case logWDelayerEscapeHatchWithdrawal:
|
|
var escapeHatchWithdrawal WDelayerEventEscapeHatchWithdrawal
|
|
err := c.contractAbi.Unpack(&escapeHatchWithdrawal, "EscapeHatchWithdrawal", vLog.Data)
|
|
if err != nil {
|
|
return nil, nil, tracerr.Wrap(err)
|
|
}
|
|
escapeHatchWithdrawal.Who = ethCommon.BytesToAddress(vLog.Topics[1].Bytes())
|
|
escapeHatchWithdrawal.To = ethCommon.BytesToAddress(vLog.Topics[2].Bytes())
|
|
escapeHatchWithdrawal.Token = ethCommon.BytesToAddress(vLog.Topics[3].Bytes())
|
|
wdelayerEvents.EscapeHatchWithdrawal = append(wdelayerEvents.EscapeHatchWithdrawal, escapeHatchWithdrawal)
|
|
|
|
case logWDelayerNewEmergencyCouncil:
|
|
var emergencyCouncil WDelayerEventNewEmergencyCouncil
|
|
err := c.contractAbi.Unpack(&emergencyCouncil, "NewEmergencyCouncil", vLog.Data)
|
|
if err != nil {
|
|
return nil, nil, tracerr.Wrap(err)
|
|
}
|
|
wdelayerEvents.NewEmergencyCouncil = append(wdelayerEvents.NewEmergencyCouncil, emergencyCouncil)
|
|
|
|
case logWDelayerNewHermezGovernanceAddress:
|
|
var governanceAddress WDelayerEventNewHermezGovernanceAddress
|
|
err := c.contractAbi.Unpack(&governanceAddress, "NewHermezGovernanceAddress", vLog.Data)
|
|
if err != nil {
|
|
return nil, nil, tracerr.Wrap(err)
|
|
}
|
|
wdelayerEvents.NewHermezGovernanceAddress = append(wdelayerEvents.NewHermezGovernanceAddress, governanceAddress)
|
|
}
|
|
}
|
|
return &wdelayerEvents, blockHash, nil
|
|
}
|