Skip to content

Commit

Permalink
Merge pull request #4745 from onflow/bastian/flex-poc
Browse files Browse the repository at this point in the history
  • Loading branch information
turbolent authored Sep 22, 2023
2 parents 2e429b4 + 2170337 commit 0d46322
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 54 deletions.
9 changes: 5 additions & 4 deletions fvm/flex/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package flex
import (
"github.com/ethereum/go-ethereum/common"
"github.com/onflow/atree"

env "github.com/onflow/flow-go/fvm/flex/environment"
"github.com/onflow/flow-go/fvm/flex/models"
"github.com/onflow/flow-go/fvm/flex/storage"
Expand All @@ -21,20 +22,20 @@ func (h *FOAHandler) Address() *models.FlexAddress {

// Deposit deposits the token from the given vault into the Flex main vault
// and update the FOA balance with the new amount
func (h *FOAHandler) Deposit(models.FlowTokenVault) {
func (h *FOAHandler) Deposit(models.FLOWTokenVault) {
panic("not implemented")
}

// Withdraw deducts the balance from the FOA account and
// withdraw and return flow token from the Flex main vault.
func (h *FOAHandler) Withdraw(models.Balance) models.FlowTokenVault {
func (h *FOAHandler) Withdraw(models.Balance) models.FLOWTokenVault {
panic("not implemented")
}

// Deploy deploys a contract to the Flex environment
// the new deployed contract would be at the returned address and
// the contract data is not controlled by the FOA accounts
func (h *FOAHandler) Deploy(code models.Code, gaslimit models.Gaslimit, balance models.Balance) models.FlexAddress {
func (h *FOAHandler) Deploy(code models.Code, gaslimit models.GasLimit, balance models.Balance) models.FlexAddress {
config := env.NewFlexConfig(
env.WithBlockNumber(env.BlockNumberForEVMRules))
env, err := env.NewEnvironment(config, h.fch.db)
Expand All @@ -56,7 +57,7 @@ func (h *FOAHandler) Deploy(code models.Code, gaslimit models.Gaslimit, balance
// given it doesn't goes beyond what Flow transaction allows.
// the balance would be deducted from the OFA account and would be transferred to the target address
// contract data is not controlled by the FOA accounts
func (h *FOAHandler) Call(to models.FlexAddress, data models.Data, gaslimit models.Gaslimit, balance models.Balance) models.Data {
func (h *FOAHandler) Call(to models.FlexAddress, data models.Data, gaslimit models.GasLimit, balance models.Balance) models.Data {
config := env.NewFlexConfig(
env.WithBlockNumber(env.BlockNumberForEVMRules))
env, err := env.NewEnvironment(config, h.fch.db)
Expand Down
114 changes: 64 additions & 50 deletions fvm/flex/models/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,57 @@ package models
import (
"math/big"

"github.com/ethereum/go-ethereum/common"
gethCommon "github.com/ethereum/go-ethereum/common"
"github.com/onflow/cadence"
)

// Flex is an account inside FVM with special access to the underlying infrasturcture which
// allows to run a virtual evm-based blockchain on top of FVM. There are two ways to interact with this
// blockchain (flex env), first by passing signed transactions (EOA accounts) through Flex.Run method and each transaction
// would be considered as a block, updating the internal merkle tree of the Flex env and emitting a new root hash.
// The second way is through a new form of accounts called (FOA) which acts as a resource that any account on Flow environment
// could own and it has a collision-proof allocated flex address and any one who owns the resource, would be able to
// interact with the Flex environment on behalf of the flex address.

// The Flex enviornment shares the same native token as Flow, there is no new tokens minted and tokens could be bridged between
// FOA resources and Flow accounts. Then it could be circulated to any address space in the Flex (EOA, smart contracts), etc.

// Flex addresses are evm-compatible addresses
type FlexAddress common.Address

func (fa FlexAddress) ToCommon() common.Address {
return common.Address(fa)
// Flex is an account inside FVM with special access to the underlying infrastructure
// which allows to run a virtual EVM-based blockchain inside FVM.
//
// There are two ways to interact with this environment:
//
// First, passing a signed transaction (EOA account) to the `Flex.run` Cadence function
// creates a new block, updates the internal merkle tree, and emits a new root hash.
//
// The Second way is through a new form of account called Flow-owned account (FOA),
// which is represented and controlled through a resource, owned by a Flow account.
// The FOA has a collision-proof allocated address.
/// The owner of the FOA resource can interact with the Flex environment on behalf of the Flex address.
//
// The Flex environment shares the same native token as Flow, there are no new tokens minted.
// Other ERC-20 fungible tokens can be bridged between FOA resources and Flow accounts.

// FlexAddress is an EVM-compatible address
type FlexAddress gethCommon.Address

func (fa FlexAddress) ToCommon() gethCommon.Address {
return gethCommon.Address(fa)
}

func NewFlexAddressFromString(str string) FlexAddress {
return FlexAddress(common.BytesToAddress([]byte(str)))
return FlexAddress(gethCommon.BytesToAddress([]byte(str)))
}

// FlexBlock captures block info such as height and state
// FlexBlock represents an EVM block.
// It captures block info such as height and state
type FlexBlock interface {
// returns the height of this block (autoincrement number)
// Height returns the height of this EVM block (auto-incremented number)
Height() uint64
// returns the root hash of the state after executing this block
StateRoot() common.Hash
// returns the root hash of the events emited during execution of this block
EventRoot() common.Hash
// StateRoot returns the EVM root hash of the state after executing this EVM block
StateRoot() gethCommon.Hash
// EventRoot returns the EVM root hash of the events emitted during execution of this EVM block
EventRoot() gethCommon.Hash
}

// Balance of a flex account
// Balance represents the balance of a Flex account
// a separate type has been considered here to prevent
// accidental dev mistakes when dealing with the conversion
type Balance interface {
InAttoFlow() *big.Int
InFlow() cadence.UFix64
}

type Gaslimit uint64
type GasLimit uint64

type Code []byte

Expand All @@ -59,51 +65,59 @@ type FlexAccount interface {
Balance() Balance
}

type FlowTokenVault interface {
// FLOWTokenVault represents a FLOW Vault
type FLOWTokenVault interface {
Balance() Balance
Withdraw(Balance) FlowTokenVault
Deposit(FlowTokenVault)
Withdraw(Balance) FLOWTokenVault
Deposit(FLOWTokenVault)
}

// FlowOwnedAccount is a new type of accounts on the Flex environment
// that instead of being managed by public key inside the Flex, it would be managed
// as a resource inside the FVM accounts. in other words, the FVM account who holds
// a owns the FOA resource, could bridge native token from and to flex account associated with the FOA
// and deploys contracts or calls method on contracts without the need to sign a transaction.
// FlowOwnedAccount is a new type of account in the Flex environment,
// that instead of being managed by public key inside the Flex,
// 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 Flex account associated with the FOA,
// deploy contracts to the Flex environment,
// or call methods on contracts without the need to sign a transaction.
type FlowOwnedAccount interface {
// Address returns the flex address associated with the FOA account
Address() *FlexAddress

// Deposit deposits the token from the given vault into the Flex main vault
// and update the FOA balance with the new amount
Deposit(FlowTokenVault)
// TODO: move to FlexAccount
Deposit(FLOWTokenVault)

// Withdraw deducts the balance from the FOA account and
// withdraw and return flow token from the Flex main vault.
Withdraw(Balance) FlowTokenVault
Withdraw(Balance) FLOWTokenVault

// Deploy deploys a contract to the Flex environment
// the new deployed contract would be at the returned address and
// the contract data is not controlled by the FOA accounts
Deploy(Code, Gaslimit, Balance) FlexAddress

// Call calls a smart contract function with the given data
// it would limit the gas used according to the limit provided
// given it doesn't goes beyond what Flow transaction allows.
// the balance would be deducted from the OFA account and would be transferred to the target address
// contract data is not controlled by the FOA accounts
Call(FlexAddress, Data, Gaslimit, Balance) Data
Deploy(Code, GasLimit, Balance) FlexAddress

// 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 FOA
// and are transferred to the target address.
// TODO: clarify
// Contract data is not controlled by the FOA account
Call(FlexAddress, Data, GasLimit, Balance) Data
}

// Flex contract handles operations on the flex environment
// FlexContractHandler handles operations on the Flex environment
type FlexContractHandler interface {
// constructs a new flow owned account
// NewFlowOwnedAccount constructs a new FOA
NewFlowOwnedAccount() FlowOwnedAccount

// returns the last executed block info
// LastExecutedBlock returns information about the last executed block
LastExecutedBlock() FlexBlock

// runs a transaction in the Flex environment and collect
// the flex gas fees under coinbase account, if tx is success full it returns true
Run(bytes []byte, coinbase FlexAddress) bool
// Run runs a transaction in the Flex environment,
// collects the gas fees, and transfers the gas fees to the given coinbase account.
// Returns true if the transaction was successfully executed
Run(tx []byte, coinbase FlexAddress) bool
}

0 comments on commit 0d46322

Please sign in to comment.