Documentation
¶
Index ¶
- Constants
- Variables
- func IsADatabaseError(err error) bool
- func IsAFatalError(err error) bool
- func IsAInsufficientTotalSupplyError(err error) bool
- func IsAUnAuthroizedMethodCallError(err error) bool
- func IsEVMExecutionError(err error) bool
- func IsEVMValidationError(err error) bool
- type Account
- type Address
- type AddressAllocator
- type Backend
- type Balance
- type Block
- type BlockContext
- type BlockExecutedEventPayload
- type BlockStore
- type BlockView
- type Code
- type ContractHandler
- type Data
- type Database
- type DatabaseError
- type DirectCall
- func NewContractCall(caller Address, to Address, data Data, gasLimit uint64, value *big.Int) *DirectCall
- func NewDeployCall(caller Address, code Code, gasLimit uint64, value *big.Int) *DirectCall
- func NewDepositCall(address Address, amount *big.Int) *DirectCall
- func NewTransferCall(from Address, to Address, amount *big.Int) *DirectCall
- func NewWithdrawCall(address Address, amount *big.Int) *DirectCall
- type EVMExecutionError
- type EVMValidationError
- type Emulator
- type Event
- type EventPayload
- type FLOWTokenVault
- type FatalError
- type GasLimit
- type ReadOnlyBlockView
- type Result
- type TransactionExecutedPayload
Constants ¶
const ( // tx type 255 is used for direct calls from bridged accounts DirectCallTxType = byte(255) UnknownCallSubType = byte(0) DepositCallSubType = byte(1) WithdrawCallSubType = byte(2) TransferCallSubType = byte(3) DeployCallSubType = byte(4) ContractCallSubType = byte(5) TransferGasUsage = 21_000 )
const ( EventTypeBlockExecuted flow.EventType = "evm.BlockExecuted" EventTypeTransactionExecuted flow.EventType = "evm.TransactionExecuted" )
const AddressLength = gethCommon.AddressLength
AddressLength holds the number of bytes used for each EVM address
Variables ¶
var ( SmallestAcceptableBalanceValueInAttoFlow = new(big.Int).SetInt64(1e10) OneFlowInAttoFlow = new(big.Int).SetInt64(1e18) )
var ( DefaultDirectCallBaseGasUsage = uint64(21_000) DefaultDirectCallGasPrice = uint64(0) // anything block number above 0 works here BlockNumberForEVMRules = big.NewInt(1) )
var ( // ErrAccountDoesNotExist is returned when evm account doesn't exist ErrAccountDoesNotExist = errors.New("account does not exist") // ErrInsufficientBalance is returned when evm account doesn't have enough balance ErrInsufficientBalance = errors.New("insufficient balance") // ErrInsufficientComputation is returned when not enough computation is // left in the context of flow transaction to execute the evm operation. ErrInsufficientComputation = errors.New("insufficient computation") // unauthorized method call, usually emited when calls are called on EOA accounts ErrUnAuthroizedMethodCall = errors.New("unauthroized method call") // ErrInsufficientTotalSupply is returned when flow token // is withdraw request is there but not enough balance is on EVM vault // this should never happen but its a saftey measure to protect Flow against EVM issues. // TODO: we might consider this fatal ErrInsufficientTotalSupply = errors.New("insufficient total supply") // ErrBalanceConversion is returned conversion of balance has failed, usually // is returned when the balance presented in attoflow has values that could // be marginally lost on the conversion. ErrBalanceConversion = errors.New("balance converion error") // ErrNotImplemented is a fatal error when something is called that is not implemented ErrNotImplemented = NewFatalError(errors.New("a functionality is called that is not implemented")) )
var EmptyAddress = Address(gethCommon.Address{})
EmptyAddress is an empty evm address
var GenesisBlock = &Block{ ParentBlockHash: gethCommon.Hash{}, Height: uint64(0), StateRoot: gethTypes.EmptyRootHash, ReceiptRoot: gethTypes.EmptyRootHash, }
GenesisBlock is the genesis block in the EVM environment
Functions ¶
func IsADatabaseError ¶
IsADatabaseError returns true if the error or any underlying errors is of the type EVM validation error
func IsAFatalError ¶
IsAFatalError returns true if the error or underlying error is of fatal type.
func IsAInsufficientTotalSupplyError ¶
IsAInsufficientTotalSupplyError returns true if the error type is InsufficientTotalSupplyError
func IsAUnAuthroizedMethodCallError ¶
IsAUnAuthroizedMethodCallError returns true if the error type is UnAuthroizedMethodCallError
func IsEVMExecutionError ¶
IsEVMValidationError returns true if the error or any underlying errors is of the type EVM execution error
func IsEVMValidationError ¶
IsEVMValidationError returns true if the error or any underlying errors is of the type EVM validation error
Types ¶
type Account ¶
type Account interface { // Returns the address of this account Address() Address // Returns balance of this account Balance() Balance // Deposit deposits the token from the given vault into this account Deposit(*FLOWTokenVault) // Withdraw withdraws the balance from account and // return it as a FlowTokenVault // works only for bridged accounts Withdraw(Balance) *FLOWTokenVault // Transfer is a utility method on top of call for transfering tokens to another account Transfer(to Address, balance Balance) // Deploy deploys a contract to the environment // the new deployed contract would be at the returned address and // the contract data is not controlled by the bridge account // works only for bridged accounts Deploy(Code, GasLimit, Balance) Address // Call calls a smart contract function with the given data. // The gas usage is limited by the given gas limit, // and the Flow transaction's computation limit. // The fees are deducted from the bridged account // and are transferred to the target address. // if no data is provided it would behave as transfering tokens to the // target address // works only for bridged accounts Call(Address, Data, GasLimit, Balance) Data }
Account is an EVM account, currently three types of accounts are supported on Flow EVM, externally owned accounts (EOAs), smart contract accounts and bridged accounts BridgedAccount is a new type of account in the environment, that instead of being managed by public key, it is managed by a resource owned by a Flow account.
In other words, the FVM account who owns the FOA resource can bridge native tokens to and from the account associated with the bridged account, deploy contracts to the environment, or call methods on contracts without the need to sign a transaction.
type Address ¶
type Address gethCommon.Address
Address is an EVM-compatible address
func NewAddress ¶
func NewAddress(addr gethCommon.Address) Address
NewAddress constructs a new Address
func NewAddressFromBytes ¶
NewAddressFromBytes constructs a new address from bytes
func NewAddressFromString ¶
NewAddressFromString constructs a new address from an string
func (Address) ToCommon ¶
func (fa Address) ToCommon() gethCommon.Address
ToCommon returns the geth address
type AddressAllocator ¶
type AddressAllocator interface { // AllocateAddress allocates an address to be used by a bridged account resource AllocateAddress() (Address, error) }
AddressAllocator allocates addresses, used by the handler
type Backend ¶
type Backend interface { environment.ValueStore environment.Meter environment.EventEmitter }
Backend passes the FVM functionality needed inside the handler
type Balance ¶
Balance represents the balance of an address in the evm environment, balances are kept in attoflow (1e10^-18 flow), the smallest denomination of FLOW token (similar to how Wei is used to store Eth) But on the FLOW Vaults, we use Cadence.UFix64 to store values in Flow. this could result in accidental conversion mistakes, the balance object here would do the conversions and does appropriate checks.
For example the smallest unit of Flow token that a FlowVault could store is 1e10^-8, so transfering smaller values (or values with smalls fractions) could result in loss in conversion. The balance object checks it to prevent invalid balance. This means that values smaller than 1e10^-8 flow could not be bridged between FVM and Flow EVM.
func DecodeBalance ¶
DecodeBalance decodes a balance from an encoded byte slice
func NewBalanceFromAttoFlow ¶
NewBalanceFromAttoFlow constructs a new balance from atto flow value
func (Balance) ToAttoFlow ¶
ToAttoFlow converts the balance into AttoFlow
type Block ¶
type Block struct { // the hash of the parent block ParentBlockHash gethCommon.Hash // Height returns the height of this block Height uint64 // holds the total amount of the native token deposited in the evm side. TotalSupply uint64 // StateRoot returns the EVM root hash of the state after executing this block StateRoot gethCommon.Hash // ReceiptRoot returns the root hash of the receipts emitted in this block ReceiptRoot gethCommon.Hash // transaction hashes TransactionHashes []gethCommon.Hash }
Block represents a evm block. It captures block info such as height and state
func NewBlock ¶
func NewBlock(height, uuidIndex, totalSupply uint64, stateRoot, receiptRoot gethCommon.Hash, txHashes []gethCommon.Hash, ) *Block
NewBlock constructs a new block
func NewBlockFromBytes ¶
NewBlockFromBytes constructs a new block from encoded data
func (*Block) AppendTxHash ¶
func (b *Block) AppendTxHash(txHash gethCommon.Hash)
AppendTxHash appends a transaction hash to the list of transaction hashes of the block
type BlockContext ¶
type BlockContext struct { BlockNumber uint64 DirectCallBaseGasUsage uint64 DirectCallGasPrice uint64 GasFeeCollector Address }
BlockContext holds the context needed for the emulator operations
func NewDefaultBlockContext ¶
func NewDefaultBlockContext(BlockNumber uint64) BlockContext
NewDefaultBlockContext returns a new default block context
type BlockExecutedEventPayload ¶
type BlockExecutedEventPayload struct {
Block *Block
}
func (*BlockExecutedEventPayload) CadenceEvent ¶
func (p *BlockExecutedEventPayload) CadenceEvent() (cadence.Event, error)
type BlockStore ¶
type BlockStore interface { // LatestBlock returns the latest appended block LatestBlock() (*Block, error) // BlockHash returns the hash of the block at the given height BlockHash(height int) (gethCommon.Hash, error) // BlockProposal returns the block proposal BlockProposal() (*Block, error) // CommitBlockProposal commits the block proposal and update the chain of blocks CommitBlockProposal() error // ResetBlockProposal resets the block proposal ResetBlockProposal() error }
BlockStore stores the chain of blocks
type BlockView ¶
type BlockView interface { // executes a direct call DirectCall(call *DirectCall) (*Result, error) // RunTransaction executes an evm transaction RunTransaction(tx *gethTypes.Transaction) (*Result, error) }
BlockView facilitates execution of a transaction or a direct evm call in the context of a block Errors returned by the methods are one of the followings: - Fatal error - Database error (non-fatal) - EVM validation error - EVM execution error
type ContractHandler ¶
type ContractHandler interface { // AllocateAddress allocates an address to be used by a bridged account resource AllocateAddress() Address // AccountByAddress returns an account by address // if isAuthorized is set, it allows for functionality like `call`, `deploy` // should only be set for bridged accounts only. AccountByAddress(address Address, isAuthorized bool) Account // LastExecutedBlock returns information about the last executed block LastExecutedBlock() *Block // Run runs a transaction in the evm environment, // collects the gas fees, and transfers the gas fees to the given coinbase account. Run(tx []byte, coinbase Address) FlowTokenAddress() common.Address }
ContractHandler handles operations on the evm environment
type Database ¶
type Database interface { ethdb.KeyValueStore // Commit commits the changes Commit(rootHash gethCommon.Hash) error // GetRootHash returns the active root hash GetRootHash() (gethCommon.Hash, error) }
Database provides what Emulator needs for storing tries and accounts Errors returned by the methods are one of the followings: - Fatal error - Database error (non-fatal)
type DatabaseError ¶
type DatabaseError struct {
// contains filtered or unexported fields
}
DatabaseError is a non-fatal error, returned when a database operation has failed (e.g. reaching storage interaction limit)
func NewDatabaseError ¶
func NewDatabaseError(rootCause error) DatabaseError
NewDatabaseError returns a new DatabaseError
func (DatabaseError) Error ¶
func (err DatabaseError) Error() string
func (DatabaseError) Unwrap ¶
func (err DatabaseError) Unwrap() error
Unwrap unwraps the underlying evm error
type DirectCall ¶
type DirectCall struct { Type byte SubType byte From Address To Address Data []byte Value *big.Int GasLimit uint64 }
DirectCall captures all the data related to a direct call to evm direct calls are similar to transactions but they don't have signatures and don't need sequence number checks
func NewContractCall ¶
func NewDeployCall ¶
func NewDepositCall ¶
func NewDepositCall(address Address, amount *big.Int) *DirectCall
func NewTransferCall ¶
func NewTransferCall(from Address, to Address, amount *big.Int) *DirectCall
func NewWithdrawCall ¶
func NewWithdrawCall(address Address, amount *big.Int) *DirectCall
func (*DirectCall) Encode ¶
func (dc *DirectCall) Encode() ([]byte, error)
Encode encodes the direct call it also adds the type as the very first byte, similar to how evm encodes types.
func (*DirectCall) Hash ¶
func (dc *DirectCall) Hash() (gethCommon.Hash, error)
Hash computes the hash of a direct call
func (*DirectCall) Message ¶
func (dc *DirectCall) Message() *gethCore.Message
Message constructs a core.Message from the direct call
type EVMExecutionError ¶
type EVMExecutionError struct {
// contains filtered or unexported fields
}
EVMExecutionError is a non-fatal error, returned when execution of an evm transaction or direct call has failed.
func NewEVMExecutionError ¶
func NewEVMExecutionError(rootCause error) EVMExecutionError
NewEVMExecutionError returns a new EVMExecutionError
func (EVMExecutionError) Error ¶
func (err EVMExecutionError) Error() string
func (EVMExecutionError) Unwrap ¶
func (err EVMExecutionError) Unwrap() error
Unwrap unwraps the underlying evm error
type EVMValidationError ¶
type EVMValidationError struct {
// contains filtered or unexported fields
}
EVMValidationError is a non-fatal error, returned when validation steps of an EVM transaction or direct call has failed.
func NewEVMValidationError ¶
func NewEVMValidationError(rootCause error) EVMValidationError
NewEVMValidationError returns a new EVMValidationError
func (EVMValidationError) Error ¶
func (err EVMValidationError) Error() string
func (EVMValidationError) Unwrap ¶
func (err EVMValidationError) Unwrap() error
Unwrap unwraps the underlying evm error
type Emulator ¶
type Emulator interface { // constructs a new block view NewReadOnlyBlockView(ctx BlockContext) (ReadOnlyBlockView, error) // constructs a new block NewBlockView(ctx BlockContext) (BlockView, error) }
Emulator emulates an evm-compatible chain
type Event ¶
type Event struct { Etype flow.EventType Payload EventPayload }
func NewBlockExecutedEvent ¶
type EventPayload ¶
type FLOWTokenVault ¶
type FLOWTokenVault struct {
// contains filtered or unexported fields
}
FLOWTokenVault holds a balance of flow token
func NewFlowTokenVault ¶
func NewFlowTokenVault(balance Balance) *FLOWTokenVault
func (*FLOWTokenVault) Balance ¶
func (t *FLOWTokenVault) Balance() Balance
func (*FLOWTokenVault) Deposit ¶
func (t *FLOWTokenVault) Deposit(inp *FLOWTokenVault)
func (*FLOWTokenVault) Withdraw ¶
func (t *FLOWTokenVault) Withdraw(b Balance) *FLOWTokenVault
type FatalError ¶
type FatalError struct {
// contains filtered or unexported fields
}
FatalError is user for any error that is not user related and something unusual has happend. Usually we stop the node when this happens given it might have a non-deterministic root.
func NewFatalError ¶
func NewFatalError(rootCause error) FatalError
NewFatalError returns a new FatalError
func (FatalError) Error ¶
func (err FatalError) Error() string
func (FatalError) Unwrap ¶
func (err FatalError) Unwrap() error
Unwrap unwraps the underlying fatal error
type ReadOnlyBlockView ¶
type ReadOnlyBlockView interface { // BalanceOf returns the balance of this address BalanceOf(address Address) (*big.Int, error) // NonceOf returns the nonce of this address NonceOf(address Address) (uint64, error) // CodeOf returns the code for this address (if smart contract is deployed at this address) CodeOf(address Address) (Code, error) }
ReadOnlyBlockView provides a read only view of a block
type Result ¶
type Result struct { // a boolean that is set to false if the execution has failed (non-fatal) Failed bool // type of transaction defined by the evm package // see DirectCallTxType as extra type we added type for direct calls. TxType uint8 // total gas consumed during an opeartion GasConsumed uint64 // the root hash of the state after execution StateRootHash gethCommon.Hash // the address where the contract is deployed (if any) DeployedContractAddress Address // returned value from a function call ReturnedValue []byte // EVM logs (events that are emited by evm) Logs []*gethTypes.Log }
Result captures the result of an interaction to the emulator it could be the out put of a direct call or output of running an evm transaction. Its more comprehensive than typical evm receipt, usually the receipt generation requires some extra calculation (e.g. Deployed contract address) but we take a different apporach here and include more data so that it requires less work for anyone who tracks and consume results.
func (*Result) Receipt ¶
func (res *Result) Receipt() *gethTypes.ReceiptForStorage
Receipt constructs an EVM-style receipt can be used by json-rpc and other integration to be returned.
type TransactionExecutedPayload ¶
type TransactionExecutedPayload struct { BlockHeight uint64 TxEncoded []byte TxHash gethCommon.Hash Result *Result }
we might break this event into two (tx included /tx executed) if size becomes an issue
func (*TransactionExecutedPayload) CadenceEvent ¶
func (p *TransactionExecutedPayload) CadenceEvent() (cadence.Event, error)