From 6ed21ea3fba41b47dc52876f9f016b5f6c4a5757 Mon Sep 17 00:00:00 2001 From: MiniFrenchBread <103425574+MiniFrenchBread@users.noreply.github.com> Date: Fri, 10 Jan 2025 17:00:09 +0800 Subject: [PATCH] test: wrapped-a0gi-base precompile --- precompiles/wrapped-a0gi-base/query_test.go | 147 ++++++++++++ precompiles/wrapped-a0gi-base/tx_test.go | 218 ++++++++++++++++++ .../wrapped_a0gi_base_test.go | 80 +++++++ 3 files changed, 445 insertions(+) create mode 100644 precompiles/wrapped-a0gi-base/query_test.go create mode 100644 precompiles/wrapped-a0gi-base/tx_test.go create mode 100644 precompiles/wrapped-a0gi-base/wrapped_a0gi_base_test.go diff --git a/precompiles/wrapped-a0gi-base/query_test.go b/precompiles/wrapped-a0gi-base/query_test.go new file mode 100644 index 00000000..a930f12b --- /dev/null +++ b/precompiles/wrapped-a0gi-base/query_test.go @@ -0,0 +1,147 @@ +package wrappeda0gibase_test + +import ( + "math/big" + + wrappeda0gibaseprecompile "github.com/0glabs/0g-chain/precompiles/wrapped-a0gi-base" + "github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" +) + +func (s *WrappedA0giBaseTestSuite) TestGetW0GI() { + method := wrappeda0gibaseprecompile.WrappedA0GIBaseFunctionGetWA0GI + + testCases := []struct { + name string + malleate func() []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "success", + func() []byte { + input, err := s.abi.Pack( + method, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + wa0gi := out[0].(common.Address) + s.Require().Equal(wa0gi, common.HexToAddress(types.DEFAULT_WRAPPED_A0GI)) + // fmt.Println(wa0gi) + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + + bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} + +func (s *WrappedA0giBaseTestSuite) TestMinterSupply() { + method := wrappeda0gibaseprecompile.WrappedA0GIBaseFunctionMinterSupply + govAccAddr := s.App.GetGovKeeper().GetGovernanceAccount(s.Ctx).GetAddress().String() + + testCases := []struct { + name string + malleate func() []byte + postCheck func(bz []byte) + gas uint64 + expErr bool + errContains string + }{ + { + "non-empty", + func() []byte { + input, err := s.abi.Pack( + method, + s.signerOne.Addr, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + wa0gi := out[0].(wrappeda0gibaseprecompile.Supply) + s.Require().Equal(wa0gi.Cap, big.NewInt(8e18)) + s.Require().Equal(wa0gi.Total, big.NewInt(1e18)) + // fmt.Println(wa0gi) + }, + 100000, + false, + "", + }, { + "empty", + func() []byte { + input, err := s.abi.Pack( + method, + s.signerTwo.Addr, + ) + s.Assert().NoError(err) + return input + }, + func(data []byte) { + out, err := s.abi.Methods[method].Outputs.Unpack(data) + s.Require().NoError(err, "failed to unpack output") + supply := out[0].(wrappeda0gibaseprecompile.Supply) + s.Require().Equal(supply.Cap.Bytes(), big.NewInt(0).Bytes()) + s.Require().Equal(supply.Total.Bytes(), big.NewInt(0).Bytes()) + // fmt.Println(wa0gi) + }, + 100000, + false, + "", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + + s.wa0gibasekeeper.SetMinterCap(sdk.WrapSDKContext(s.Ctx), &types.MsgSetMintCap{ + Authority: govAccAddr, + Minter: s.signerOne.Addr.Bytes(), + Cap: big.NewInt(8e18).Bytes(), + }) + + s.wa0gibasekeeper.Mint(sdk.WrapSDKContext(s.Ctx), &types.MsgMint{ + Minter: s.signerOne.Addr.Bytes(), + Amount: big.NewInt(1e18).Bytes(), + }) + + bz, err := s.runTx(tc.malleate(), s.signerOne, 10000000) + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + s.Require().NotNil(bz) + tc.postCheck(bz) + } + }) + } +} diff --git a/precompiles/wrapped-a0gi-base/tx_test.go b/precompiles/wrapped-a0gi-base/tx_test.go new file mode 100644 index 00000000..81910379 --- /dev/null +++ b/precompiles/wrapped-a0gi-base/tx_test.go @@ -0,0 +1,218 @@ +package wrappeda0gibase_test + +import ( + "fmt" + "math/big" + + wrappeda0gibaseprecompile "github.com/0glabs/0g-chain/precompiles/wrapped-a0gi-base" + "github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (s *WrappedA0giBaseTestSuite) TestMint() { + method := wrappeda0gibaseprecompile.WrappedA0GIBaseFunctionMint + govAccAddr := s.App.GetGovKeeper().GetGovernanceAccount(s.Ctx).GetAddress().String() + + testCases := []struct { + name string + malleate func() []byte + postCheck func() + gas uint64 + expErr bool + errContains string + isSignerOne bool + }{ + { + "success", + func() []byte { + input, err := s.abi.Pack( + method, + s.signerOne.Addr, + big.NewInt(1e18), + ) + s.Assert().NoError(err) + return input + }, + func() { + supply, err := s.wa0gibasekeeper.MinterSupply(s.Ctx, &types.MinterSupplyRequest{ + Address: s.signerOne.Addr.Bytes(), + }) + s.Assert().NoError(err) + s.Require().Equal(supply.Cap, big.NewInt(8e18).Bytes()) + s.Require().Equal(supply.Supply, big.NewInt(1e18).Bytes()) + // fmt.Println(wa0gi) + }, + 100000, + false, + "", + true, + }, { + "fail", + func() []byte { + input, err := s.abi.Pack( + method, + s.signerOne.Addr, + big.NewInt(9e18), + ) + s.Assert().NoError(err) + return input + }, + func() {}, + 100000, + true, + "insufficient mint cap", + true, + }, { + "invalid sender", + func() []byte { + input, err := s.abi.Pack( + method, + s.signerTwo.Addr, + big.NewInt(9e18), + ) + s.Assert().NoError(err) + return input + }, + func() {}, + 100000, + true, + "sender is not WA0GI", + false, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + + fmt.Println(s.signerOne.Addr) + s.wa0gibasekeeper.SetWA0GIAddress(s.Ctx, s.signerOne.Addr) + s.wa0gibasekeeper.SetMinterCap(sdk.WrapSDKContext(s.Ctx), &types.MsgSetMintCap{ + Authority: govAccAddr, + Minter: s.signerOne.Addr.Bytes(), + Cap: big.NewInt(8e18).Bytes(), + }) + + var err error + if tc.isSignerOne { + _, err = s.runTx(tc.malleate(), s.signerOne, 10000000) + } else { + _, err = s.runTx(tc.malleate(), s.signerTwo, 10000000) + } + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + tc.postCheck() + } + }) + } +} + +func (s *WrappedA0giBaseTestSuite) TestBurn() { + method := wrappeda0gibaseprecompile.WrappedA0GIBaseFunctionBurn + govAccAddr := s.App.GetGovKeeper().GetGovernanceAccount(s.Ctx).GetAddress().String() + + testCases := []struct { + name string + malleate func() []byte + postCheck func() + gas uint64 + expErr bool + errContains string + isSignerOne bool + }{ + { + "success", + func() []byte { + input, err := s.abi.Pack( + method, + s.signerOne.Addr, + big.NewInt(1e18), + ) + s.Assert().NoError(err) + return input + }, + func() { + supply, err := s.wa0gibasekeeper.MinterSupply(s.Ctx, &types.MinterSupplyRequest{ + Address: s.signerOne.Addr.Bytes(), + }) + s.Assert().NoError(err) + s.Require().Equal(supply.Cap, big.NewInt(8e18).Bytes()) + s.Require().Equal(supply.Supply, big.NewInt(3e18).Bytes()) + // fmt.Println(wa0gi) + }, + 100000, + false, + "", + true, + }, { + "fail", + func() []byte { + input, err := s.abi.Pack( + method, + s.signerOne.Addr, + big.NewInt(9e18), + ) + s.Assert().NoError(err) + return input + }, + func() {}, + 100000, + true, + "insufficient mint supply", + true, + }, { + "invalid sender", + func() []byte { + input, err := s.abi.Pack( + method, + s.signerTwo.Addr, + big.NewInt(9e18), + ) + s.Assert().NoError(err) + return input + }, + func() {}, + 100000, + true, + "sender is not WA0GI", + false, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + s.SetupTest() + + fmt.Println(s.signerOne.Addr) + s.wa0gibasekeeper.SetWA0GIAddress(s.Ctx, s.signerOne.Addr) + s.wa0gibasekeeper.SetMinterCap(sdk.WrapSDKContext(s.Ctx), &types.MsgSetMintCap{ + Authority: govAccAddr, + Minter: s.signerOne.Addr.Bytes(), + Cap: big.NewInt(8e18).Bytes(), + }) + s.wa0gibasekeeper.Mint(sdk.WrapSDKContext(s.Ctx), &types.MsgMint{ + Minter: s.signerOne.Addr.Bytes(), + Amount: big.NewInt(4e18).Bytes(), + }) + + var err error + if tc.isSignerOne { + _, err = s.runTx(tc.malleate(), s.signerOne, 10000000) + } else { + _, err = s.runTx(tc.malleate(), s.signerTwo, 10000000) + } + + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.errContains) + } else { + s.Require().NoError(err) + tc.postCheck() + } + }) + } +} diff --git a/precompiles/wrapped-a0gi-base/wrapped_a0gi_base_test.go b/precompiles/wrapped-a0gi-base/wrapped_a0gi_base_test.go new file mode 100644 index 00000000..62bfce4b --- /dev/null +++ b/precompiles/wrapped-a0gi-base/wrapped_a0gi_base_test.go @@ -0,0 +1,80 @@ +package wrappeda0gibase_test + +import ( + "math/big" + "strings" + "testing" + + "github.com/0glabs/0g-chain/precompiles/testutil" + wrappeda0gibaseprecompile "github.com/0glabs/0g-chain/precompiles/wrapped-a0gi-base" + wrappeda0gibasekeeper "github.com/0glabs/0g-chain/x/wrapped-a0gi-base/keeper" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/vm" + "github.com/evmos/ethermint/x/evm/statedb" + evmtypes "github.com/evmos/ethermint/x/evm/types" + "github.com/stretchr/testify/suite" +) + +type WrappedA0giBaseTestSuite struct { + testutil.PrecompileTestSuite + + abi abi.ABI + addr common.Address + wa0gibasekeeper wrappeda0gibasekeeper.Keeper + wa0gibase *wrappeda0gibaseprecompile.WrappedA0giBasePrecompile + signerOne *testutil.TestSigner + signerTwo *testutil.TestSigner +} + +func (suite *WrappedA0giBaseTestSuite) SetupTest() { + suite.PrecompileTestSuite.SetupTest() + + suite.wa0gibasekeeper = suite.App.GetWrappedA0GIBaseKeeper() + + suite.addr = common.HexToAddress(wrappeda0gibaseprecompile.PrecompileAddress) + + precompiles := suite.EvmKeeper.GetPrecompiles() + precompile, ok := precompiles[suite.addr] + suite.Assert().EqualValues(ok, true) + + suite.wa0gibase = precompile.(*wrappeda0gibaseprecompile.WrappedA0giBasePrecompile) + + suite.signerOne = suite.GenSigner() + suite.signerTwo = suite.GenSigner() + + abi, err := abi.JSON(strings.NewReader(wrappeda0gibaseprecompile.Wrappeda0gibaseABI)) + suite.Assert().NoError(err) + suite.abi = abi +} + +func (suite *WrappedA0giBaseTestSuite) runTx(input []byte, signer *testutil.TestSigner, gas uint64) ([]byte, error) { + contract := vm.NewPrecompile(vm.AccountRef(signer.Addr), vm.AccountRef(suite.addr), big.NewInt(0), gas) + contract.Input = input + + msgEthereumTx := evmtypes.NewTx(suite.EvmKeeper.ChainID(), 0, &suite.addr, big.NewInt(0), gas, big.NewInt(0), big.NewInt(0), big.NewInt(0), input, nil) + msgEthereumTx.From = signer.HexAddr + err := msgEthereumTx.Sign(suite.EthSigner, signer.Signer) + suite.Assert().NoError(err, "failed to sign Ethereum message") + + proposerAddress := suite.Ctx.BlockHeader().ProposerAddress + cfg, err := suite.EvmKeeper.EVMConfig(suite.Ctx, proposerAddress, suite.EvmKeeper.ChainID()) + suite.Assert().NoError(err, "failed to instantiate EVM config") + + msg, err := msgEthereumTx.AsMessage(suite.EthSigner, big.NewInt(0)) + suite.Assert().NoError(err, "failed to instantiate Ethereum message") + + evm := suite.EvmKeeper.NewEVM(suite.Ctx, msg, cfg, nil, suite.Statedb) + precompiles := suite.EvmKeeper.GetPrecompiles() + evm.WithPrecompiles(precompiles, []common.Address{suite.addr}) + + bz, err := suite.wa0gibase.Run(evm, contract, false) + if err == nil { + evm.StateDB.(*statedb.StateDB).Commit() + } + return bz, err +} + +func TestWrappedA0giBaseTestSuite(t *testing.T) { + suite.Run(t, new(WrappedA0giBaseTestSuite)) +}