From 993f8ed20b302976a036d47c4573cd88e3f03cb9 Mon Sep 17 00:00:00 2001 From: Dzmitry Hil Date: Mon, 18 Mar 2024 13:37:59 +0300 Subject: [PATCH] Add RPC client clawback test (#193) --- .github/workflows/relayer-ci.yml | 2 +- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 +- integration-tests/xrpl/rpc_test.go | 131 +++++++++++++++++++++++++++++ relayer/go.mod | 2 +- relayer/go.sum | 4 +- 6 files changed, 138 insertions(+), 7 deletions(-) diff --git a/.github/workflows/relayer-ci.yml b/.github/workflows/relayer-ci.yml index f6821152..dec21caf 100644 --- a/.github/workflows/relayer-ci.yml +++ b/.github/workflows/relayer-ci.yml @@ -65,7 +65,7 @@ jobs: with: repository: CoreumFoundation/crust path: crust - ref: bfeaa9ae4eace8b2d66e718ad50a03acd59d182c + ref: 9e29fa9e7f52a0e8db70c1a1d43404de432bdac3 - name: Checkout coreum uses: actions/checkout@v4 with: diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 2ca19929..f3354cc8 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -13,7 +13,7 @@ replace ( // Fix upstream GHSA-h395-qcrw-5vmq vulnerability. // TODO remove it: https://github.com/cosmos/cosmos-sdk/issues/10409 github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.0 - github.com/rubblelabs/ripple => github.com/sologenic/ripple v0.0.0-20240212093037-7c70304af75a + github.com/rubblelabs/ripple => github.com/sologenic/ripple v0.0.0-20240311151913-cfb0e720be27 // https://github.com/cosmos/cosmos-sdk/issues/14949 // pin the version of goleveldb to v1.0.1-0.20210819022825-2ae1ddf74ef7 required by SDK v47 upgrade guide. github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index a96a90d1..0dc5f952 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -952,8 +952,8 @@ github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sologenic/ripple v0.0.0-20240212093037-7c70304af75a h1:rV+sOnHYOJMQK6H4rrMV5mF4c8aBizXRBAavFvY6uZQ= -github.com/sologenic/ripple v0.0.0-20240212093037-7c70304af75a/go.mod h1:fMkR1lFpPmqtrRLsnAT86pDLUlOBqcfot815LgiAqjQ= +github.com/sologenic/ripple v0.0.0-20240311151913-cfb0e720be27 h1:/OHFmZy8m386MVKMhGO/FNZiUo4s7mvCBbQLj2d6TL8= +github.com/sologenic/ripple v0.0.0-20240311151913-cfb0e720be27/go.mod h1:fMkR1lFpPmqtrRLsnAT86pDLUlOBqcfot815LgiAqjQ= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= diff --git a/integration-tests/xrpl/rpc_test.go b/integration-tests/xrpl/rpc_test.go index 00d6d43a..e5fdeeb7 100644 --- a/integration-tests/xrpl/rpc_test.go +++ b/integration-tests/xrpl/rpc_test.go @@ -17,6 +17,8 @@ import ( "github.com/CoreumFoundation/coreumbridge-xrpl/relayer/xrpl" ) +const asfAllowTrustLineClawbackFlag = uint32(16) + func TestXRPAndIssuedTokensPayment(t *testing.T) { t.Parallel() @@ -945,6 +947,135 @@ func TestXRPLHighLowAmountsPayments(t *testing.T) { } } +func TestXRPLClawback(t *testing.T) { + t.Parallel() + + ctx, chains := integrationtests.NewTestingContext(t) + + issuerClawbackAcc := chains.XRPL.GenAccount(ctx, t, 10) + t.Logf("Issuer clawback account: %s", issuerClawbackAcc) + + issuerNoClawbackAcc := chains.XRPL.GenAccount(ctx, t, 10) + t.Logf("Issuer no-clawback account: %s", issuerClawbackAcc) + + recipientAcc := chains.XRPL.GenAccount(ctx, t, 0) + t.Logf("Recipient account: %s", recipientAcc) + + // enable clawback + allowClawbackTx := rippledata.AccountSet{ + TxBase: rippledata.TxBase{ + Account: issuerClawbackAcc, + TransactionType: rippledata.ACCOUNT_SET, + }, + // https://xrpl.org/docs/references/protocol/transactions/types/accountset/#accountset-flags + SetFlag: lo.ToPtr(asfAllowTrustLineClawbackFlag), + } + require.NoError(t, chains.XRPL.AutoFillSignAndSubmitTx(ctx, t, &allowClawbackTx, issuerClawbackAcc)) + + const fooCurrencyCode = "FOO" + fooCurrency, err := rippledata.NewCurrency(fooCurrencyCode) + require.NoError(t, err) + fooCurrencyTrustSetValue, err := rippledata.NewValue("10000000000000000", false) + require.NoError(t, err) + fooClawbackCurrencyTrustSetTx := rippledata.TrustSet{ + LimitAmount: rippledata.Amount{ + Value: fooCurrencyTrustSetValue, + Currency: fooCurrency, + Issuer: issuerClawbackAcc, + }, + TxBase: rippledata.TxBase{ + TransactionType: rippledata.TRUST_SET, + }, + } + require.NoError(t, chains.XRPL.AutoFillSignAndSubmitTx(ctx, t, &fooClawbackCurrencyTrustSetTx, recipientAcc)) + + fooValue, err := rippledata.NewValue("100000", false) + require.NoError(t, err) + fooPaymentTx := rippledata.Payment{ + Destination: recipientAcc, + Amount: rippledata.Amount{ + Value: fooValue, + Currency: fooCurrency, + Issuer: issuerClawbackAcc, + }, + TxBase: rippledata.TxBase{ + TransactionType: rippledata.PAYMENT, + }, + } + + currencyIssuerClawbackKey := fmt.Sprintf( + "%s/%s", xrpl.ConvertCurrencyToString(fooCurrency), issuerClawbackAcc.String(), + ) + balancesBefore := chains.XRPL.GetAccountBalances(ctx, t, recipientAcc) + t.Logf("Recipient account balances before: %s", balancesBefore) + require.NoError(t, chains.XRPL.AutoFillSignAndSubmitTx(ctx, t, &fooPaymentTx, issuerClawbackAcc)) + balancesAfter := chains.XRPL.GetAccountBalances(ctx, t, recipientAcc) + t.Logf("Recipient account balances after: %s", balancesAfter) + require.Equal(t, fooValue.String(), balancesAfter[currencyIssuerClawbackKey].Value.String()) + + // clawback the amount + clawbackTx := rippledata.Clawback{ + Amount: rippledata.Amount{ + Value: fooValue, + Currency: fooCurrency, + // the issuer here is the holder + Issuer: recipientAcc, + }, + TxBase: rippledata.TxBase{ + Account: issuerClawbackAcc, + TransactionType: rippledata.CLAWBACK, + }, + } + + balancesBefore = chains.XRPL.GetAccountBalances(ctx, t, recipientAcc) + t.Logf("Recipient account balances before: %s", balancesBefore) + require.NoError(t, chains.XRPL.AutoFillSignAndSubmitTx(ctx, t, &clawbackTx, issuerClawbackAcc)) + balancesAfter = chains.XRPL.GetAccountBalances(ctx, t, recipientAcc) + t.Logf("Recipient account balances after: %s", balancesAfter) + require.True(t, balancesAfter[currencyIssuerClawbackKey].Value.IsZero()) + + // try to do the clawback after the issuance + fooNoClawbackCurrencyTrustSetTx := rippledata.TrustSet{ + LimitAmount: rippledata.Amount{ + Value: fooCurrencyTrustSetValue, + Currency: fooCurrency, + Issuer: issuerNoClawbackAcc, + }, + TxBase: rippledata.TxBase{ + TransactionType: rippledata.TRUST_SET, + }, + } + require.NoError(t, chains.XRPL.AutoFillSignAndSubmitTx(ctx, t, &fooNoClawbackCurrencyTrustSetTx, recipientAcc)) + + fooPaymentTx = rippledata.Payment{ + Destination: recipientAcc, + Amount: rippledata.Amount{ + Value: fooValue, + Currency: fooCurrency, + Issuer: issuerNoClawbackAcc, + }, + TxBase: rippledata.TxBase{ + TransactionType: rippledata.PAYMENT, + }, + } + require.NoError(t, chains.XRPL.AutoFillSignAndSubmitTx(ctx, t, &fooPaymentTx, issuerNoClawbackAcc)) + + // try to enable the clawback now + allowClawbackTx = rippledata.AccountSet{ + TxBase: rippledata.TxBase{ + Account: issuerNoClawbackAcc, + TransactionType: rippledata.ACCOUNT_SET, + }, + // https://xrpl.org/docs/references/protocol/transactions/types/accountset/#accountset-flags + SetFlag: lo.ToPtr(asfAllowTrustLineClawbackFlag), + } + require.ErrorContains( + t, + chains.XRPL.AutoFillSignAndSubmitTx(ctx, t, &allowClawbackTx, issuerNoClawbackAcc), + rippledata.TecOWNERS.Human(), + ) +} + func getBalanceAccount( ctx context.Context, t *testing.T, diff --git a/relayer/go.mod b/relayer/go.mod index b3c3cd47..287d251c 100644 --- a/relayer/go.mod +++ b/relayer/go.mod @@ -12,7 +12,7 @@ replace ( // Fix upstream GHSA-h395-qcrw-5vmq vulnerability. // TODO remove it: https://github.com/cosmos/cosmos-sdk/issues/10409 github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.0 - github.com/rubblelabs/ripple => github.com/sologenic/ripple v0.0.0-20240212093037-7c70304af75a + github.com/rubblelabs/ripple => github.com/sologenic/ripple v0.0.0-20240311151913-cfb0e720be27 // https://github.com/cosmos/cosmos-sdk/issues/14949 // pin the version of goleveldb to v1.0.1-0.20210819022825-2ae1ddf74ef7 required by SDK v47 upgrade guide. github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 diff --git a/relayer/go.sum b/relayer/go.sum index 51c15ac1..f097c67c 100644 --- a/relayer/go.sum +++ b/relayer/go.sum @@ -952,8 +952,8 @@ github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sologenic/ripple v0.0.0-20240212093037-7c70304af75a h1:rV+sOnHYOJMQK6H4rrMV5mF4c8aBizXRBAavFvY6uZQ= -github.com/sologenic/ripple v0.0.0-20240212093037-7c70304af75a/go.mod h1:fMkR1lFpPmqtrRLsnAT86pDLUlOBqcfot815LgiAqjQ= +github.com/sologenic/ripple v0.0.0-20240311151913-cfb0e720be27 h1:/OHFmZy8m386MVKMhGO/FNZiUo4s7mvCBbQLj2d6TL8= +github.com/sologenic/ripple v0.0.0-20240311151913-cfb0e720be27/go.mod h1:fMkR1lFpPmqtrRLsnAT86pDLUlOBqcfot815LgiAqjQ= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=