package types import ( "math/big" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/tharsis/ethermint/types" ) func newAccessListTx(tx *ethtypes.Transaction) *AccessListTx { txData := &AccessListTx{ Nonce: tx.Nonce(), Data: tx.Data(), GasLimit: tx.Gas(), } v, r, s := tx.RawSignatureValues() if tx.To() != nil { txData.To = tx.To().Hex() } if tx.Value() != nil { amountInt := sdk.NewIntFromBigInt(tx.Value()) txData.Amount = &amountInt } if tx.GasPrice() != nil { gasPriceInt := sdk.NewIntFromBigInt(tx.GasPrice()) txData.GasPrice = &gasPriceInt } if tx.AccessList() != nil { al := tx.AccessList() txData.Accesses = NewAccessList(&al) } txData.SetSignatureValues(tx.ChainId(), v, r, s) return txData } // TxType returns the tx type func (tx *AccessListTx) TxType() uint8 { return ethtypes.AccessListTxType } // Copy returns an instance with the same field values func (tx *AccessListTx) Copy() TxData { return &AccessListTx{ ChainID: tx.ChainID, Nonce: tx.Nonce, GasPrice: tx.GasPrice, GasLimit: tx.GasLimit, To: tx.To, Amount: tx.Amount, Data: common.CopyBytes(tx.Data), Accesses: tx.Accesses, V: common.CopyBytes(tx.V), R: common.CopyBytes(tx.R), S: common.CopyBytes(tx.S), } } // GetChainID returns the chain id field from the AccessListTx func (tx *AccessListTx) GetChainID() *big.Int { if tx.ChainID == nil { return nil } return tx.ChainID.BigInt() } // GetAccessList returns the AccessList field. func (tx *AccessListTx) GetAccessList() ethtypes.AccessList { if tx.Accesses == nil { return nil } return *tx.Accesses.ToEthAccessList() } // GetData returns the a copy of the input data bytes. func (tx *AccessListTx) GetData() []byte { return common.CopyBytes(tx.Data) } // GetGas returns the gas limit. func (tx *AccessListTx) GetGas() uint64 { return tx.GasLimit } // GetGasPrice returns the gas price field. func (tx *AccessListTx) GetGasPrice() *big.Int { if tx.GasPrice == nil { return nil } return tx.GasPrice.BigInt() } // GetGasTipCap returns the gas price field. func (tx *AccessListTx) GetGasTipCap() *big.Int { return tx.GetGasPrice() } // GetGasFeeCap returns the gas price field. func (tx *AccessListTx) GetGasFeeCap() *big.Int { return tx.GetGasPrice() } // GetValue returns the tx amount. func (tx *AccessListTx) GetValue() *big.Int { if tx.Amount == nil { return nil } return tx.Amount.BigInt() } // GetNonce returns the account sequence for the transaction. func (tx *AccessListTx) GetNonce() uint64 { return tx.Nonce } // GetTo returns the pointer to the recipient address. func (tx *AccessListTx) GetTo() *common.Address { if tx.To == "" { return nil } to := common.HexToAddress(tx.To) return &to } // AsEthereumData returns an AccessListTx transaction tx from the proto-formatted // TxData defined on the Cosmos EVM. func (tx *AccessListTx) AsEthereumData() ethtypes.TxData { v, r, s := tx.GetRawSignatureValues() return ðtypes.AccessListTx{ ChainID: tx.GetChainID(), Nonce: tx.GetNonce(), GasPrice: tx.GetGasPrice(), Gas: tx.GetGas(), To: tx.GetTo(), Value: tx.GetValue(), Data: tx.GetData(), AccessList: tx.GetAccessList(), V: v, R: r, S: s, } } // GetRawSignatureValues returns the V, R, S signature values of the transaction. // The return values should not be modified by the caller. func (tx *AccessListTx) GetRawSignatureValues() (v, r, s *big.Int) { return rawSignatureValues(tx.V, tx.R, tx.S) } // SetSignatureValues sets the signature values to the transaction. func (tx *AccessListTx) SetSignatureValues(chainID, v, r, s *big.Int) { if v != nil { tx.V = v.Bytes() } if r != nil { tx.R = r.Bytes() } if s != nil { tx.S = s.Bytes() } if chainID != nil { chainIDInt := sdk.NewIntFromBigInt(chainID) tx.ChainID = &chainIDInt } } // Validate performs a stateless validation of the tx fields. func (tx AccessListTx) Validate() error { gasPrice := tx.GetGasPrice() if gasPrice == nil { return sdkerrors.Wrap(ErrInvalidGasPrice, "cannot be nil") } if gasPrice.Sign() == -1 { return sdkerrors.Wrapf(ErrInvalidGasPrice, "gas price cannot be negative %s", gasPrice) } amount := tx.GetValue() // Amount can be 0 if amount != nil && amount.Sign() == -1 { return sdkerrors.Wrapf(ErrInvalidAmount, "amount cannot be negative %s", amount) } if tx.To != "" { if err := types.ValidateAddress(tx.To); err != nil { return sdkerrors.Wrap(err, "invalid to address") } } if tx.GetChainID() == nil { return sdkerrors.Wrap( sdkerrors.ErrInvalidChainID, "chain ID must be present on AccessList txs", ) } return nil } // Fee returns gasprice * gaslimit. func (tx AccessListTx) Fee() *big.Int { return fee(tx.GetGasPrice(), tx.GetGas()) } // Cost returns amount + gasprice * gaslimit. func (tx AccessListTx) Cost() *big.Int { return cost(tx.Fee(), tx.GetValue()) }