From ce3d278b77cac382ed490615912f661a71372849 Mon Sep 17 00:00:00 2001 From: Gjermund Garaba Date: Thu, 21 Dec 2023 10:47:46 +0100 Subject: [PATCH] marketplace operator e2e tests (#1117) * marketplace e2e tests * Lint --- chain/tests/e2e/e2e_base.go | 12 + chain/tests/e2e/e2e_utils.go | 19 +- .../tests/e2e/marketplace/buy_credits_test.go | 96 ++++++ .../e2e/marketplace/freeze_cancel_test.go | 78 +++++ .../e2e/marketplace/freeze_release_test.go | 298 ++++++++++++++++++ chain/tests/e2e/marketplace/freeze_test.go | 83 +++++ 6 files changed, 584 insertions(+), 2 deletions(-) create mode 100644 chain/tests/e2e/marketplace/freeze_cancel_test.go create mode 100644 chain/tests/e2e/marketplace/freeze_release_test.go create mode 100644 chain/tests/e2e/marketplace/freeze_test.go diff --git a/chain/tests/e2e/e2e_base.go b/chain/tests/e2e/e2e_base.go index 934a5fb49..41a603bc8 100644 --- a/chain/tests/e2e/e2e_base.go +++ b/chain/tests/e2e/e2e_base.go @@ -34,6 +34,7 @@ const ( RandomKeyName = "randomKey" ContractAdminKeyName = "contractAdmin" NoCoinsIssuerAdminKeyName = "nocoins" + OperatorKeyName = "operator" Val1KeyName = "node0" Val2KeyName = "node1" Val3KeyName = "node2" @@ -44,6 +45,7 @@ const ( RandomAddress = "empower15hxwswcmmkasaar65n3vkmp6skurvtas3xzl7s" ContractAdminAddress = "empower1reurz37gn2sk3vgr3fupcultkagzverqczer0l" NoCoinsIssuerAdminAddress = "empower1xgsaene8aqfknmldemvl5q0mtgcgjv9svupqwu" + OperatorAddress = "empower1sqlanjwywjq84u29xvgfq7uv2d3p26u26d9c5t" DevAddress = "empower1egyu4d0zn38cs7fsynf2zq6ckppe9ecn0eh5zh" SomeOtherRandomAddress = "empower1skasndc8qy35zwymj62h4m6vl423vrf34de6xz" ) @@ -179,6 +181,15 @@ func (s *TestSuite) SetupSuite() { ) s.Require().NoError(err) + _, err = kb.NewAccount( + OperatorKeyName, + "expect guilt like ritual shrimp virtual panda plate pull dawn little retire bachelor weasel liquid remain diamond pitch mask sauce chest emotion aspect project", + keyring.DefaultBIP39Passphrase, + sdk.FullFundraiserPath, + hd.Secp256k1, + ) + s.Require().NoError(err) + // Import other validator keys to 1st validator keyring for easier voting validator2Key, err := s.Network.Validators[1].ClientCtx.Keyring.ExportPrivKeyArmor("node1", "") s.Require().NoError(err) @@ -414,4 +425,5 @@ func AddGenesisE2ETestData(cdc codec.Codec, genesisState *genesistools.GenesisSt genesistools.AddGenesisBaseAccountAndBalance(cdc, genesisState, sdk.MustAccAddressFromBech32(RandomAddress), balances) genesistools.AddGenesisBaseAccountAndBalance(cdc, genesisState, sdk.MustAccAddressFromBech32(ContractAdminAddress), balances) genesistools.AddGenesisBaseAccountAndBalance(cdc, genesisState, sdk.MustAccAddressFromBech32(NoCoinsIssuerAdminAddress), sdk.NewCoins(sdk.NewCoin(bondDenom, sdk.NewInt(10)))) + genesistools.AddGenesisBaseAccountAndBalance(cdc, genesisState, sdk.MustAccAddressFromBech32(OperatorAddress), balances) } diff --git a/chain/tests/e2e/e2e_utils.go b/chain/tests/e2e/e2e_utils.go index bf92bc436..c4908031c 100644 --- a/chain/tests/e2e/e2e_utils.go +++ b/chain/tests/e2e/e2e_utils.go @@ -12,8 +12,10 @@ import ( govcli "github.com/cosmos/cosmos-sdk/x/gov/client/cli" govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + "github.com/EmpowerPlastic/empowerchain/x/certificates" + certificatescli "github.com/EmpowerPlastic/empowerchain/x/certificates/client/cli" "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" - "github.com/EmpowerPlastic/empowerchain/x/plasticcredit/client/cli" + plasticcreditcli "github.com/EmpowerPlastic/empowerchain/x/plasticcredit/client/cli" ) func (s *TestSuite) GetBankBalance(address, denom string) uint64 { @@ -35,7 +37,7 @@ func (s *TestSuite) GetBankBalance(address, denom string) uint64 { func (s *TestSuite) GetCreditBalance(address, denom string) plasticcredit.CreditAmount { val := s.Network.Validators[0] - cmdQueryBalance := cli.CmdQueryCreditBalance() + cmdQueryBalance := plasticcreditcli.CmdQueryCreditBalance() out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmdQueryBalance, []string{address, denom, fmt.Sprintf("--%s=json", flags.FlagOutput)}) if err != nil && strings.Contains(err.Error(), "credit balance not found") { return plasticcredit.CreditAmount{} @@ -48,6 +50,19 @@ func (s *TestSuite) GetCreditBalance(address, denom string) plasticcredit.Credit return creditBalanceResponse.Balance.Balance } +func (s *TestSuite) GetCertificates(address string) []certificates.Certificate { + val := s.Network.Validators[0] + + cmdQueryCertificates := certificatescli.CmdQueryCertificatesByOwner() + out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmdQueryCertificates, []string{address, fmt.Sprintf("--%s=json", flags.FlagOutput)}) + s.Require().NoError(err) + + var certificatesResponse certificates.QueryCertificatesResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &certificatesResponse)) + + return certificatesResponse.Certificates +} + // MakeSuccessfulProposal creates a proposal, votes yes on it, and waits for it to pass // If the process fails at any point, the calling test will fail func (s *TestSuite) MakeSuccessfulProposal(pathToProposalJSON string, extraFlags ...string) { diff --git a/chain/tests/e2e/marketplace/buy_credits_test.go b/chain/tests/e2e/marketplace/buy_credits_test.go index aa701bf31..1db90fbbf 100644 --- a/chain/tests/e2e/marketplace/buy_credits_test.go +++ b/chain/tests/e2e/marketplace/buy_credits_test.go @@ -9,6 +9,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/EmpowerPlastic/empowerchain/tests/e2e" + "github.com/EmpowerPlastic/empowerchain/x/certificates" "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" "github.com/EmpowerPlastic/empowerchain/x/plasticcredit/client/cli" ) @@ -180,3 +181,98 @@ func (s *E2ETestSuite) TestBuyCreditsWithFeeSplit() { Retired: 0, }, contractCreditBalance) } + +func (s *E2ETestSuite) TestBuyCreditsWithRetire() { + val := s.Network.Validators[0] + marketplaceAddress := s.instantiateMarketplace(MarketplaceInstantiateMessage{ + Admin: e2e.ContractAdminAddress, + FeePercentage: "0", + Shares: []MarketplaceFeeShare{}, + }) + creditOwnerKey, err := val.ClientCtx.Keyring.Key(e2e.ApplicantKeyName) + s.Require().NoError(err) + creditOwnerAddress, err := creditOwnerKey.GetAddress() + s.Require().NoError(err) + buyerKey, err := val.ClientCtx.Keyring.Key(e2e.RandomKeyName) + s.Require().NoError(err) + + grantCmd := cli.MsgGrantTransferAuthorizationCmd() + out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, grantCmd, append([]string{ + marketplaceAddress, + "PTEST/00001", + "10", + fmt.Sprintf("--%s=%s", flags.FlagFrom, creditOwnerKey.Name), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err := s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Create the listing + executeContractCmd := wasmcli.ExecuteContractCmd() + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"create_listing": {"denom": "PTEST/00001", "number_of_credits": "5", "price_per_credit": {"denom": "%s", "amount": "1500000"}}}`, sdk.DefaultBondDenom), + fmt.Sprintf("--%s=%s", flags.FlagFrom, creditOwnerKey.Name), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Get balances before the transaction + creditOwnerBalanceBefore := s.GetBankBalance(e2e.ApplicantAddress, sdk.DefaultBondDenom) + buyerBalanceBefore := s.GetBankBalance(e2e.RandomAddress, sdk.DefaultBondDenom) + buyerCreditBalanceBefore := s.GetCreditBalance(e2e.RandomAddress, "PTEST/00001") + certsBefore := s.GetCertificates(e2e.RandomAddress) + + // Buy some credits + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"buy_credits": {"owner": "%s", "denom": "PTEST/00001", "number_of_credits_to_buy": 2, "retire": true, "retiring_entity_name": "retire_name", "retiring_entity_additional_data": "additional_retire_date"}}`, creditOwnerAddress.String()), + fmt.Sprintf("--amount=%s%s", "3000000", sdk.DefaultBondDenom), + fmt.Sprintf("--%s=%s", flags.FlagFrom, buyerKey.Name), + fmt.Sprintf("--%s=%s", flags.FlagGas, "300000"), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Get balances after the transaction + creditOwnerBalanceAfter := s.GetBankBalance(e2e.ApplicantAddress, sdk.DefaultBondDenom) + buyerBalanceAfter := s.GetBankBalance(e2e.RandomAddress, sdk.DefaultBondDenom) + + // Check that the coin balances are correct + s.Require().Equal(creditOwnerBalanceBefore+3000000, creditOwnerBalanceAfter) + s.Require().Equal(buyerBalanceBefore-3000000-e2e.DefaultFee.Amount.Uint64(), buyerBalanceAfter) + + // Check that the credits were transferred + buyerCreditBalance := s.GetCreditBalance(e2e.RandomAddress, "PTEST/00001") + s.Require().Equal(plasticcredit.CreditAmount{ + Active: buyerCreditBalanceBefore.Active, + Retired: buyerCreditBalanceBefore.Retired + 2, + }, buyerCreditBalance) + contractCreditBalance := s.GetCreditBalance(marketplaceAddress, "PTEST/00001") + s.Require().Equal(plasticcredit.CreditAmount{ + Active: 3, + Retired: 0, + }, contractCreditBalance) + + // Check that the certificate was created + certs := s.GetCertificates(e2e.RandomAddress) + s.Require().Len(certs, len(certsBefore)+1) + s.Require().Equal(certs[len(certs)-1].Owner, e2e.RandomAddress) + s.Require().Equal(certs[len(certs)-1].Type, certificates.CertificateType_CREDIT_RETIREMENT) + s.Require().Equal(certs[len(certs)-1].Issuer, e2e.IssuerAddress) + s.Require().Equal(certs[len(certs)-1].AdditionalData[0].Key, "denom") + s.Require().Equal(certs[len(certs)-1].AdditionalData[0].Value, "PTEST/00001") + s.Require().Equal(certs[len(certs)-1].AdditionalData[1].Key, "amount") + s.Require().Equal(certs[len(certs)-1].AdditionalData[1].Value, "2") + s.Require().Equal(certs[len(certs)-1].AdditionalData[2].Key, "retiring_entity_address") + s.Require().Equal(certs[len(certs)-1].AdditionalData[2].Value, e2e.RandomAddress) + s.Require().Equal(certs[len(certs)-1].AdditionalData[3].Key, "retiring_entity_name") + s.Require().Equal(certs[len(certs)-1].AdditionalData[3].Value, "retire_name") + s.Require().Equal(certs[len(certs)-1].AdditionalData[4].Key, "retiring_entity_additional_data") + s.Require().Equal(certs[len(certs)-1].AdditionalData[4].Value, "additional_retire_date") +} diff --git a/chain/tests/e2e/marketplace/freeze_cancel_test.go b/chain/tests/e2e/marketplace/freeze_cancel_test.go new file mode 100644 index 000000000..2c45ef808 --- /dev/null +++ b/chain/tests/e2e/marketplace/freeze_cancel_test.go @@ -0,0 +1,78 @@ +package marketplace_test + +import ( + "fmt" + "time" + + wasmcli "github.com/CosmWasm/wasmd/x/wasm/client/cli" + "github.com/cosmos/cosmos-sdk/client/flags" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/EmpowerPlastic/empowerchain/tests/e2e" + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit/client/cli" +) + +func (s *E2ETestSuite) TestFreezeCancelCredits() { + val := s.Network.Validators[0] + marketplaceAddress := s.instantiateMarketplace(MarketplaceInstantiateMessage{ + Admin: e2e.ContractAdminAddress, + FeePercentage: "0", + Shares: []MarketplaceFeeShare{}, + }) + creditOwnerKey, err := val.ClientCtx.Keyring.Key(e2e.ApplicantKeyName) + s.Require().NoError(err) + creditOwnerAddress, err := creditOwnerKey.GetAddress() + s.Require().NoError(err) + buyerKey, err := val.ClientCtx.Keyring.Key(e2e.RandomKeyName) + s.Require().NoError(err) + buyerAddress, err := buyerKey.GetAddress() + s.Require().NoError(err) + + grantCmd := cli.MsgGrantTransferAuthorizationCmd() + out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, grantCmd, append([]string{ + marketplaceAddress, + "PTEST/00001", + "10", + fmt.Sprintf("--%s=%s", flags.FlagFrom, creditOwnerKey.Name), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err := s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Create the listing + executeContractCmd := wasmcli.ExecuteContractCmd() + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"create_listing": {"denom": "PTEST/00001", "number_of_credits": "5", "price_per_credit": {"denom": "%s", "amount": "1500000"}, "operator": "%s"}}`, sdk.DefaultBondDenom, e2e.OperatorAddress), + fmt.Sprintf("--%s=%s", flags.FlagFrom, creditOwnerKey.Name), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Freeze credits + timeoutUnixTimestamp := time.Now().Unix() + 1000 // 1000 seconds into the future + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"freeze_credits": {"owner": "%s", "denom": "PTEST/00001", "number_of_credits_to_freeze": 5, "buyer": "%s", "timeout_unix_timestamp": %d}}`, creditOwnerAddress, buyerAddress, timeoutUnixTimestamp), + fmt.Sprintf("--%s=%s", flags.FlagFrom, e2e.OperatorKeyName), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Cancel freeze + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"cancel_frozen_credits": {"owner": "%s", "denom": "PTEST/00001", "number_of_frozen_credits_to_cancel": 5, "buyer": "%s"}}`, creditOwnerAddress, buyerAddress), + fmt.Sprintf("--%s=%s", flags.FlagFrom, e2e.OperatorKeyName), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) +} diff --git a/chain/tests/e2e/marketplace/freeze_release_test.go b/chain/tests/e2e/marketplace/freeze_release_test.go new file mode 100644 index 000000000..08bbb6b48 --- /dev/null +++ b/chain/tests/e2e/marketplace/freeze_release_test.go @@ -0,0 +1,298 @@ +package marketplace_test + +import ( + "fmt" + "time" + + wasmcli "github.com/CosmWasm/wasmd/x/wasm/client/cli" + "github.com/cometbft/cometbft/crypto/secp256k1" + "github.com/cosmos/cosmos-sdk/client/flags" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/EmpowerPlastic/empowerchain/tests/e2e" + "github.com/EmpowerPlastic/empowerchain/x/certificates" + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit/client/cli" +) + +func (s *E2ETestSuite) TestFreezeReleaseCreditsWithoutFeeSplit() { + val := s.Network.Validators[0] + marketplaceAddress := s.instantiateMarketplace(MarketplaceInstantiateMessage{ + Admin: e2e.ContractAdminAddress, + FeePercentage: "0", + Shares: []MarketplaceFeeShare{}, + }) + creditOwnerKey, err := val.ClientCtx.Keyring.Key(e2e.ApplicantKeyName) + s.Require().NoError(err) + creditOwnerAddress, err := creditOwnerKey.GetAddress() + s.Require().NoError(err) + randomPrivKey := secp256k1.GenPrivKeySecp256k1([]byte("random string 0")) + randomPubKey := randomPrivKey.PubKey() + randomBuyerAddress := sdk.AccAddress(randomPubKey.Address().Bytes()) + + grantCmd := cli.MsgGrantTransferAuthorizationCmd() + out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, grantCmd, append([]string{ + marketplaceAddress, + "PTEST/00001", + "10", + fmt.Sprintf("--%s=%s", flags.FlagFrom, creditOwnerKey.Name), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err := s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Create the listing + executeContractCmd := wasmcli.ExecuteContractCmd() + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"create_listing": {"denom": "PTEST/00001", "number_of_credits": "5", "price_per_credit": {"denom": "%s", "amount": "1500000"}, "operator": "%s"}}`, sdk.DefaultBondDenom, e2e.OperatorAddress), + fmt.Sprintf("--%s=%s", flags.FlagFrom, creditOwnerKey.Name), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Freeze credits + timeoutUnixTimestamp := time.Now().Unix() + 1000 // 1000 seconds into the future + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"freeze_credits": {"owner": "%s", "denom": "PTEST/00001", "number_of_credits_to_freeze": 5, "buyer": "%s", "timeout_unix_timestamp": %d}}`, creditOwnerAddress, randomBuyerAddress, timeoutUnixTimestamp), + fmt.Sprintf("--%s=%s", flags.FlagFrom, e2e.OperatorKeyName), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Get balances before the transaction + buyerCreditBalanceBefore := s.GetCreditBalance(randomBuyerAddress.String(), "PTEST/00001") + + // Release freeze + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"release_frozen_credits": {"owner": "%s", "denom": "PTEST/00001", "number_of_credits_to_release": 2, "buyer": "%s", "retire": false}}`, creditOwnerAddress, randomBuyerAddress), + fmt.Sprintf("--%s=%s", flags.FlagFrom, e2e.OperatorKeyName), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Check that the credits were transferred + buyerCreditBalance := s.GetCreditBalance(randomBuyerAddress.String(), "PTEST/00001") + s.Require().Equal(plasticcredit.CreditAmount{ + Active: buyerCreditBalanceBefore.Active + 2, + Retired: buyerCreditBalanceBefore.Retired, + }, buyerCreditBalance) + contractCreditBalance := s.GetCreditBalance(marketplaceAddress, "PTEST/00001") + s.Require().Equal(plasticcredit.CreditAmount{ + Active: 3, + Retired: 0, + }, contractCreditBalance) +} + +func (s *E2ETestSuite) TestFreezeReleaseCreditsWithFeeShare() { + val := s.Network.Validators[0] + marketplaceAddress := s.instantiateMarketplace(MarketplaceInstantiateMessage{ + Admin: e2e.ContractAdminAddress, + FeePercentage: "0.005", + Shares: []MarketplaceFeeShare{ + { + Address: e2e.DevAddress, + Percentage: "0.7", + }, + { + Address: e2e.SomeOtherRandomAddress, + Percentage: "0.3", + }, + }, + }) + creditOwnerKey, err := val.ClientCtx.Keyring.Key(e2e.ApplicantKeyName) + s.Require().NoError(err) + creditOwnerAddress, err := creditOwnerKey.GetAddress() + s.Require().NoError(err) + randomPrivKey := secp256k1.GenPrivKeySecp256k1([]byte("random string 1")) + randomPubKey := randomPrivKey.PubKey() + randomBuyerAddress := sdk.AccAddress(randomPubKey.Address().Bytes()) + + grantCmd := cli.MsgGrantTransferAuthorizationCmd() + out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, grantCmd, append([]string{ + marketplaceAddress, + "PTEST/00001", + "10", + fmt.Sprintf("--%s=%s", flags.FlagFrom, creditOwnerKey.Name), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err := s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Create the listing + executeContractCmd := wasmcli.ExecuteContractCmd() + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"create_listing": {"denom": "PTEST/00001", "number_of_credits": "5", "price_per_credit": {"denom": "%s", "amount": "1500000"}, "operator": "%s"}}`, sdk.DefaultBondDenom, e2e.OperatorAddress), + fmt.Sprintf("--%s=%s", flags.FlagFrom, creditOwnerKey.Name), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Freeze credits + timeoutUnixTimestamp := time.Now().Unix() + 1000 // 1000 seconds into the future + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"freeze_credits": {"owner": "%s", "denom": "PTEST/00001", "number_of_credits_to_freeze": 5, "buyer": "%s", "timeout_unix_timestamp": %d}}`, creditOwnerAddress, randomBuyerAddress, timeoutUnixTimestamp), + fmt.Sprintf("--%s=%s", flags.FlagFrom, e2e.OperatorKeyName), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Get balances before the transaction + operatorBalanceBefore := s.GetBankBalance(e2e.OperatorAddress, sdk.DefaultBondDenom) + creditOwnerBalanceBefore := s.GetBankBalance(e2e.ApplicantAddress, sdk.DefaultBondDenom) + buyerBalanceBefore := s.GetBankBalance(randomBuyerAddress.String(), sdk.DefaultBondDenom) + devBalanceBefore := s.GetBankBalance(e2e.DevAddress, sdk.DefaultBondDenom) + someOtherRandomBalanceBefore := s.GetBankBalance(e2e.SomeOtherRandomAddress, sdk.DefaultBondDenom) + buyerCreditBalanceBefore := s.GetCreditBalance(randomBuyerAddress.String(), "PTEST/00001") + + // Release freeze + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"release_frozen_credits": {"owner": "%s", "denom": "PTEST/00001", "number_of_credits_to_release": 2, "buyer": "%s", "retire": false}}`, creditOwnerAddress, randomBuyerAddress), + fmt.Sprintf("--amount=%s%s", "15000", sdk.DefaultBondDenom), + fmt.Sprintf("--%s=%s", flags.FlagGas, "300000"), + fmt.Sprintf("--%s=%s", flags.FlagFrom, e2e.OperatorKeyName), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Get balances after the transaction + operatorBalanceAfter := s.GetBankBalance(e2e.OperatorAddress, sdk.DefaultBondDenom) + creditOwnerBalanceAfter := s.GetBankBalance(e2e.ApplicantAddress, sdk.DefaultBondDenom) + buyerBalanceAfter := s.GetBankBalance(randomBuyerAddress.String(), sdk.DefaultBondDenom) + devBalanceAfter := s.GetBankBalance(e2e.DevAddress, sdk.DefaultBondDenom) + someOtherRandomBalanceAfter := s.GetBankBalance(e2e.SomeOtherRandomAddress, sdk.DefaultBondDenom) + + // Check that the coin balances are correct + s.Require().Equal(operatorBalanceBefore-15000-e2e.DefaultFee.Amount.Uint64(), operatorBalanceAfter) + s.Require().Equal(creditOwnerBalanceBefore, creditOwnerBalanceAfter) // Payment is happening off-chain in this scenario + s.Require().Equal(buyerBalanceBefore, buyerBalanceAfter) // Payment is happening off-chain in this scenario + s.Require().Equal(devBalanceBefore+10500, devBalanceAfter) + s.Require().Equal(someOtherRandomBalanceBefore+4500, someOtherRandomBalanceAfter) + + // Check that the credits were transferred + buyerCreditBalance := s.GetCreditBalance(randomBuyerAddress.String(), "PTEST/00001") + s.Require().Equal(plasticcredit.CreditAmount{ + Active: buyerCreditBalanceBefore.Active + 2, + Retired: buyerCreditBalanceBefore.Retired, + }, buyerCreditBalance) + contractCreditBalance := s.GetCreditBalance(marketplaceAddress, "PTEST/00001") + s.Require().Equal(plasticcredit.CreditAmount{ + Active: 3, + Retired: 0, + }, contractCreditBalance) +} + +func (s *E2ETestSuite) TestFreezeReleaseCreditsWithRetire() { + val := s.Network.Validators[0] + marketplaceAddress := s.instantiateMarketplace(MarketplaceInstantiateMessage{ + Admin: e2e.ContractAdminAddress, + FeePercentage: "0", + Shares: []MarketplaceFeeShare{}, + }) + creditOwnerKey, err := val.ClientCtx.Keyring.Key(e2e.ApplicantKeyName) + s.Require().NoError(err) + creditOwnerAddress, err := creditOwnerKey.GetAddress() + s.Require().NoError(err) + randomPrivKey := secp256k1.GenPrivKeySecp256k1([]byte("random string 2")) + randomPubKey := randomPrivKey.PubKey() + randomBuyerAddress := sdk.AccAddress(randomPubKey.Address().Bytes()) + + grantCmd := cli.MsgGrantTransferAuthorizationCmd() + out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, grantCmd, append([]string{ + marketplaceAddress, + "PTEST/00001", + "10", + fmt.Sprintf("--%s=%s", flags.FlagFrom, creditOwnerKey.Name), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err := s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Create the listing + executeContractCmd := wasmcli.ExecuteContractCmd() + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"create_listing": {"denom": "PTEST/00001", "number_of_credits": "5", "price_per_credit": {"denom": "%s", "amount": "1500000"}, "operator": "%s"}}`, sdk.DefaultBondDenom, e2e.OperatorAddress), + fmt.Sprintf("--%s=%s", flags.FlagFrom, creditOwnerKey.Name), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Freeze credits + timeoutUnixTimestamp := time.Now().Unix() + 1000 // 1000 seconds into the future + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"freeze_credits": {"owner": "%s", "denom": "PTEST/00001", "number_of_credits_to_freeze": 5, "buyer": "%s", "timeout_unix_timestamp": %d}}`, creditOwnerAddress, randomBuyerAddress, timeoutUnixTimestamp), + fmt.Sprintf("--%s=%s", flags.FlagFrom, e2e.OperatorKeyName), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Get balances before the transaction + buyerCreditBalanceBefore := s.GetCreditBalance(randomBuyerAddress.String(), "PTEST/00001") + + // Release freeze + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"release_frozen_credits": {"owner": "%s", "denom": "PTEST/00001", "number_of_credits_to_release": 2, "buyer": "%s", "retire": true, "retiring_entity_name": "test_retire_name", "retiring_entity_additional_data": "test_retire_data"}}`, creditOwnerAddress, randomBuyerAddress), + fmt.Sprintf("--%s=%s", flags.FlagFrom, e2e.OperatorKeyName), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Check that the credits were transferred + buyerCreditBalance := s.GetCreditBalance(randomBuyerAddress.String(), "PTEST/00001") + s.Require().Equal(plasticcredit.CreditAmount{ + Active: buyerCreditBalanceBefore.Active, + Retired: buyerCreditBalanceBefore.Retired + 2, + }, buyerCreditBalance) + contractCreditBalance := s.GetCreditBalance(marketplaceAddress, "PTEST/00001") + s.Require().Equal(plasticcredit.CreditAmount{ + Active: 3, + Retired: 0, + }, contractCreditBalance) + + // Check that the certificate was created + certs := s.GetCertificates(randomBuyerAddress.String()) + s.Require().Len(certs, 1) + s.Require().Equal(certs[0].Owner, randomBuyerAddress.String()) + s.Require().Equal(certs[0].Type, certificates.CertificateType_CREDIT_RETIREMENT) + s.Require().Equal(certs[0].Issuer, e2e.IssuerAddress) + s.Require().Equal(certs[0].AdditionalData[0].Key, "denom") + s.Require().Equal(certs[0].AdditionalData[0].Value, "PTEST/00001") + s.Require().Equal(certs[0].AdditionalData[1].Key, "amount") + s.Require().Equal(certs[0].AdditionalData[1].Value, "2") + s.Require().Equal(certs[0].AdditionalData[2].Key, "retiring_entity_address") + s.Require().Equal(certs[0].AdditionalData[2].Value, randomBuyerAddress.String()) + s.Require().Equal(certs[0].AdditionalData[3].Key, "retiring_entity_name") + s.Require().Equal(certs[0].AdditionalData[3].Value, "test_retire_name") + s.Require().Equal(certs[0].AdditionalData[4].Key, "retiring_entity_additional_data") + s.Require().Equal(certs[0].AdditionalData[4].Value, "test_retire_data") +} diff --git a/chain/tests/e2e/marketplace/freeze_test.go b/chain/tests/e2e/marketplace/freeze_test.go new file mode 100644 index 000000000..ede8829d2 --- /dev/null +++ b/chain/tests/e2e/marketplace/freeze_test.go @@ -0,0 +1,83 @@ +package marketplace_test + +import ( + "fmt" + "time" + + wasmcli "github.com/CosmWasm/wasmd/x/wasm/client/cli" + "github.com/cosmos/cosmos-sdk/client/flags" + clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/EmpowerPlastic/empowerchain/tests/e2e" + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit" + "github.com/EmpowerPlastic/empowerchain/x/plasticcredit/client/cli" +) + +func (s *E2ETestSuite) TestFreezeCredits() { + val := s.Network.Validators[0] + marketplaceAddress := s.instantiateMarketplace(MarketplaceInstantiateMessage{ + Admin: e2e.ContractAdminAddress, + FeePercentage: "0", + Shares: []MarketplaceFeeShare{}, + }) + creditOwnerKey, err := val.ClientCtx.Keyring.Key(e2e.ApplicantKeyName) + s.Require().NoError(err) + creditOwnerAddress, err := creditOwnerKey.GetAddress() + s.Require().NoError(err) + buyerKey, err := val.ClientCtx.Keyring.Key(e2e.RandomKeyName) + s.Require().NoError(err) + buyerAddress, err := buyerKey.GetAddress() + s.Require().NoError(err) + + grantCmd := cli.MsgGrantTransferAuthorizationCmd() + out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, grantCmd, append([]string{ + marketplaceAddress, + "PTEST/00001", + "10", + fmt.Sprintf("--%s=%s", flags.FlagFrom, creditOwnerKey.Name), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err := s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Create the listing + executeContractCmd := wasmcli.ExecuteContractCmd() + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"create_listing": {"denom": "PTEST/00001", "number_of_credits": "5", "price_per_credit": {"denom": "%s", "amount": "1500000"}, "operator": "%s"}}`, sdk.DefaultBondDenom, e2e.OperatorAddress), + fmt.Sprintf("--%s=%s", flags.FlagFrom, creditOwnerKey.Name), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Get balances before the transaction + buyerCreditBalanceBefore := s.GetCreditBalance(e2e.RandomAddress, "PTEST/00001") + + // Freeze credits + timeoutUnixTimestamp := time.Now().Unix() + 1000 // 1000 seconds into the future + out, err = clitestutil.ExecTestCLICmd(val.ClientCtx, executeContractCmd, append([]string{ + marketplaceAddress, + fmt.Sprintf(`{"freeze_credits": {"owner": "%s", "denom": "PTEST/00001", "number_of_credits_to_freeze": 5, "buyer": "%s", "timeout_unix_timestamp": %d}}`, creditOwnerAddress, buyerAddress, timeoutUnixTimestamp), + fmt.Sprintf("--%s=%s", flags.FlagFrom, e2e.OperatorKeyName), + }, s.CommonFlags...)) + s.Require().NoError(err, out.String()) + cliResponse, err = s.GetCliResponse(val.ClientCtx, out.Bytes()) + s.Require().NoError(err) + s.Require().Equal(uint32(0), cliResponse.Code, cliResponse.RawLog) + + // Check that no credits were transferred + buyerCreditBalance := s.GetCreditBalance(e2e.RandomAddress, "PTEST/00001") + s.Require().Equal(plasticcredit.CreditAmount{ + Active: buyerCreditBalanceBefore.Active, + Retired: buyerCreditBalanceBefore.Retired, + }, buyerCreditBalance) + contractCreditBalance := s.GetCreditBalance(marketplaceAddress, "PTEST/00001") + s.Require().Equal(plasticcredit.CreditAmount{ + Active: 5, + Retired: 0, + }, contractCreditBalance) +}