diff --git a/app/test_common.go b/app/test_common.go
index b822ddd2..b4657884 100644
--- a/app/test_common.go
+++ b/app/test_common.go
@@ -49,6 +49,7 @@ import (
 	issuancekeeper "github.com/0glabs/0g-chain/x/issuance/keeper"
 	precisebankkeeper "github.com/0glabs/0g-chain/x/precisebank/keeper"
 	pricefeedkeeper "github.com/0glabs/0g-chain/x/pricefeed/keeper"
+	wrappeda0gibasekeeper "github.com/0glabs/0g-chain/x/wrapped-a0gi-base/keeper"
 )
 
 var (
@@ -118,6 +119,9 @@ func (tApp TestApp) GetEvmKeeper() *evmkeeper.Keeper                { return tAp
 func (tApp TestApp) GetFeeMarketKeeper() feemarketkeeper.Keeper     { return tApp.feeMarketKeeper }
 func (tApp TestApp) GetDASignersKeeper() dasignerskeeper.Keeper     { return tApp.dasignersKeeper }
 func (tApp TestApp) GetPrecisebankKeeper() precisebankkeeper.Keeper { return tApp.precisebankKeeper }
+func (tApp TestApp) GetWrappedA0GIBaseKeeper() wrappeda0gibasekeeper.Keeper {
+	return tApp.wrappeda0gibaseKeeper
+}
 
 func (tApp TestApp) GetKVStoreKey(key string) *storetypes.KVStoreKey {
 	return tApp.keys[key]
diff --git a/x/wrapped-a0gi-base/cli/query.go b/x/wrapped-a0gi-base/cli/query.go
index 52e4eaca..c693ab23 100644
--- a/x/wrapped-a0gi-base/cli/query.go
+++ b/x/wrapped-a0gi-base/cli/query.go
@@ -11,7 +11,7 @@ import (
 func GetQueryCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:                        types.ModuleName,
-		Short:                      "Querying commands for the dasigners module",
+		Short:                      "Querying commands for the wrapped a0gi base module",
 		DisableFlagParsing:         true,
 		SuggestionsMinimumDistance: 2,
 		RunE:                       client.ValidateCmd,
diff --git a/x/wrapped-a0gi-base/genesis_test.go b/x/wrapped-a0gi-base/genesis_test.go
new file mode 100644
index 00000000..831efd82
--- /dev/null
+++ b/x/wrapped-a0gi-base/genesis_test.go
@@ -0,0 +1,67 @@
+package wrappeda0gibase_test
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/suite"
+
+	tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
+
+	"github.com/0glabs/0g-chain/app"
+	wrappeda0gibase "github.com/0glabs/0g-chain/x/wrapped-a0gi-base"
+	"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/testutil"
+	"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types"
+)
+
+type GenesisTestSuite struct {
+	testutil.Suite
+}
+
+func (suite *GenesisTestSuite) TestInitGenesis() {
+	// Most genesis validation tests are located in the types directory. The 'invalid' test cases are
+	// randomly selected subset of those tests.
+	testCases := []struct {
+		name       string
+		genState   *types.GenesisState
+		expectPass bool
+	}{
+		{
+			name:       "default genesis",
+			genState:   types.DefaultGenesisState(),
+			expectPass: true,
+		},
+	}
+	for _, tc := range testCases {
+		suite.Run(tc.name, func() {
+			// Setup (note: suite.SetupTest is not run before every suite.Run)
+			suite.App = app.NewTestApp()
+			suite.Keeper = suite.App.GetWrappedA0GIBaseKeeper()
+			suite.Ctx = suite.App.NewContext(true, tmproto.Header{})
+
+			// Run
+			var exportedGenState *types.GenesisState
+			run := func() {
+				wrappeda0gibase.InitGenesis(suite.Ctx, suite.Keeper, *tc.genState)
+				exportedGenState = wrappeda0gibase.ExportGenesis(suite.Ctx, suite.Keeper)
+			}
+			if tc.expectPass {
+				suite.Require().NotPanics(run)
+			} else {
+				suite.Require().Panics(run)
+			}
+
+			// Check
+			if tc.expectPass {
+				expectedJson, err := suite.App.AppCodec().MarshalJSON(tc.genState)
+				suite.Require().NoError(err)
+				actualJson, err := suite.App.AppCodec().MarshalJSON(exportedGenState)
+				suite.Require().NoError(err)
+				suite.Equal(expectedJson, actualJson)
+			}
+		})
+	}
+}
+
+func TestGenesisTestSuite(t *testing.T) {
+	suite.Run(t, new(GenesisTestSuite))
+}
diff --git a/x/wrapped-a0gi-base/keeper/keeper_test.go b/x/wrapped-a0gi-base/keeper/keeper_test.go
new file mode 100644
index 00000000..b045109f
--- /dev/null
+++ b/x/wrapped-a0gi-base/keeper/keeper_test.go
@@ -0,0 +1,40 @@
+package keeper_test
+
+import (
+	"testing"
+
+	"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/testutil"
+	"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types"
+	"github.com/ethereum/go-ethereum/common"
+	"github.com/stretchr/testify/suite"
+)
+
+type KeeperTestSuite struct {
+	testutil.Suite
+}
+
+func (s *KeeperTestSuite) TestSetWA0GIAddress() {
+	testCases := []struct {
+		name  string
+		wa0gi common.Address
+	}{
+		{
+			name:  "zero address",
+			wa0gi: common.HexToAddress("0x0000000000000000000000000000000000000000"),
+		},
+	}
+	for _, tc := range testCases {
+		s.Run(tc.name, func() {
+			s.SetupTest()
+
+			s.Keeper.SetWA0GIAddress(s.Ctx, tc.wa0gi)
+			response, err := s.Keeper.GetWA0GI(s.Ctx, &types.GetWA0GIRequest{})
+			s.Require().NoError(err)
+			s.Require().Equal(common.BytesToAddress(response.Address), tc.wa0gi)
+		})
+	}
+}
+
+func TestKeeperSuite(t *testing.T) {
+	suite.Run(t, new(KeeperTestSuite))
+}
diff --git a/x/wrapped-a0gi-base/keeper/msg_server.go b/x/wrapped-a0gi-base/keeper/msg_server.go
index 0d47034c..f3de20dd 100644
--- a/x/wrapped-a0gi-base/keeper/msg_server.go
+++ b/x/wrapped-a0gi-base/keeper/msg_server.go
@@ -18,10 +18,6 @@ var _ types.MsgServer = &Keeper{}
 func (k Keeper) Burn(goCtx context.Context, msg *types.MsgBurn) (*types.MsgBurnResponse, error) {
 	ctx := sdk.UnwrapSDKContext(goCtx)
 	minter := common.BytesToAddress(msg.Minter)
-	cap, err := k.getMinterCap(ctx, minter)
-	if err != nil {
-		return nil, err
-	}
 	supply, err := k.getMinterSupply(ctx, minter)
 	if err != nil {
 		return nil, err
@@ -29,17 +25,17 @@ func (k Keeper) Burn(goCtx context.Context, msg *types.MsgBurn) (*types.MsgBurnR
 	amount := new(big.Int).SetBytes(msg.Amount)
 	// check & update mint supply
 	supply.Sub(supply, amount)
-	if supply.Cmp(cap) > 0 {
-		return nil, types.ErrInsufficientMintCap
-	}
-	if err = k.setMinterSupply(ctx, minter, supply); err != nil {
-		return nil, err
+	if supply.Cmp(big.NewInt(0)) < 0 {
+		return nil, types.ErrInsufficientMintSupply
 	}
 	// burn
 	c := sdk.NewCoin(precisebanktypes.ExtendedCoinDenom, sdk.NewIntFromBigInt(amount))
 	if err = k.pbkeeper.BurnCoins(ctx, types.ModuleName, sdk.NewCoins(c)); err != nil {
 		return nil, err
 	}
+	if err = k.setMinterSupply(ctx, minter, supply); err != nil {
+		return nil, err
+	}
 	return &types.MsgBurnResponse{}, nil
 }
 
@@ -61,14 +57,14 @@ func (k Keeper) Mint(goCtx context.Context, msg *types.MsgMint) (*types.MsgMintR
 	if supply.Cmp(cap) > 0 {
 		return nil, types.ErrInsufficientMintCap
 	}
-	if err = k.setMinterSupply(ctx, minter, supply); err != nil {
-		return nil, err
-	}
 	// mint
 	c := sdk.NewCoin(precisebanktypes.ExtendedCoinDenom, sdk.NewIntFromBigInt(amount))
 	if err = k.pbkeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins(c)); err != nil {
 		return nil, err
 	}
+	if err = k.setMinterSupply(ctx, minter, supply); err != nil {
+		return nil, err
+	}
 	return &types.MsgMintResponse{}, nil
 }
 
diff --git a/x/wrapped-a0gi-base/keeper/msg_server_test.go b/x/wrapped-a0gi-base/keeper/msg_server_test.go
new file mode 100644
index 00000000..8c54cd3f
--- /dev/null
+++ b/x/wrapped-a0gi-base/keeper/msg_server_test.go
@@ -0,0 +1,284 @@
+package keeper_test
+
+import (
+	"fmt"
+	"math/big"
+	"testing"
+
+	precisebanktypes "github.com/0glabs/0g-chain/x/precisebank/types"
+	"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/testutil"
+	"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types"
+	sdk "github.com/cosmos/cosmos-sdk/types"
+	"github.com/ethereum/go-ethereum/common"
+	"github.com/stretchr/testify/suite"
+)
+
+type MsgServerTestSuite struct {
+	testutil.Suite
+}
+
+func (s *MsgServerTestSuite) TestSetWA0GI() {
+	govAccAddr := s.GovKeeper.GetGovernanceAccount(s.Ctx).GetAddress().String()
+	testCases := []struct {
+		name      string
+		req       *types.MsgSetWA0GI
+		expectErr bool
+		errMsg    string
+	}{
+		{
+			name: "invalid signer",
+			req: &types.MsgSetWA0GI{
+				Authority: s.Addresses[0].String(),
+				Address:   common.HexToAddress("0x0000000000000000000000000000000000000001").Bytes(),
+			},
+			expectErr: true,
+			errMsg:    "expected gov account as only signer for proposal message",
+		},
+		{
+			name: "success",
+			req: &types.MsgSetWA0GI{
+				Authority: govAccAddr,
+				Address:   common.HexToAddress("0x0000000000000000000000000000000000000001").Bytes(),
+			},
+			expectErr: false,
+		},
+	}
+	for _, tc := range testCases {
+		s.Run(tc.name, func() {
+			_, err := s.Keeper.SetWA0GI(sdk.WrapSDKContext(s.Ctx), tc.req)
+			if tc.expectErr {
+				s.Require().Error(err)
+				s.Require().Contains(err.Error(), tc.errMsg)
+			} else {
+				s.Require().NoError(err)
+				response, err := s.Keeper.GetWA0GI(s.Ctx, &types.GetWA0GIRequest{})
+				s.Require().NoError(err)
+				s.Require().Equal(response.Address, tc.req.Address)
+			}
+		})
+	}
+}
+
+func (s *MsgServerTestSuite) TestSetMinterCap() {
+	testCases := []struct {
+		name string
+		caps []struct {
+			account common.Address
+			cap     *big.Int
+		}
+	}{
+		{
+			name: "success",
+			caps: []struct {
+				account common.Address
+				cap     *big.Int
+			}{
+				{
+					account: common.HexToAddress("0x0000000000000000000000000000000000000000"),
+					cap:     big.NewInt(100000),
+				},
+				{
+					account: common.HexToAddress("0x0000000000000000000000000000000000000001"),
+					cap:     big.NewInt(200000),
+				},
+				{
+					account: common.HexToAddress("0x0000000000000000000000000000000000000002"),
+					cap:     big.NewInt(300000),
+				},
+				{
+					account: common.HexToAddress("0x0000000000000000000000000000000000000003"),
+					cap:     big.NewInt(400000),
+				},
+				{
+					account: common.HexToAddress("0x0000000000000000000000000000000000000002"),
+					cap:     big.NewInt(500000),
+				},
+				{
+					account: common.HexToAddress("0x0000000000000000000000000000000000000001"),
+					cap:     big.NewInt(600000),
+				},
+				{
+					account: common.HexToAddress("0x0000000000000000000000000000000000000000"),
+					cap:     big.NewInt(700000),
+				},
+			},
+		},
+	}
+	s.Run("invalid authority", func() {
+		s.SetupTest()
+		_, err := s.Keeper.SetMinterCap(sdk.WrapSDKContext(s.Ctx), &types.MsgSetMintCap{
+			Authority: s.Addresses[0].String(),
+			Minter:    common.HexToAddress("0x0000000000000000000000000000000000000000").Bytes(),
+			Cap:       big.NewInt(600000).Bytes(),
+		})
+		s.Require().Error(err)
+		s.Require().Contains(err.Error(), "expected gov account as only signer for proposal message")
+	})
+	govAccAddr := s.GovKeeper.GetGovernanceAccount(s.Ctx).GetAddress().String()
+	for _, tc := range testCases {
+		s.Run(tc.name, func() {
+			s.SetupTest()
+
+			c := make(map[common.Address]*big.Int)
+			for _, cap := range tc.caps {
+				_, err := s.Keeper.SetMinterCap(sdk.WrapSDKContext(s.Ctx), &types.MsgSetMintCap{
+					Authority: govAccAddr,
+					Minter:    cap.account.Bytes(),
+					Cap:       cap.cap.Bytes(),
+				})
+				s.Require().NoError(err)
+				response, err := s.Keeper.MinterSupply(s.Ctx, &types.MinterSupplyRequest{
+					Address: cap.account.Bytes(),
+				})
+				s.Require().NoError(err)
+				s.Require().Equal(new(big.Int).SetBytes(response.Cap), cap.cap)
+				c[cap.account] = cap.cap
+			}
+			for account, cap := range c {
+				response, err := s.Keeper.MinterSupply(s.Ctx, &types.MinterSupplyRequest{
+					Address: account.Bytes(),
+				})
+				s.Require().NoError(err)
+				s.Require().Equal(new(big.Int).SetBytes(response.Cap), cap)
+			}
+		})
+	}
+}
+
+type MintBurn struct {
+	IsMint  bool
+	Minter  common.Address
+	Amount  *big.Int
+	Success bool
+}
+
+func (s *MsgServerTestSuite) TestSetMintBurn() {
+	precisebankKeeper := s.App.GetPrecisebankKeeper()
+	accountKeeper := s.App.GetAccountKeeper()
+	moduleAcc := accountKeeper.GetModuleAccount(s.Ctx, types.ModuleName).GetAddress()
+	govAccAddr := s.GovKeeper.GetGovernanceAccount(s.Ctx).GetAddress().String()
+
+	minter1 := common.HexToAddress("0x0000000000000000000000000000000000000001")
+	minter2 := common.HexToAddress("0x0000000000000000000000000000000000000002")
+
+	// set mint cap of minter 1 to 8 a0gi
+	_, err := s.Keeper.SetMinterCap(sdk.WrapSDKContext(s.Ctx), &types.MsgSetMintCap{
+		Authority: govAccAddr,
+		Minter:    minter1.Bytes(),
+		Cap:       big.NewInt(8e18).Bytes(),
+	})
+	s.Require().NoError(err)
+	// set mint cap of minter 2 to 5 a0gi
+	_, err = s.Keeper.SetMinterCap(sdk.WrapSDKContext(s.Ctx), &types.MsgSetMintCap{
+		Authority: govAccAddr,
+		Minter:    minter2.Bytes(),
+		Cap:       big.NewInt(5e18).Bytes(),
+	})
+	s.Require().NoError(err)
+
+	testCases := []MintBurn{
+		// #0, failed burn
+		{
+			IsMint:  false,
+			Minter:  minter1,
+			Amount:  big.NewInt(1e18),
+			Success: false,
+		},
+		// #1, mint 5 a0gi by minter 1
+		{
+			IsMint:  true,
+			Minter:  minter1,
+			Amount:  big.NewInt(5e18),
+			Success: true,
+		},
+		// #2, burn 0.5 a0gi by minter 1
+		{
+			IsMint:  false,
+			Minter:  minter1,
+			Amount:  big.NewInt(5e17),
+			Success: true,
+		},
+		// #3, mint 0.7 a0gi by minter 2
+		{
+			IsMint:  true,
+			Minter:  minter2,
+			Amount:  big.NewInt(7e17),
+			Success: true,
+		},
+		// #4, mint 2 a0gi by minter 2
+		{
+			IsMint:  true,
+			Minter:  minter2,
+			Amount:  big.NewInt(2e18),
+			Success: true,
+		},
+		// #5, burn 0.3 a0gi by minter 2
+		{
+			IsMint:  false,
+			Minter:  minter1,
+			Amount:  big.NewInt(3e17),
+			Success: true,
+		},
+		// #6, failed to mint 4 a0gi by minter 1
+		{
+			IsMint:  true,
+			Minter:  minter1,
+			Amount:  big.NewInt(4e18),
+			Success: false,
+		},
+		// #7, mint 3.5 a0gi by minter 1
+		{
+			IsMint:  true,
+			Minter:  minter1,
+			Amount:  big.NewInt(3e18 + 5e17),
+			Success: true,
+		},
+	}
+	minted := big.NewInt(0)
+	supplied := make(map[common.Address]*big.Int)
+	for id, c := range testCases {
+		fmt.Println(id)
+		if c.IsMint {
+			_, err = s.Keeper.Mint(sdk.WrapSDKContext(s.Ctx), &types.MsgMint{
+				Minter: c.Minter.Bytes(),
+				Amount: c.Amount.Bytes(),
+			})
+		} else {
+			_, err = s.Keeper.Burn(sdk.WrapSDKContext(s.Ctx), &types.MsgBurn{
+				Minter: c.Minter.Bytes(),
+				Amount: c.Amount.Bytes(),
+			})
+		}
+		if c.Success {
+			if c.IsMint {
+				minted.Add(minted, c.Amount)
+				if amt, ok := supplied[c.Minter]; ok {
+					amt.Add(amt, c.Amount)
+				} else {
+					supplied[c.Minter] = new(big.Int).Set(c.Amount)
+				}
+			} else {
+				minted.Sub(minted, c.Amount)
+				if amt, ok := supplied[c.Minter]; ok {
+					amt.Sub(amt, c.Amount)
+				} else {
+					supplied[c.Minter] = new(big.Int).Set(c.Amount)
+				}
+			}
+			s.Require().NoError(err)
+			response, err := s.Keeper.MinterSupply(s.Ctx, &types.MinterSupplyRequest{
+				Address: c.Minter.Bytes(),
+			})
+			s.Require().NoError(err)
+			s.Require().Equal(supplied[c.Minter].Bytes(), response.Supply)
+		} else {
+			s.Require().Error(err)
+		}
+		coins := precisebankKeeper.GetBalance(s.Ctx, moduleAcc, precisebanktypes.ExtendedCoinDenom)
+		s.Require().Equal(coins.Amount.BigInt(), minted)
+	}
+}
+
+func TestMsgServerSuite(t *testing.T) {
+	suite.Run(t, new(MsgServerTestSuite))
+}
diff --git a/x/wrapped-a0gi-base/testutil/suite.go b/x/wrapped-a0gi-base/testutil/suite.go
new file mode 100644
index 00000000..071d87de
--- /dev/null
+++ b/x/wrapped-a0gi-base/testutil/suite.go
@@ -0,0 +1,66 @@
+package testutil
+
+import (
+	"strings"
+
+	tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
+	sdk "github.com/cosmos/cosmos-sdk/types"
+	stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
+	"github.com/ethereum/go-ethereum/crypto"
+	"github.com/stretchr/testify/suite"
+
+	"github.com/0glabs/0g-chain/app"
+	"github.com/0glabs/0g-chain/chaincfg"
+	"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/keeper"
+	"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types"
+	govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
+	stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
+	"github.com/evmos/ethermint/crypto/ethsecp256k1"
+)
+
+// Suite implements a test suite for the module integration tests
+type Suite struct {
+	suite.Suite
+
+	Keeper        keeper.Keeper
+	StakingKeeper *stakingkeeper.Keeper
+	GovKeeper     govkeeper.Keeper
+	App           app.TestApp
+	Ctx           sdk.Context
+	QueryClient   types.QueryClient
+	Addresses     []sdk.AccAddress
+}
+
+// SetupTest instantiates a new app, keepers, and sets suite state
+func (suite *Suite) SetupTest() {
+	chaincfg.SetSDKConfig()
+	suite.App = app.NewTestApp()
+	suite.App.InitializeFromGenesisStates()
+	suite.Keeper = suite.App.GetWrappedA0GIBaseKeeper()
+	suite.GovKeeper = suite.App.GetGovKeeper()
+	suite.StakingKeeper = suite.App.GetStakingKeeper()
+
+	// make block header
+	privkey, _ := ethsecp256k1.GenerateKey()
+	consAddress := sdk.ConsAddress(privkey.PubKey().Address())
+	key, err := privkey.ToECDSA()
+	suite.Assert().NoError(err)
+	hexAddr := strings.ToLower(crypto.PubkeyToAddress(key.PublicKey).Hex()[2:])
+	valAddr, err := sdk.ValAddressFromHex(hexAddr)
+	suite.Assert().NoError(err)
+	suite.Ctx = suite.App.NewContext(true, tmproto.Header{Height: 1, ChainID: app.TestChainId, ProposerAddress: consAddress})
+	newValidator, err := stakingtypes.NewValidator(valAddr, privkey.PubKey(), stakingtypes.Description{})
+	suite.Assert().NoError(err)
+	err = suite.StakingKeeper.SetValidatorByConsAddr(suite.Ctx, newValidator)
+	suite.Assert().NoError(err)
+	suite.StakingKeeper.SetValidator(suite.Ctx, newValidator)
+
+	_, accAddresses := app.GeneratePrivKeyAddressPairs(10)
+	suite.Addresses = accAddresses
+
+	// Set query client
+	queryHelper := suite.App.NewQueryServerTestHelper(suite.Ctx)
+	queryHandler := suite.Keeper
+	types.RegisterQueryServer(queryHelper, queryHandler)
+	suite.QueryClient = types.NewQueryClient(queryHelper)
+}
diff --git a/x/wrapped-a0gi-base/testutil/types.go b/x/wrapped-a0gi-base/testutil/types.go
new file mode 100644
index 00000000..1ae3828c
--- /dev/null
+++ b/x/wrapped-a0gi-base/testutil/types.go
@@ -0,0 +1,25 @@
+package testutil
+
+import (
+	"testing"
+
+	sdkmath "cosmossdk.io/math"
+	"github.com/cosmos/cosmos-sdk/codec"
+	sdk "github.com/cosmos/cosmos-sdk/types"
+	"github.com/gogo/protobuf/proto"
+	"github.com/stretchr/testify/assert"
+)
+
+// Avoid cluttering test cases with long function names
+func I(in int64) sdkmath.Int                { return sdkmath.NewInt(in) }
+func D(str string) sdk.Dec                  { return sdk.MustNewDecFromStr(str) }
+func C(denom string, amount int64) sdk.Coin { return sdk.NewInt64Coin(denom, amount) }
+func Cs(coins ...sdk.Coin) sdk.Coins        { return sdk.NewCoins(coins...) }
+
+func AssertProtoMessageJSON(t *testing.T, cdc codec.Codec, expected proto.Message, actual proto.Message) {
+	expectedJson, err := cdc.MarshalJSON(expected)
+	assert.NoError(t, err)
+	actualJson, err := cdc.MarshalJSON(actual)
+	assert.NoError(t, err)
+	assert.Equal(t, string(expectedJson), string(actualJson))
+}
diff --git a/x/wrapped-a0gi-base/types/errors.go b/x/wrapped-a0gi-base/types/errors.go
index 7b38b98c..cd8bff0d 100644
--- a/x/wrapped-a0gi-base/types/errors.go
+++ b/x/wrapped-a0gi-base/types/errors.go
@@ -3,6 +3,7 @@ package types
 import errorsmod "cosmossdk.io/errors"
 
 var (
-	ErrTxForbidden         = errorsmod.Register(ModuleName, 1, "cosmos tx forbidden")
-	ErrInsufficientMintCap = errorsmod.Register(ModuleName, 2, "insufficient mint cap")
+	ErrTxForbidden            = errorsmod.Register(ModuleName, 1, "cosmos tx forbidden")
+	ErrInsufficientMintCap    = errorsmod.Register(ModuleName, 2, "insufficient mint cap")
+	ErrInsufficientMintSupply = errorsmod.Register(ModuleName, 3, "insufficient mint supply")
 )
diff --git a/x/wrapped-a0gi-base/types/genesis.go b/x/wrapped-a0gi-base/types/genesis.go
index 0b622117..d306dc5f 100644
--- a/x/wrapped-a0gi-base/types/genesis.go
+++ b/x/wrapped-a0gi-base/types/genesis.go
@@ -3,7 +3,16 @@ package types
 import "github.com/ethereum/go-ethereum/common"
 
 const (
-	DEFAULT_WRAPPED_A0GI = "0000000000000000000000000000000000000000"
+	// This is a Wrapped A0GI contract deployed by a raw transaction:
+	// raw tx params:
+	//	 from: 0x43db6cef54678f25310c0804bc1c1c2418f68e5b
+	//   nonce: 0
+	//	 gasPrice: 100 Gwei
+	//   gasLimit: 1000000
+	// The sender is an ephemeral account, nobody holds its private key and this is the only transaction it signed.
+	// This transaction is a legacy transaction without chain ID so it can be deployed at any EVM chain which supports pre-EIP155 transactions.
+	// raw tx: 0xf90c378085174876e800830f42408080b90be460c0604052600c60809081526b57726170706564204130474960a01b60a05260009061002b908261011c565b50604080518082019091526005815264574130474960d81b6020820152600190610055908261011c565b50600280546001600160a81b0319166210021217905534801561007757600080fd5b506101db565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806100a757607f821691505b6020821081036100c757634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561011757600081815260208120601f850160051c810160208610156100f45750805b601f850160051c820191505b8181101561011357828155600101610100565b5050505b505050565b81516001600160401b038111156101355761013561007d565b610149816101438454610093565b846100cd565b602080601f83116001811461017e57600084156101665750858301515b600019600386901b1c1916600185901b178555610113565b600085815260208120601f198616915b828110156101ad5788860151825594840194600190910190840161018e565b50858210156101cb5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6109f980620001eb6000396000f3fe6080604052600436106100e15760003560e01c806342966c681161007f57806395d89b411161005957806395d89b4114610283578063a9059cbb14610298578063d0e30db0146102b8578063dd62ed3e146102c057600080fd5b806342966c68146101f95780635001f3b51461021957806370a082311461025657600080fd5b806323b872dd116100bb57806323b872dd1461016d5780632e1a7d4d1461018d578063313ce567146101ad57806340c10f19146101d957600080fd5b806306fdde03146100f5578063095ea7b31461012057806318160ddd1461015057600080fd5b366100f0576100ee6102f8565b005b600080fd5b34801561010157600080fd5b5061010a610353565b6040516101179190610816565b60405180910390f35b34801561012c57600080fd5b5061014061013b366004610880565b6103e1565b6040519015158152602001610117565b34801561015c57600080fd5b50475b604051908152602001610117565b34801561017957600080fd5b506101406101883660046108aa565b61044e565b34801561019957600080fd5b506100ee6101a83660046108e6565b6105d2565b3480156101b957600080fd5b506002546101c79060ff1681565b60405160ff9091168152602001610117565b3480156101e557600080fd5b506100ee6101f4366004610880565b61065d565b34801561020557600080fd5b506100ee6102143660046108e6565b610736565b34801561022557600080fd5b5060025461023e9061010090046001600160a01b031681565b6040516001600160a01b039091168152602001610117565b34801561026257600080fd5b5061015f6102713660046108ff565b60036020526000908152604090205481565b34801561028f57600080fd5b5061010a6107f5565b3480156102a457600080fd5b506101406102b3366004610880565b610802565b6100ee6102f8565b3480156102cc57600080fd5b5061015f6102db36600461091a565b600460209081526000928352604080842090915290825290205481565b3360009081526003602052604081208054349290610317908490610963565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b6000805461036090610976565b80601f016020809104026020016040519081016040528092919081815260200182805461038c90610976565b80156103d95780601f106103ae576101008083540402835291602001916103d9565b820191906000526020600020905b8154815290600101906020018083116103bc57829003601f168201915b505050505081565b3360008181526004602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259061043c9086815260200190565b60405180910390a35060015b92915050565b6001600160a01b03831660009081526003602052604081205482111561047357600080fd5b6001600160a01b03841633148015906104b157506001600160a01b038416600090815260046020908152604080832033845290915290205460001914155b1561051f576001600160a01b03841660009081526004602090815260408083203384529091529020548211156104e657600080fd5b6001600160a01b0384166000908152600460209081526040808320338452909152812080548492906105199084906109b0565b90915550505b6001600160a01b038416600090815260036020526040812080548492906105479084906109b0565b90915550506001600160a01b03831660009081526003602052604081208054849290610574908490610963565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516105c091815260200190565b60405180910390a35060019392505050565b33600090815260036020526040812080548392906105f19084906109b0565b9091555050604051339082156108fc029083906000818181858888f19350505050158015610623573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65906020015b60405180910390a250565b6002546040516340c10f1960e01b8152336004820152602481018390526101009091046001600160a01b0316906340c10f1990604401600060405180830381600087803b1580156106ad57600080fd5b505af11580156106c1573d6000803e3d6000fd5b505050506001600160a01b038216600090815260036020526040812080548392906106ed908490610963565b90915550506040518181526001600160a01b0383169033907fab8530f87dc9b59234c4623bf917212bb2536d647574c8e7e5da92c2ede0c9f89060200160405180910390a35050565b600254604051632770a7eb60e21b8152336004820152602481018390526101009091046001600160a01b031690639dc29fac90604401600060405180830381600087803b15801561078657600080fd5b505af115801561079a573d6000803e3d6000fd5b505033600090815260036020526040812080548594509092506107be9084906109b0565b909155505060405181815233907fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca590602001610652565b6001805461036090610976565b600061080f33848461044e565b9392505050565b600060208083528351808285015260005b8181101561084357858101830151858201604001528201610827565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b038116811461087b57600080fd5b919050565b6000806040838503121561089357600080fd5b61089c83610864565b946020939093013593505050565b6000806000606084860312156108bf57600080fd5b6108c884610864565b92506108d660208501610864565b9150604084013590509250925092565b6000602082840312156108f857600080fd5b5035919050565b60006020828403121561091157600080fd5b61080f82610864565b6000806040838503121561092d57600080fd5b61093683610864565b915061094460208401610864565b90509250929050565b634e487b7160e01b600052601160045260246000fd5b808201808211156104485761044861094d565b600181811c9082168061098a57607f821691505b6020821081036109aa57634e487b7160e01b600052602260045260246000fd5b50919050565b818103818111156104485761044861094d56fea2646970667358221220076f43aa18ca3555e080ebb6815ba9bdfa3617ec5fad0223a8d6007ea588a6f364736f6c634300081400331ba07f6fb2afc9cb39989c4e35299f44266a2f800f009fdeb24914df0b51de47c85fa02acc21d7f401e1529a4fbd0b3cf888414a07494af162ddca5670a6fa181ebe07
+	DEFAULT_WRAPPED_A0GI = "0xCDf97Ac4453AD85C663d2555BF4424601e1f2A9F"
 )
 
 // NewGenesisState returns a new genesis state object for the module.