Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Flow EVM] Adding FLOW token bridge event #5538

Merged
merged 9 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions fvm/evm/stdlib/contract.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ contract EVM {
access(all)
event CadenceOwnedAccountCreated(addressBytes: [UInt8; 20])

/// FLOWTokenDeposit is emitted when FLOW tokens is bridged
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we are using past tense for events. FLOWTokensDeposited.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update those to use past participle.

/// into the EVM environment. Note that this event is not emitted
/// for transfer of flow tokens between two EVM addresses.
access(all)
event FLOWTokenDeposit(addressBytes: [UInt8; 20], amount: UFix64)

/// FLOWTokenWithdraw is emitted when FLOW tokens are bridged
/// out of the EVM environment. Note that this event is not emitted
/// for transfer of flow tokens between two EVM addresses.
access(all)
event FLOWTokenWithdraw(addressBytes: [UInt8; 20], amount: UFix64)

/// EVMAddress is an EVM-compatible address
access(all)
struct EVMAddress {
Expand Down Expand Up @@ -56,10 +68,12 @@ contract EVM {
/// Deposits the given vault into the EVM account with the given address
access(all)
fun deposit(from: @FlowToken.Vault) {
let amount = from.balance
InternalEVM.deposit(
from: <-from,
to: self.bytes
)
emit FLOWTokenDeposit(addressBytes: self.bytes, amount: amount)
}
}

Expand Down Expand Up @@ -224,6 +238,7 @@ contract EVM {
from: self.addressBytes,
amount: balance.attoflow
) as! @FlowToken.Vault
emit FLOWTokenWithdraw(addressBytes: self.addressBytes, amount: balance.inFLOW())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not emit an event if the balance is 0. I think I would prefer the whole function just exiting early if the balance is 0.

same with deposit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added protection

return <-vault
}

Expand Down
65 changes: 61 additions & 4 deletions fvm/evm/stdlib/contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2987,8 +2987,10 @@ func TestEVMCreateCadenceOwnedAccount(t *testing.T) {
false,
)

// Run script
// reset events
events = make([]cadence.Event, 0)

// Run script
actual, err := rt.ExecuteScript(
runtime.Script{
Source: script,
Expand Down Expand Up @@ -3018,6 +3020,20 @@ func TestEVMCreateCadenceOwnedAccount(t *testing.T) {
))

require.Equal(t, expected, actual)

// check deposit event
expectedEventTypes := []string{
"EVM.CadenceOwnedAccountCreated",
"EVM.CadenceOwnedAccountCreated",
}
CheckCadenceEventTypes(t, events, expectedEventTypes)

// check cadence owned account created events
expectedCoaAddress := types.Address{3}
require.Equal(t, expectedCoaAddress.ToCadenceValue().ToGoValue(), events[0].Fields[0].ToGoValue())

expectedCoaAddress = types.Address{4}
require.Equal(t, expectedCoaAddress.ToCadenceValue().ToGoValue(), events[1].Fields[0].ToGoValue())
}

func TestCadenceOwnedAccountCall(t *testing.T) {
Expand Down Expand Up @@ -3270,10 +3286,12 @@ func TestCOADeposit(t *testing.T) {

var deposited bool

var expectedCoaAddress = types.Address{5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

handler := &testContractHandler{

accountByAddress: func(fromAddress types.Address, isAuthorized bool) types.Account {
assert.Equal(t, types.Address{5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fromAddress)
assert.Equal(t, expectedCoaAddress, fromAddress)
assert.False(t, isAuthorized)

return &testFlowAccount{
Expand Down Expand Up @@ -3358,6 +3376,9 @@ func TestCOADeposit(t *testing.T) {

// Run script

// reset events before script execution
events = make([]cadence.Event, 0)

_, err = rt.ExecuteScript(
runtime.Script{
Source: script,
Expand All @@ -3371,6 +3392,22 @@ func TestCOADeposit(t *testing.T) {
require.NoError(t, err)

require.True(t, deposited)

// check deposit event
expectedEventTypes := []string{
"FlowToken.MinterCreated",
"FlowToken.TokensMinted",
"EVM.CadenceOwnedAccountCreated",
"EVM.FLOWTokenDeposit",
}
CheckCadenceEventTypes(t, events, expectedEventTypes)

// token deposit event
tokenDepositEvent := events[3]
// check address
require.Equal(t, expectedCoaAddress.ToCadenceValue().ToGoValue(), tokenDepositEvent.Fields[0].ToGoValue())
// check amount
require.Equal(t, expectedBalance.ToGoValue(), tokenDepositEvent.Fields[1].ToGoValue())
}

func TestCadenceOwnedAccountWithdraw(t *testing.T) {
Expand All @@ -3390,10 +3427,12 @@ func TestCadenceOwnedAccountWithdraw(t *testing.T) {

var nextUUID uint64 = 1

var expectedCoaAddress = types.Address{5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

handler := &testContractHandler{
flowTokenAddress: common.Address(contractsAddress),
accountByAddress: func(fromAddress types.Address, isAuthorized bool) types.Account {
assert.Equal(t, types.Address{5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, fromAddress)
assert.Equal(t, expectedCoaAddress, fromAddress)
assert.Equal(t, deposited, isAuthorized)

return &testFlowAccount{
Expand Down Expand Up @@ -3498,8 +3537,9 @@ func TestCadenceOwnedAccountWithdraw(t *testing.T) {
false,
)

// reset events
events = make([]cadence.Event, 0)
// Run script

result, err := rt.ExecuteScript(
runtime.Script{
Source: script,
Expand All @@ -3517,6 +3557,23 @@ func TestCadenceOwnedAccountWithdraw(t *testing.T) {
assert.Equal(t, expectedWithdrawBalance, result)

assert.Equal(t, []string{"1"}, logs)

// check deposit event
expectedEventTypes := []string{
"FlowToken.MinterCreated",
"FlowToken.TokensMinted",
"EVM.CadenceOwnedAccountCreated",
"EVM.FLOWTokenDeposit",
"EVM.FLOWTokenWithdraw",
}
CheckCadenceEventTypes(t, events, expectedEventTypes)

// token deposit event
tokenWithdrawEvent := events[4]
// check address
require.Equal(t, expectedCoaAddress.ToCadenceValue().ToGoValue(), tokenWithdrawEvent.Fields[0].ToGoValue())
// check amount
require.Equal(t, expectedWithdrawBalance.ToGoValue(), tokenWithdrawEvent.Fields[1].ToGoValue())
}

func TestCadenceOwnedAccountDeploy(t *testing.T) {
Expand Down
9 changes: 9 additions & 0 deletions fvm/evm/testutils/cadence.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strconv"
"strings"
"sync/atomic"
"testing"
"time"

"github.com/onflow/atree"
Expand All @@ -20,6 +21,7 @@ import (
"github.com/onflow/cadence/runtime/interpreter"
"github.com/onflow/cadence/runtime/sema"
cadenceStdlib "github.com/onflow/cadence/runtime/stdlib"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/otel/attribute"
)

Expand Down Expand Up @@ -715,3 +717,10 @@ func (i *TestRuntimeInterface) InteractionUsed() (uint64, error) {

return i.OnInteractionUsed()
}

func CheckCadenceEventTypes(t testing.TB, events []cadence.Event, expectedTypes []string) {
require.Equal(t, len(events), len(expectedTypes))
for i, ev := range events {
require.Equal(t, expectedTypes[i], ev.EventType.QualifiedIdentifier)
}
}
2 changes: 1 addition & 1 deletion fvm/fvm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3325,7 +3325,7 @@ func TestEVM(t *testing.T) {

require.NoError(t, err)
require.NoError(t, output.Err)
require.Len(t, output.Events, 6)
require.Len(t, output.Events, 7)

evmLocation := types.EVMLocation{}
txExe, blockExe := output.Events[4], output.Events[5]
Expand Down
Loading