Skip to content

Commit

Permalink
eibc basic order fulfillment test
Browse files Browse the repository at this point in the history
  • Loading branch information
pgoos committed Feb 29, 2024
1 parent b604835 commit 7177aed
Show file tree
Hide file tree
Showing 4 changed files with 308 additions and 5 deletions.
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@ e2e-test-ibc-success:
e2e-test-ibc-timeout:
cd tests && go test -timeout=25m -race -v -run TestIBCTransferTimeout .

# Executes IBC tests via rollup-e2e-testing
e2e-test-eibc-fulfillment:
cd tests && go test -timeout=25m -race -v -run TestEIBCFulfillment .

# Executes IBC tests via rollup-e2e-testing
e2e-test-ibc-grace-period:
cd tests && go test -timeout=25m -race -v -run TestIBCGracePeriodCompliance .

# Executes all tests via rollup-e2e-testing
e2e-test-all: e2e-test-ibc-success e2e-test-ibc-timeout e2e-test-ibc-grace-period
e2e-test-all: e2e-test-ibc-success e2e-test-ibc-timeout e2e-test-ibc-grace-period e2e-test-eibc-fulfillment

.PHONY: e2e-test-ibc-success e2e-test-ibc-timeout e2e-test-ibc-grace-period e2e-test-all
.PHONY: e2e-test-ibc-success e2e-test-ibc-timeout e2e-test-ibc-grace-period e2e-test-eibc-fulfillment e2e-test-all

2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ require (
cosmossdk.io/math v1.0.0-rc.0
github.com/cosmos/cosmos-sdk v0.46.16-0.20231025193730-41d2a21c1348
github.com/cosmos/ibc-go/v6 v6.2.1
github.com/decentrio/rollup-e2e-testing v0.0.0-20240226065125-246da844cabf
github.com/decentrio/rollup-e2e-testing v0.0.0-20240226185345-987643a0a7d2
github.com/evmos/ethermint v0.0.0-00010101000000-000000000000
github.com/stretchr/testify v1.8.4
go.uber.org/zap v1.24.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,8 @@ github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnG
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decentrio/rollup-e2e-testing v0.0.0-20240226065125-246da844cabf h1:yx8AVPUPphUcQxwxD2OVvJCitiRXr0SxnhNV0BXvoWY=
github.com/decentrio/rollup-e2e-testing v0.0.0-20240226065125-246da844cabf/go.mod h1:Hy/8P41OEKrlAatPG5NcD/BOWTa2s+laECwpZpmA9f0=
github.com/decentrio/rollup-e2e-testing v0.0.0-20240226185345-987643a0a7d2 h1:WOQhNzQmUunlwO20MLpWv6cMATfu1B2XOEXaS1ub34Q=
github.com/decentrio/rollup-e2e-testing v0.0.0-20240226185345-987643a0a7d2/go.mod h1:Hy/8P41OEKrlAatPG5NcD/BOWTa2s+laECwpZpmA9f0=
github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=
github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
Expand Down
298 changes: 298 additions & 0 deletions tests/eibc_fulfillment_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,298 @@
package tests

import (
"context"
"fmt"
"testing"

"cosmossdk.io/math"
transfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types"
test "github.com/decentrio/rollup-e2e-testing"
"github.com/decentrio/rollup-e2e-testing/blockdb"
"github.com/decentrio/rollup-e2e-testing/cosmos"
"github.com/decentrio/rollup-e2e-testing/cosmos/hub/dym_hub"
"github.com/decentrio/rollup-e2e-testing/cosmos/rollapp/dym_rollapp"
"github.com/decentrio/rollup-e2e-testing/ibc"

dymensiontesting "github.com/decentrio/rollup-e2e-testing/dymension"
"github.com/decentrio/rollup-e2e-testing/relayer"
"github.com/decentrio/rollup-e2e-testing/testreporter"
"github.com/decentrio/rollup-e2e-testing/testutil"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
)

// This test case verifies the system's behavior when an eIBC packet sent from the rollapp to the hub
// that is fulfilled by the market maker
func TestEIBCFulfillment(t *testing.T) {
if testing.Short() {
t.Skip()
}

ctx := context.Background()

configFileOverrides := make(map[string]any)
dymintTomlOverrides := make(testutil.Toml)
dymintTomlOverrides["settlement_layer"] = "dymension"
dymintTomlOverrides["node_address"] = "http://dymension_100-1-val-0-TestEIBCFulfillment:26657"
dymintTomlOverrides["rollapp_id"] = "demo-dymension-rollapp"

configFileOverrides["config/dymint.toml"] = dymintTomlOverrides
const BLOCK_FINALITY_PERIOD = 50
modifyGenesisKV := []cosmos.GenesisKV{
{
Key: "app_state.rollapp.params.dispute_period_in_blocks",
Value: fmt.Sprint(BLOCK_FINALITY_PERIOD),
},
}

// Create chain factory with dymension
numHubVals := 1
numHubFullNodes := 1
numRollAppFn := 0
numRollAppVals := 1
cf := test.NewBuiltinChainFactory(zaptest.NewLogger(t), []*test.ChainSpec{
{
Name: "rollapp1",
ChainConfig: ibc.ChainConfig{
Type: "rollapp-dym",
Name: "rollapp-temp",
ChainID: "demo-dymension-rollapp",
Images: []ibc.DockerImage{rollappImage},
Bin: "rollappd",
Bech32Prefix: "rol",
Denom: "urax",
CoinType: "118",
GasPrices: "0.0urax",
GasAdjustment: 1.1,
TrustingPeriod: "112h",
NoHostMount: false,
ModifyGenesis: nil,
ConfigFileOverrides: configFileOverrides,
},
NumValidators: &numRollAppVals,
NumFullNodes: &numRollAppFn,
},
{
Name: "dymension-hub",
ChainConfig: ibc.ChainConfig{
Type: "hub-dym",
Name: "dymension",
ChainID: "dymension_100-1",
Images: []ibc.DockerImage{dymensionImage},
Bin: "dymd",
Bech32Prefix: "dym",
Denom: "udym",
CoinType: "118",
GasPrices: "0.0udym",
EncodingConfig: evmConfig(),
GasAdjustment: 1.1,
TrustingPeriod: "112h",
NoHostMount: false,
ModifyGenesis: cosmos.ModifyGenesis(modifyGenesisKV),
ConfigFileOverrides: nil,
},
NumValidators: &numHubVals,
NumFullNodes: &numHubFullNodes,
},
})

// Get chains from the chain factory
chains, err := cf.Chains(t.Name())
require.NoError(t, err)

rollapp1 := chains[0].(*dym_rollapp.DymRollApp)
dymension := chains[1].(*dym_hub.DymHub)

// Relayer Factory
client, network := test.DockerSetup(t)
r := test.NewBuiltinRelayerFactory(ibc.CosmosRly, zaptest.NewLogger(t),
relayer.CustomDockerImage("ghcr.io/cosmos/relayer", "reece-v2.3.1-ethermint", "100:1000"),
).Build(t, client, network)
const ibcPath = "ibc-path"
ic := test.NewSetup().
AddRollUp(dymension, rollapp1).
AddRelayer(r, "relayer").
AddLink(test.InterchainLink{
Chain1: dymension,
Chain2: rollapp1,
Relayer: r,
Path: ibcPath,
})

rep := testreporter.NewNopReporter()
eRep := rep.RelayerExecReporter(t)

err = ic.Build(ctx, eRep, test.InterchainBuildOptions{
TestName: t.Name(),
Client: client,
NetworkID: network,
SkipPathCreation: false,

// This can be used to write to the block database which will index all block data e.g. txs, msgs, events, etc.
// BlockDatabaseFile: test.DefaultBlockDatabaseFilepath(),
})
require.NoError(t, err)

walletAmount := math.NewInt(1_000_000_000_000)

// Create some user accounts on both chains
users := test.GetAndFundTestUsers(t, ctx, t.Name(), walletAmount, dymension, dymension, rollapp1)

// Wait a few blocks for relayer to start and for user accounts to be created
err = testutil.WaitForBlocks(ctx, 5, dymension, rollapp1)
require.NoError(t, err)

// Get our Bech32 encoded user addresses
dymensionUser, marketMaker, rollappUser := users[0], users[1], users[2]

dymensionUserAddr := dymensionUser.FormattedAddress()
marketMakerAddr := marketMaker.FormattedAddress()
rollappUserAddr := rollappUser.FormattedAddress()

// Assert the accounts were funded
testutil.AssertBalance(t, ctx, dymension, dymensionUserAddr, dymension.Config().Denom, walletAmount)
testutil.AssertBalance(t, ctx, dymension, marketMakerAddr, dymension.Config().Denom, walletAmount)
testutil.AssertBalance(t, ctx, rollapp1, rollappUserAddr, rollapp1.Config().Denom, walletAmount)

// Compose an IBC transfer and send from dymension -> rollapp
transferAmount := math.NewInt(1_000_000)
multiplier := math.NewInt(10)

eibcFee := transferAmount.Quo(multiplier) // transferAmount * 0.1
transferAmountWithoutFee := transferAmount.Sub(eibcFee)

channel, err := ibc.GetTransferChannel(ctx, r, eRep, dymension.Config().ChainID, rollapp1.Config().ChainID)
require.NoError(t, err)

transferData := ibc.WalletData{
Address: dymensionUserAddr,
Denom: rollapp1.Config().Denom,
Amount: transferAmount,
}

err = r.StartRelayer(ctx, eRep, ibcPath)
require.NoError(t, err)

var options ibc.TransferOptions
// set eIBC specific memo
options.Memo = BuildEIbcMemo(eibcFee)

_, err = rollapp1.SendIBCTransfer(ctx, channel.ChannelID, rollappUserAddr, transferData, options)
require.NoError(t, err)

// get eIbc event
eibcEvents, err := getEIbcEventsWithinBlockRange(ctx, dymension, 20)
require.NoError(t, err)
fmt.Println("Event:", eibcEvents[0])

// fulfill demand order
txhash, err := dymension.FullfillDemandOrder(ctx, dymension.CosmosChain.FullNodes[0], eibcEvents[0].ID, marketMakerAddr)
require.NoError(t, err)
fmt.Println(txhash)

eibcEvents, err = getEIbcEventsWithinBlockRange(ctx, dymension, 20)
require.NoError(t, err)
fmt.Println("After order fulfillment:", eibcEvents[0])

// wait a few blocks and verify sender received funds on the hub
err = testutil.WaitForBlocks(ctx, 5, dymension)
require.NoError(t, err)
// Get the IBC denom for urax on Hub
rollappTokenDenom := transfertypes.GetPrefixedDenom(channel.Counterparty.PortID, channel.Counterparty.ChannelID, rollapp1.Config().Denom)
rollappIBCDenom := transfertypes.ParseDenomTrace(rollappTokenDenom).IBCDenom()

// verify funds minus fee were added to receiver's address
testutil.AssertBalance(t, ctx, dymension, dymensionUserAddr, rollappIBCDenom, transferAmountWithoutFee)
// verify funds were deducted from market maker's wallet address
testutil.AssertBalance(t, ctx, dymension, marketMakerAddr, rollappIBCDenom, walletAmount.Sub(transferAmountWithoutFee))
// wait until packet finalization and verify funds + fee were added to market maker's wallet address
err = testutil.WaitForBlocks(ctx, BLOCK_FINALITY_PERIOD, dymension)
require.NoError(t, err)
testutil.AssertBalance(t, ctx, dymension, marketMakerAddr, rollappIBCDenom, walletAmount.Sub(transferAmountWithoutFee).Add(transferData.Amount))

fmt.Println("Now waiting 500 blocks...")
err = testutil.WaitForBlocks(ctx, 500, rollapp1)
require.NoError(t, err)

t.Cleanup(
func() {
err := r.StopRelayer(ctx, eRep)
if err != nil {
t.Logf("an error occurred while stopping the relayer: %s", err)
}
},
)
}

func getEIbcEventsWithinBlockRange(
ctx context.Context,
dymension *dym_hub.DymHub,
blockRange uint64,
) ([]dymensiontesting.EibcEvent, error) {
var eibcEventsArray []dymensiontesting.EibcEvent

height, err := dymension.Height(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get Dymension height: %w", err)
}
fmt.Printf("Dymension height: %d\n", height)

err = testutil.WaitForBlocks(ctx, int(blockRange), dymension)
if err != nil {
return nil, fmt.Errorf("error waiting for blocks: %w", err)
}

eibcEvents, err := getEventsOfType(dymension.CosmosChain, height, height+blockRange, "eibc", true)
if err != nil {
return nil, fmt.Errorf("error getting events of type 'eibc': %w", err)
}

if len(eibcEvents) == 0 {
return nil, fmt.Errorf("There wasn't a single 'eibc' event registered within the specified block range on the hub")
}

for _, event := range eibcEvents {
eibcEvent, err := dymensiontesting.MapToEibcEvent(event)
if err != nil {
return nil, fmt.Errorf("error mapping to EibcEvent: %w", err)
}
eibcEventsArray = append(eibcEventsArray, eibcEvent)
}

return eibcEventsArray, nil
}

func getEventsOfType(chain *cosmos.CosmosChain, startHeight uint64, endHeight uint64, eventType string, breakOnFirstOccurence bool) ([]blockdb.Event, error) {
var eventTypeArray []blockdb.Event
shouldReturn := false

for height := startHeight; height <= endHeight && !shouldReturn; height++ {
txs, err := chain.FindTxs(context.Background(), height)
if err != nil {
return nil, fmt.Errorf("error fetching transactions at height %d: %w", height, err)
}

for _, tx := range txs {
for _, event := range tx.Events {
if event.Type == eventType {
eventTypeArray = append(eventTypeArray, event)
if breakOnFirstOccurence {
shouldReturn = true
fmt.Println("eibc found!")
break
}
}
}
if shouldReturn {
break
}
}
}

return eventTypeArray, nil
}

func BuildEIbcMemo(eibcFee math.Int) string {
return fmt.Sprintf(`{"eibc": {"fee": "%s"}}`, eibcFee.String())
}

0 comments on commit 7177aed

Please sign in to comment.