mirror of
https://github.com/0glabs/0g-chain.git
synced 2025-04-04 15:55:23 +00:00
Compare commits
16 Commits
82676e505f
...
281488a514
Author | SHA1 | Date | |
---|---|---|---|
![]() |
281488a514 | ||
![]() |
f04c87506b | ||
![]() |
65a4f9128b | ||
![]() |
0a79fe53a2 | ||
![]() |
aed6a6161a | ||
![]() |
75cccf2c8f | ||
![]() |
db1d6463ec | ||
![]() |
1a039a0d13 | ||
![]() |
6ed21ea3fb | ||
![]() |
8b43aa4064 | ||
![]() |
2500f6cb31 | ||
![]() |
88304562cc | ||
![]() |
58871957a8 | ||
![]() |
aff086bf7b | ||
![]() |
0ff16c798a | ||
![]() |
e2668ad80d |
338
app/abci_utils.go
Normal file
338
app/abci_utils.go
Normal file
@ -0,0 +1,338 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
gethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/mempool"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
)
|
||||
|
||||
type (
|
||||
// GasTx defines the contract that a transaction with a gas limit must implement.
|
||||
GasTx interface {
|
||||
GetGas() uint64
|
||||
}
|
||||
|
||||
// ProposalTxVerifier defines the interface that is implemented by BaseApp,
|
||||
// that any custom ABCI PrepareProposal and ProcessProposal handler can use
|
||||
// to verify a transaction.
|
||||
ProposalTxVerifier interface {
|
||||
PrepareProposalVerifyTx(tx sdk.Tx) ([]byte, error)
|
||||
ProcessProposalVerifyTx(txBz []byte) (sdk.Tx, error)
|
||||
}
|
||||
|
||||
// DefaultProposalHandler defines the default ABCI PrepareProposal and
|
||||
// ProcessProposal handlers.
|
||||
DefaultProposalHandler struct {
|
||||
mempool mempool.Mempool
|
||||
txVerifier ProposalTxVerifier
|
||||
txSelector TxSelector
|
||||
}
|
||||
)
|
||||
|
||||
func NewDefaultProposalHandler(mp mempool.Mempool, txVerifier ProposalTxVerifier) *DefaultProposalHandler {
|
||||
return &DefaultProposalHandler{
|
||||
mempool: mp,
|
||||
txVerifier: txVerifier,
|
||||
txSelector: NewDefaultTxSelector(),
|
||||
}
|
||||
}
|
||||
|
||||
// SetTxSelector sets the TxSelector function on the DefaultProposalHandler.
|
||||
func (h *DefaultProposalHandler) SetTxSelector(ts TxSelector) {
|
||||
h.txSelector = ts
|
||||
}
|
||||
|
||||
// PrepareProposalHandler returns the default implementation for processing an
|
||||
// ABCI proposal. The application's mempool is enumerated and all valid
|
||||
// transactions are added to the proposal. Transactions are valid if they:
|
||||
//
|
||||
// 1) Successfully encode to bytes.
|
||||
// 2) Are valid (i.e. pass runTx, AnteHandler only).
|
||||
//
|
||||
// Enumeration is halted once RequestPrepareProposal.MaxBytes of transactions is
|
||||
// reached or the mempool is exhausted.
|
||||
//
|
||||
// Note:
|
||||
//
|
||||
// - Step (2) is identical to the validation step performed in
|
||||
// DefaultProcessProposal. It is very important that the same validation logic
|
||||
// is used in both steps, and applications must ensure that this is the case in
|
||||
// non-default handlers.
|
||||
//
|
||||
// - If no mempool is set or if the mempool is a no-op mempool, the transactions
|
||||
// requested from CometBFT will simply be returned, which, by default, are in
|
||||
// FIFO order.
|
||||
func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler {
|
||||
return func(ctx sdk.Context, req abci.RequestPrepareProposal) abci.ResponsePrepareProposal {
|
||||
var maxBlockGas uint64
|
||||
if b := ctx.ConsensusParams().Block; b != nil {
|
||||
maxBlockGas = uint64(b.MaxGas)
|
||||
}
|
||||
|
||||
defer h.txSelector.Clear()
|
||||
|
||||
// If the mempool is nil or NoOp we simply return the transactions
|
||||
// requested from CometBFT, which, by default, should be in FIFO order.
|
||||
//
|
||||
// Note, we still need to ensure the transactions returned respect req.MaxTxBytes.
|
||||
_, isNoOp := h.mempool.(mempool.NoOpMempool)
|
||||
if h.mempool == nil || isNoOp {
|
||||
for _, txBz := range req.Txs {
|
||||
// XXX: We pass nil as the memTx because we have no way of decoding the
|
||||
// txBz. We'd need to break (update) the ProposalTxVerifier interface.
|
||||
// As a result, we CANNOT account for block max gas.
|
||||
stop := h.txSelector.SelectTxForProposal(uint64(req.MaxTxBytes), maxBlockGas, nil, txBz)
|
||||
if stop {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return abci.ResponsePrepareProposal{Txs: h.txSelector.SelectedTxs()}
|
||||
}
|
||||
|
||||
iterator := h.mempool.Select(ctx, req.Txs)
|
||||
selectedTxsSignersSeqs := make(map[string]uint64)
|
||||
var selectedTxsNums int
|
||||
for iterator != nil {
|
||||
memTx := iterator.Tx()
|
||||
sigs, err := memTx.(signing.SigVerifiableTx).GetSignaturesV2()
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to get signatures: %w", err))
|
||||
}
|
||||
// If the signers aren't in selectedTxsSignersSeqs then we haven't seen them before
|
||||
// so we add them and continue given that we don't need to check the sequence.
|
||||
shouldAdd := true
|
||||
txSignersSeqs := make(map[string]uint64)
|
||||
if len(sigs) == 0 {
|
||||
msgs := memTx.GetMsgs()
|
||||
if len(msgs) == 1 {
|
||||
msgEthTx, ok := msgs[0].(*evmtypes.MsgEthereumTx)
|
||||
if ok {
|
||||
ethTx := msgEthTx.AsTransaction()
|
||||
signer := gethtypes.NewEIP2930Signer(ethTx.ChainId())
|
||||
ethSender, err := signer.Sender(ethTx)
|
||||
if err == nil {
|
||||
signer := sdk.AccAddress(ethSender.Bytes()).String()
|
||||
nonce := ethTx.Nonce()
|
||||
seq, ok := selectedTxsSignersSeqs[signer]
|
||||
if !ok {
|
||||
txSignersSeqs[signer] = nonce
|
||||
} else {
|
||||
// If we have seen this signer before in this block, we must make
|
||||
// sure that the current sequence is seq+1; otherwise is invalid
|
||||
// and we skip it.
|
||||
if seq+1 != nonce {
|
||||
shouldAdd = false
|
||||
} else {
|
||||
txSignersSeqs[signer] = nonce
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, sig := range sigs {
|
||||
signer := sdk.AccAddress(sig.PubKey.Address()).String()
|
||||
seq, ok := selectedTxsSignersSeqs[signer]
|
||||
if !ok {
|
||||
txSignersSeqs[signer] = sig.Sequence
|
||||
continue
|
||||
}
|
||||
|
||||
// If we have seen this signer before in this block, we must make
|
||||
// sure that the current sequence is seq+1; otherwise is invalid
|
||||
// and we skip it.
|
||||
if seq+1 != sig.Sequence {
|
||||
shouldAdd = false
|
||||
break
|
||||
}
|
||||
txSignersSeqs[signer] = sig.Sequence
|
||||
}
|
||||
}
|
||||
|
||||
if !shouldAdd {
|
||||
iterator = iterator.Next()
|
||||
continue
|
||||
}
|
||||
|
||||
// NOTE: Since transaction verification was already executed in CheckTx,
|
||||
// which calls mempool.Insert, in theory everything in the pool should be
|
||||
// valid. But some mempool implementations may insert invalid txs, so we
|
||||
// check again.
|
||||
txBz, err := h.txVerifier.PrepareProposalVerifyTx(memTx)
|
||||
if err != nil {
|
||||
err := h.mempool.Remove(memTx)
|
||||
if err != nil && !errors.Is(err, mempool.ErrTxNotFound) {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
stop := h.txSelector.SelectTxForProposal(uint64(req.MaxTxBytes), maxBlockGas, memTx, txBz)
|
||||
if stop {
|
||||
break
|
||||
}
|
||||
|
||||
txsLen := len(h.txSelector.SelectedTxs())
|
||||
for sender, seq := range txSignersSeqs {
|
||||
// If txsLen != selectedTxsNums is true, it means that we've
|
||||
// added a new tx to the selected txs, so we need to update
|
||||
// the sequence of the sender.
|
||||
if txsLen != selectedTxsNums {
|
||||
selectedTxsSignersSeqs[sender] = seq
|
||||
} else if _, ok := selectedTxsSignersSeqs[sender]; !ok {
|
||||
// The transaction hasn't been added but it passed the
|
||||
// verification, so we know that the sequence is correct.
|
||||
// So we set this sender's sequence to seq-1, in order
|
||||
// to avoid unnecessary calls to PrepareProposalVerifyTx.
|
||||
selectedTxsSignersSeqs[sender] = seq - 1
|
||||
}
|
||||
}
|
||||
selectedTxsNums = txsLen
|
||||
}
|
||||
|
||||
iterator = iterator.Next()
|
||||
}
|
||||
return abci.ResponsePrepareProposal{Txs: h.txSelector.SelectedTxs()}
|
||||
}
|
||||
}
|
||||
|
||||
// ProcessProposalHandler returns the default implementation for processing an
|
||||
// ABCI proposal. Every transaction in the proposal must pass 2 conditions:
|
||||
//
|
||||
// 1. The transaction bytes must decode to a valid transaction.
|
||||
// 2. The transaction must be valid (i.e. pass runTx, AnteHandler only)
|
||||
//
|
||||
// If any transaction fails to pass either condition, the proposal is rejected.
|
||||
// Note that step (2) is identical to the validation step performed in
|
||||
// DefaultPrepareProposal. It is very important that the same validation logic
|
||||
// is used in both steps, and applications must ensure that this is the case in
|
||||
// non-default handlers.
|
||||
func (h *DefaultProposalHandler) ProcessProposalHandler() sdk.ProcessProposalHandler {
|
||||
// If the mempool is nil or NoOp we simply return ACCEPT,
|
||||
// because PrepareProposal may have included txs that could fail verification.
|
||||
_, isNoOp := h.mempool.(mempool.NoOpMempool)
|
||||
if h.mempool == nil || isNoOp {
|
||||
return NoOpProcessProposal()
|
||||
}
|
||||
|
||||
return func(ctx sdk.Context, req abci.RequestProcessProposal) abci.ResponseProcessProposal {
|
||||
var totalTxGas uint64
|
||||
|
||||
var maxBlockGas int64
|
||||
if b := ctx.ConsensusParams().Block; b != nil {
|
||||
maxBlockGas = b.MaxGas
|
||||
}
|
||||
|
||||
for _, txBytes := range req.Txs {
|
||||
tx, err := h.txVerifier.ProcessProposalVerifyTx(txBytes)
|
||||
if err != nil {
|
||||
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}
|
||||
}
|
||||
|
||||
if maxBlockGas > 0 {
|
||||
gasTx, ok := tx.(GasTx)
|
||||
if ok {
|
||||
totalTxGas += gasTx.GetGas()
|
||||
}
|
||||
|
||||
if totalTxGas > uint64(maxBlockGas) {
|
||||
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}
|
||||
}
|
||||
}
|
||||
|
||||
// NoOpPrepareProposal defines a no-op PrepareProposal handler. It will always
|
||||
// return the transactions sent by the client's request.
|
||||
func NoOpPrepareProposal() sdk.PrepareProposalHandler {
|
||||
return func(_ sdk.Context, req abci.RequestPrepareProposal) abci.ResponsePrepareProposal {
|
||||
return abci.ResponsePrepareProposal{Txs: req.Txs}
|
||||
}
|
||||
}
|
||||
|
||||
// NoOpProcessProposal defines a no-op ProcessProposal Handler. It will always
|
||||
// return ACCEPT.
|
||||
func NoOpProcessProposal() sdk.ProcessProposalHandler {
|
||||
return func(_ sdk.Context, _ abci.RequestProcessProposal) abci.ResponseProcessProposal {
|
||||
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}
|
||||
}
|
||||
}
|
||||
|
||||
// TxSelector defines a helper type that assists in selecting transactions during
|
||||
// mempool transaction selection in PrepareProposal. It keeps track of the total
|
||||
// number of bytes and total gas of the selected transactions. It also keeps
|
||||
// track of the selected transactions themselves.
|
||||
type TxSelector interface {
|
||||
// SelectedTxs should return a copy of the selected transactions.
|
||||
SelectedTxs() [][]byte
|
||||
|
||||
// Clear should clear the TxSelector, nulling out all relevant fields.
|
||||
Clear()
|
||||
|
||||
// SelectTxForProposal should attempt to select a transaction for inclusion in
|
||||
// a proposal based on inclusion criteria defined by the TxSelector. It must
|
||||
// return <true> if the caller should halt the transaction selection loop
|
||||
// (typically over a mempool) or <false> otherwise.
|
||||
SelectTxForProposal(maxTxBytes, maxBlockGas uint64, memTx sdk.Tx, txBz []byte) bool
|
||||
}
|
||||
|
||||
type defaultTxSelector struct {
|
||||
totalTxBytes uint64
|
||||
totalTxGas uint64
|
||||
selectedTxs [][]byte
|
||||
}
|
||||
|
||||
func NewDefaultTxSelector() TxSelector {
|
||||
return &defaultTxSelector{}
|
||||
}
|
||||
|
||||
func (ts *defaultTxSelector) SelectedTxs() [][]byte {
|
||||
txs := make([][]byte, len(ts.selectedTxs))
|
||||
copy(txs, ts.selectedTxs)
|
||||
return txs
|
||||
}
|
||||
|
||||
func (ts *defaultTxSelector) Clear() {
|
||||
ts.totalTxBytes = 0
|
||||
ts.totalTxGas = 0
|
||||
ts.selectedTxs = nil
|
||||
}
|
||||
|
||||
func (ts *defaultTxSelector) SelectTxForProposal(maxTxBytes, maxBlockGas uint64, memTx sdk.Tx, txBz []byte) bool {
|
||||
txSize := uint64(len(txBz))
|
||||
|
||||
var txGasLimit uint64
|
||||
if memTx != nil {
|
||||
if gasTx, ok := memTx.(GasTx); ok {
|
||||
txGasLimit = gasTx.GetGas()
|
||||
}
|
||||
}
|
||||
|
||||
// only add the transaction to the proposal if we have enough capacity
|
||||
if (txSize + ts.totalTxBytes) <= maxTxBytes {
|
||||
// If there is a max block gas limit, add the tx only if the limit has
|
||||
// not been met.
|
||||
if maxBlockGas > 0 {
|
||||
if (txGasLimit + ts.totalTxGas) <= maxBlockGas {
|
||||
ts.totalTxGas += txGasLimit
|
||||
ts.totalTxBytes += txSize
|
||||
ts.selectedTxs = append(ts.selectedTxs, txBz)
|
||||
}
|
||||
} else {
|
||||
ts.totalTxBytes += txSize
|
||||
ts.selectedTxs = append(ts.selectedTxs, txBz)
|
||||
}
|
||||
}
|
||||
|
||||
// check if we've reached capacity; if so, we cannot select any more transactions
|
||||
return ts.totalTxBytes >= maxTxBytes || (maxBlockGas > 0 && (ts.totalTxGas >= maxBlockGas))
|
||||
}
|
37
app/app.go
37
app/app.go
@ -111,6 +111,7 @@ import (
|
||||
"github.com/0glabs/0g-chain/chaincfg"
|
||||
dasignersprecompile "github.com/0glabs/0g-chain/precompiles/dasigners"
|
||||
stakingprecompile "github.com/0glabs/0g-chain/precompiles/staking"
|
||||
wrappeda0gibaseprecompile "github.com/0glabs/0g-chain/precompiles/wrapped-a0gi-base"
|
||||
|
||||
"github.com/0glabs/0g-chain/x/bep3"
|
||||
bep3keeper "github.com/0glabs/0g-chain/x/bep3/keeper"
|
||||
@ -140,6 +141,9 @@ import (
|
||||
validatorvesting "github.com/0glabs/0g-chain/x/validator-vesting"
|
||||
validatorvestingrest "github.com/0glabs/0g-chain/x/validator-vesting/client/rest"
|
||||
validatorvestingtypes "github.com/0glabs/0g-chain/x/validator-vesting/types"
|
||||
wrappeda0gibase "github.com/0glabs/0g-chain/x/wrapped-a0gi-base"
|
||||
wrappeda0gibasekeeper "github.com/0glabs/0g-chain/x/wrapped-a0gi-base/keeper"
|
||||
wrappeda0gibasetypes "github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
@ -187,6 +191,7 @@ var (
|
||||
dasigners.AppModuleBasic{},
|
||||
consensus.AppModuleBasic{},
|
||||
ibcwasm.AppModuleBasic{},
|
||||
wrappeda0gibase.AppModuleBasic{},
|
||||
)
|
||||
|
||||
// module account permissions
|
||||
@ -205,6 +210,7 @@ var (
|
||||
bep3types.ModuleName: {authtypes.Burner, authtypes.Minter},
|
||||
minttypes.ModuleName: {authtypes.Minter},
|
||||
precisebanktypes.ModuleName: {authtypes.Minter, authtypes.Burner}, // used for reserve account to back fractional amounts
|
||||
wrappeda0gibasetypes.ModuleName: {authtypes.Minter, authtypes.Burner},
|
||||
}
|
||||
)
|
||||
|
||||
@ -275,6 +281,7 @@ type App struct {
|
||||
dasignersKeeper dasignerskeeper.Keeper
|
||||
consensusParamsKeeper consensusparamkeeper.Keeper
|
||||
precisebankKeeper precisebankkeeper.Keeper
|
||||
wrappeda0gibaseKeeper wrappeda0gibasekeeper.Keeper
|
||||
|
||||
// make scoped keepers public for test purposes
|
||||
ScopedIBCKeeper capabilitykeeper.ScopedKeeper
|
||||
@ -293,21 +300,24 @@ type App struct {
|
||||
func init() {
|
||||
}
|
||||
|
||||
func NewBaseApp(logger tmlog.Logger, db dbm.DB, encodingConfig chainparams.EncodingConfig,
|
||||
baseAppOptions ...func(*baseapp.BaseApp)) *baseapp.BaseApp {
|
||||
bApp := baseapp.NewBaseApp(chaincfg.AppName, logger, db, encodingConfig.TxConfig.TxDecoder(), baseAppOptions...)
|
||||
return bApp
|
||||
}
|
||||
|
||||
// NewApp returns a reference to an initialized App.
|
||||
func NewApp(
|
||||
logger tmlog.Logger,
|
||||
db dbm.DB,
|
||||
homePath string,
|
||||
traceStore io.Writer,
|
||||
encodingConfig chainparams.EncodingConfig,
|
||||
options Options,
|
||||
baseAppOptions ...func(*baseapp.BaseApp),
|
||||
bApp *baseapp.BaseApp,
|
||||
) *App {
|
||||
appCodec := encodingConfig.Marshaler
|
||||
legacyAmino := encodingConfig.Amino
|
||||
interfaceRegistry := encodingConfig.InterfaceRegistry
|
||||
|
||||
bApp := baseapp.NewBaseApp(chaincfg.AppName, logger, db, encodingConfig.TxConfig.TxDecoder(), baseAppOptions...)
|
||||
bApp.SetCommitMultiStoreTracer(traceStore)
|
||||
bApp.SetVersion(version.Version)
|
||||
bApp.SetInterfaceRegistry(interfaceRegistry)
|
||||
@ -327,6 +337,7 @@ func NewApp(
|
||||
vestingtypes.StoreKey,
|
||||
consensusparamtypes.StoreKey, crisistypes.StoreKey, precisebanktypes.StoreKey,
|
||||
ibcwasmtypes.StoreKey,
|
||||
wrappeda0gibasetypes.StoreKey,
|
||||
)
|
||||
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey, evmtypes.TransientKey, feemarkettypes.TransientKey)
|
||||
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
|
||||
@ -368,7 +379,6 @@ func NewApp(
|
||||
feemarketSubspace := app.paramsKeeper.Subspace(feemarkettypes.ModuleName)
|
||||
evmSubspace := app.paramsKeeper.Subspace(evmtypes.ModuleName)
|
||||
evmutilSubspace := app.paramsKeeper.Subspace(evmutiltypes.ModuleName)
|
||||
mintSubspace := app.paramsKeeper.Subspace(minttypes.ModuleName)
|
||||
|
||||
// set the BaseApp's parameter store
|
||||
app.consensusParamsKeeper = consensusparamkeeper.NewKeeper(appCodec, keys[consensusparamtypes.StoreKey], govAuthAddrStr)
|
||||
@ -496,11 +506,10 @@ func NewApp(
|
||||
app.accountKeeper,
|
||||
)
|
||||
|
||||
// dasigners keeper
|
||||
app.dasignersKeeper = dasignerskeeper.NewKeeper(keys[dasignerstypes.StoreKey], appCodec, app.stakingKeeper, govAuthAddrStr)
|
||||
// precopmiles
|
||||
precompiles := make(map[common.Address]vm.PrecompiledContract)
|
||||
// dasigners
|
||||
app.dasignersKeeper = dasignerskeeper.NewKeeper(keys[dasignerstypes.StoreKey], appCodec, app.stakingKeeper, govAuthAddrStr)
|
||||
daSignersPrecompile, err := dasignersprecompile.NewDASignersPrecompile(app.dasignersKeeper)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("initialize dasigners precompile failed: %v", err))
|
||||
@ -512,6 +521,13 @@ func NewApp(
|
||||
panic(fmt.Sprintf("initialize staking precompile failed: %v", err))
|
||||
}
|
||||
precompiles[stakingPrecompile.Address()] = stakingPrecompile
|
||||
// wrapped wrapped a0gi base
|
||||
app.wrappeda0gibaseKeeper = wrappeda0gibasekeeper.NewKeeper(keys[wrappeda0gibasetypes.StoreKey], appCodec, app.precisebankKeeper, govAuthAddrStr)
|
||||
wrappeda0gibasePrecompile, err := wrappeda0gibaseprecompile.NewWrappedA0giBasePrecompile(app.wrappeda0gibaseKeeper)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("initialize wrapped a0gi base precompile failed: %v", err))
|
||||
}
|
||||
precompiles[wrappeda0gibasePrecompile.Address()] = wrappeda0gibasePrecompile
|
||||
|
||||
app.evmKeeper = evmkeeper.NewKeeper(
|
||||
appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey],
|
||||
@ -599,7 +615,6 @@ func NewApp(
|
||||
app.accountKeeper,
|
||||
app.bankKeeper,
|
||||
authtypes.FeeCollectorName,
|
||||
govAuthAddrStr,
|
||||
)
|
||||
|
||||
// create committee keeper with router
|
||||
@ -690,11 +705,12 @@ func NewApp(
|
||||
committee.NewAppModule(app.committeeKeeper, app.accountKeeper),
|
||||
evmutil.NewAppModule(app.evmutilKeeper, app.bankKeeper, app.accountKeeper),
|
||||
// nil InflationCalculationFn, use SDK's default inflation function
|
||||
mint.NewAppModule(appCodec, app.mintKeeper, app.accountKeeper, nil, mintSubspace),
|
||||
mint.NewAppModule(appCodec, app.mintKeeper, app.accountKeeper),
|
||||
precisebank.NewAppModule(app.precisebankKeeper, app.bankKeeper, app.accountKeeper),
|
||||
council.NewAppModule(app.CouncilKeeper),
|
||||
ibcwasm.NewAppModule(app.ibcWasmClientKeeper),
|
||||
dasigners.NewAppModule(app.dasignersKeeper, *app.stakingKeeper),
|
||||
wrappeda0gibase.NewAppModule(app.wrappeda0gibaseKeeper),
|
||||
)
|
||||
|
||||
// Warning: Some begin blockers must run before others. Ensure the dependencies are understood before modifying this list.
|
||||
@ -742,6 +758,7 @@ func NewApp(
|
||||
precisebanktypes.ModuleName,
|
||||
ibcwasmtypes.ModuleName,
|
||||
dasignerstypes.ModuleName,
|
||||
wrappeda0gibasetypes.ModuleName,
|
||||
)
|
||||
|
||||
// Warning: Some end blockers must run before others. Ensure the dependencies are understood before modifying this list.
|
||||
@ -779,6 +796,7 @@ func NewApp(
|
||||
precisebanktypes.ModuleName,
|
||||
ibcwasmtypes.ModuleName,
|
||||
dasignerstypes.ModuleName,
|
||||
wrappeda0gibasetypes.ModuleName,
|
||||
)
|
||||
|
||||
// Warning: Some init genesis methods must run before others. Ensure the dependencies are understood before modifying this list
|
||||
@ -815,6 +833,7 @@ func NewApp(
|
||||
crisistypes.ModuleName, // runs the invariants at genesis, should run after other modules
|
||||
ibcwasmtypes.ModuleName,
|
||||
dasignerstypes.ModuleName,
|
||||
wrappeda0gibasetypes.ModuleName,
|
||||
)
|
||||
|
||||
app.mm.RegisterInvariants(&app.crisisKeeper)
|
||||
|
488
app/priority_nonce.go
Normal file
488
app/priority_nonce.go
Normal file
@ -0,0 +1,488 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/huandu/skiplist"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/mempool"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
gethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
var (
|
||||
_ mempool.Mempool = (*PriorityNonceMempool)(nil)
|
||||
_ mempool.Iterator = (*PriorityNonceIterator)(nil)
|
||||
)
|
||||
|
||||
// PriorityNonceMempool is a mempool implementation that stores txs
|
||||
// in a partially ordered set by 2 dimensions: priority, and sender-nonce
|
||||
// (sequence number). Internally it uses one priority ordered skip list and one
|
||||
// skip list per sender ordered by sender-nonce (sequence number). When there
|
||||
// are multiple txs from the same sender, they are not always comparable by
|
||||
// priority to other sender txs and must be partially ordered by both sender-nonce
|
||||
// and priority.
|
||||
type PriorityNonceMempool struct {
|
||||
priorityIndex *skiplist.SkipList
|
||||
priorityCounts map[int64]int
|
||||
senderIndices map[string]*skiplist.SkipList
|
||||
scores map[txMeta]txMeta
|
||||
onRead func(tx sdk.Tx)
|
||||
txReplacement func(op, np int64, oTx, nTx sdk.Tx) bool
|
||||
maxTx int
|
||||
}
|
||||
|
||||
type PriorityNonceIterator struct {
|
||||
senderCursors map[string]*skiplist.Element
|
||||
nextPriority int64
|
||||
sender string
|
||||
priorityNode *skiplist.Element
|
||||
mempool *PriorityNonceMempool
|
||||
}
|
||||
|
||||
// txMeta stores transaction metadata used in indices
|
||||
type txMeta struct {
|
||||
// nonce is the sender's sequence number
|
||||
nonce uint64
|
||||
// priority is the transaction's priority
|
||||
priority int64
|
||||
// sender is the transaction's sender
|
||||
sender string
|
||||
// weight is the transaction's weight, used as a tiebreaker for transactions with the same priority
|
||||
weight int64
|
||||
// senderElement is a pointer to the transaction's element in the sender index
|
||||
senderElement *skiplist.Element
|
||||
}
|
||||
|
||||
// txMetaLess is a comparator for txKeys that first compares priority, then weight,
|
||||
// then sender, then nonce, uniquely identifying a transaction.
|
||||
//
|
||||
// Note, txMetaLess is used as the comparator in the priority index.
|
||||
func txMetaLess(a, b any) int {
|
||||
keyA := a.(txMeta)
|
||||
keyB := b.(txMeta)
|
||||
res := skiplist.Int64.Compare(keyA.priority, keyB.priority)
|
||||
if res != 0 {
|
||||
return res
|
||||
}
|
||||
|
||||
// Weight is used as a tiebreaker for transactions with the same priority.
|
||||
// Weight is calculated in a single pass in .Select(...) and so will be 0
|
||||
// on .Insert(...).
|
||||
res = skiplist.Int64.Compare(keyA.weight, keyB.weight)
|
||||
if res != 0 {
|
||||
return res
|
||||
}
|
||||
|
||||
// Because weight will be 0 on .Insert(...), we must also compare sender and
|
||||
// nonce to resolve priority collisions. If we didn't then transactions with
|
||||
// the same priority would overwrite each other in the priority index.
|
||||
res = skiplist.String.Compare(keyA.sender, keyB.sender)
|
||||
if res != 0 {
|
||||
return res
|
||||
}
|
||||
|
||||
return skiplist.Uint64.Compare(keyA.nonce, keyB.nonce)
|
||||
}
|
||||
|
||||
type PriorityNonceMempoolOption func(*PriorityNonceMempool)
|
||||
|
||||
// PriorityNonceWithOnRead sets a callback to be called when a tx is read from
|
||||
// the mempool.
|
||||
func PriorityNonceWithOnRead(onRead func(tx sdk.Tx)) PriorityNonceMempoolOption {
|
||||
return func(mp *PriorityNonceMempool) {
|
||||
mp.onRead = onRead
|
||||
}
|
||||
}
|
||||
|
||||
// PriorityNonceWithTxReplacement sets a callback to be called when duplicated
|
||||
// transaction nonce detected during mempool insert. An application can define a
|
||||
// transaction replacement rule based on tx priority or certain transaction fields.
|
||||
func PriorityNonceWithTxReplacement(txReplacementRule func(op, np int64, oTx, nTx sdk.Tx) bool) PriorityNonceMempoolOption {
|
||||
return func(mp *PriorityNonceMempool) {
|
||||
mp.txReplacement = txReplacementRule
|
||||
}
|
||||
}
|
||||
|
||||
// PriorityNonceWithMaxTx sets the maximum number of transactions allowed in the
|
||||
// mempool with the semantics:
|
||||
//
|
||||
// <0: disabled, `Insert` is a no-op
|
||||
// 0: unlimited
|
||||
// >0: maximum number of transactions allowed
|
||||
func PriorityNonceWithMaxTx(maxTx int) PriorityNonceMempoolOption {
|
||||
return func(mp *PriorityNonceMempool) {
|
||||
mp.maxTx = maxTx
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultPriorityMempool returns a priorityNonceMempool with no options.
|
||||
func DefaultPriorityMempool() mempool.Mempool {
|
||||
return NewPriorityMempool()
|
||||
}
|
||||
|
||||
// NewPriorityMempool returns the SDK's default mempool implementation which
|
||||
// returns txs in a partial order by 2 dimensions; priority, and sender-nonce.
|
||||
func NewPriorityMempool(opts ...PriorityNonceMempoolOption) *PriorityNonceMempool {
|
||||
mp := &PriorityNonceMempool{
|
||||
priorityIndex: skiplist.New(skiplist.LessThanFunc(txMetaLess)),
|
||||
priorityCounts: make(map[int64]int),
|
||||
senderIndices: make(map[string]*skiplist.SkipList),
|
||||
scores: make(map[txMeta]txMeta),
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(mp)
|
||||
}
|
||||
|
||||
return mp
|
||||
}
|
||||
|
||||
// NextSenderTx returns the next transaction for a given sender by nonce order,
|
||||
// i.e. the next valid transaction for the sender. If no such transaction exists,
|
||||
// nil will be returned.
|
||||
func (mp *PriorityNonceMempool) NextSenderTx(sender string) sdk.Tx {
|
||||
senderIndex, ok := mp.senderIndices[sender]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
cursor := senderIndex.Front()
|
||||
return cursor.Value.(sdk.Tx)
|
||||
}
|
||||
|
||||
// Insert attempts to insert a Tx into the app-side mempool in O(log n) time,
|
||||
// returning an error if unsuccessful. Sender and nonce are derived from the
|
||||
// transaction's first signature.
|
||||
//
|
||||
// Transactions are unique by sender and nonce. Inserting a duplicate tx is an
|
||||
// O(log n) no-op.
|
||||
//
|
||||
// Inserting a duplicate tx with a different priority overwrites the existing tx,
|
||||
// changing the total order of the mempool.
|
||||
func (mp *PriorityNonceMempool) Insert(ctx context.Context, tx sdk.Tx) error {
|
||||
if mp.maxTx > 0 && mp.CountTx() >= mp.maxTx {
|
||||
return mempool.ErrMempoolTxMaxCapacity
|
||||
} else if mp.maxTx < 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
sigs, err := tx.(signing.SigVerifiableTx).GetSignaturesV2()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sdkContext := sdk.UnwrapSDKContext(ctx)
|
||||
priority := sdkContext.Priority()
|
||||
|
||||
var sender string
|
||||
var nonce uint64
|
||||
|
||||
if len(sigs) == 0 {
|
||||
msgs := tx.GetMsgs()
|
||||
if len(msgs) != 1 {
|
||||
return fmt.Errorf("tx must have at least one signer")
|
||||
}
|
||||
msgEthTx, ok := msgs[0].(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return fmt.Errorf("tx must have at least one signer")
|
||||
}
|
||||
ethTx := msgEthTx.AsTransaction()
|
||||
signer := gethtypes.NewEIP2930Signer(ethTx.ChainId())
|
||||
ethSender, err := signer.Sender(ethTx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("tx must have at least one signer")
|
||||
}
|
||||
sender = sdk.AccAddress(ethSender.Bytes()).String()
|
||||
nonce = ethTx.Nonce()
|
||||
} else {
|
||||
sig := sigs[0]
|
||||
sender = sdk.AccAddress(sig.PubKey.Address()).String()
|
||||
nonce = sig.Sequence
|
||||
}
|
||||
|
||||
key := txMeta{nonce: nonce, priority: priority, sender: sender}
|
||||
|
||||
senderIndex, ok := mp.senderIndices[sender]
|
||||
if !ok {
|
||||
senderIndex = skiplist.New(skiplist.LessThanFunc(func(a, b any) int {
|
||||
return skiplist.Uint64.Compare(b.(txMeta).nonce, a.(txMeta).nonce)
|
||||
}))
|
||||
|
||||
// initialize sender index if not found
|
||||
mp.senderIndices[sender] = senderIndex
|
||||
}
|
||||
|
||||
// Since mp.priorityIndex is scored by priority, then sender, then nonce, a
|
||||
// changed priority will create a new key, so we must remove the old key and
|
||||
// re-insert it to avoid having the same tx with different priorityIndex indexed
|
||||
// twice in the mempool.
|
||||
//
|
||||
// This O(log n) remove operation is rare and only happens when a tx's priority
|
||||
// changes.
|
||||
sk := txMeta{nonce: nonce, sender: sender}
|
||||
if oldScore, txExists := mp.scores[sk]; txExists {
|
||||
if mp.txReplacement != nil && !mp.txReplacement(oldScore.priority, priority, senderIndex.Get(key).Value.(sdk.Tx), tx) {
|
||||
return fmt.Errorf(
|
||||
"tx doesn't fit the replacement rule, oldPriority: %v, newPriority: %v, oldTx: %v, newTx: %v",
|
||||
oldScore.priority,
|
||||
priority,
|
||||
senderIndex.Get(key).Value.(sdk.Tx),
|
||||
tx,
|
||||
)
|
||||
}
|
||||
|
||||
mp.priorityIndex.Remove(txMeta{
|
||||
nonce: nonce,
|
||||
sender: sender,
|
||||
priority: oldScore.priority,
|
||||
weight: oldScore.weight,
|
||||
})
|
||||
mp.priorityCounts[oldScore.priority]--
|
||||
}
|
||||
|
||||
mp.priorityCounts[priority]++
|
||||
|
||||
// Since senderIndex is scored by nonce, a changed priority will overwrite the
|
||||
// existing key.
|
||||
key.senderElement = senderIndex.Set(key, tx)
|
||||
|
||||
mp.scores[sk] = txMeta{priority: priority}
|
||||
mp.priorityIndex.Set(key, tx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *PriorityNonceIterator) iteratePriority() mempool.Iterator {
|
||||
// beginning of priority iteration
|
||||
if i.priorityNode == nil {
|
||||
i.priorityNode = i.mempool.priorityIndex.Front()
|
||||
} else {
|
||||
i.priorityNode = i.priorityNode.Next()
|
||||
}
|
||||
|
||||
// end of priority iteration
|
||||
if i.priorityNode == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
i.sender = i.priorityNode.Key().(txMeta).sender
|
||||
|
||||
nextPriorityNode := i.priorityNode.Next()
|
||||
if nextPriorityNode != nil {
|
||||
i.nextPriority = nextPriorityNode.Key().(txMeta).priority
|
||||
} else {
|
||||
i.nextPriority = math.MinInt64
|
||||
}
|
||||
|
||||
return i.Next()
|
||||
}
|
||||
|
||||
func (i *PriorityNonceIterator) Next() mempool.Iterator {
|
||||
if i.priorityNode == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
cursor, ok := i.senderCursors[i.sender]
|
||||
if !ok {
|
||||
// beginning of sender iteration
|
||||
cursor = i.mempool.senderIndices[i.sender].Front()
|
||||
} else {
|
||||
// middle of sender iteration
|
||||
cursor = cursor.Next()
|
||||
}
|
||||
|
||||
// end of sender iteration
|
||||
if cursor == nil {
|
||||
return i.iteratePriority()
|
||||
}
|
||||
|
||||
key := cursor.Key().(txMeta)
|
||||
|
||||
// We've reached a transaction with a priority lower than the next highest
|
||||
// priority in the pool.
|
||||
if key.priority < i.nextPriority {
|
||||
return i.iteratePriority()
|
||||
} else if key.priority == i.nextPriority && i.priorityNode.Next() != nil {
|
||||
// Weight is incorporated into the priority index key only (not sender index)
|
||||
// so we must fetch it here from the scores map.
|
||||
weight := i.mempool.scores[txMeta{nonce: key.nonce, sender: key.sender}].weight
|
||||
if weight < i.priorityNode.Next().Key().(txMeta).weight {
|
||||
return i.iteratePriority()
|
||||
}
|
||||
}
|
||||
|
||||
i.senderCursors[i.sender] = cursor
|
||||
return i
|
||||
}
|
||||
|
||||
func (i *PriorityNonceIterator) Tx() sdk.Tx {
|
||||
return i.senderCursors[i.sender].Value.(sdk.Tx)
|
||||
}
|
||||
|
||||
// Select returns a set of transactions from the mempool, ordered by priority
|
||||
// and sender-nonce in O(n) time. The passed in list of transactions are ignored.
|
||||
// This is a readonly operation, the mempool is not modified.
|
||||
//
|
||||
// The maxBytes parameter defines the maximum number of bytes of transactions to
|
||||
// return.
|
||||
//
|
||||
// NOTE: It is not safe to use this iterator while removing transactions from
|
||||
// the underlying mempool.
|
||||
func (mp *PriorityNonceMempool) Select(_ context.Context, _ [][]byte) mempool.Iterator {
|
||||
if mp.priorityIndex.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
mp.reorderPriorityTies()
|
||||
|
||||
iterator := &PriorityNonceIterator{
|
||||
mempool: mp,
|
||||
senderCursors: make(map[string]*skiplist.Element),
|
||||
}
|
||||
|
||||
return iterator.iteratePriority()
|
||||
}
|
||||
|
||||
type reorderKey struct {
|
||||
deleteKey txMeta
|
||||
insertKey txMeta
|
||||
tx sdk.Tx
|
||||
}
|
||||
|
||||
func (mp *PriorityNonceMempool) reorderPriorityTies() {
|
||||
node := mp.priorityIndex.Front()
|
||||
|
||||
var reordering []reorderKey
|
||||
for node != nil {
|
||||
key := node.Key().(txMeta)
|
||||
if mp.priorityCounts[key.priority] > 1 {
|
||||
newKey := key
|
||||
newKey.weight = senderWeight(key.senderElement)
|
||||
reordering = append(reordering, reorderKey{deleteKey: key, insertKey: newKey, tx: node.Value.(sdk.Tx)})
|
||||
}
|
||||
|
||||
node = node.Next()
|
||||
}
|
||||
|
||||
for _, k := range reordering {
|
||||
mp.priorityIndex.Remove(k.deleteKey)
|
||||
delete(mp.scores, txMeta{nonce: k.deleteKey.nonce, sender: k.deleteKey.sender})
|
||||
mp.priorityIndex.Set(k.insertKey, k.tx)
|
||||
mp.scores[txMeta{nonce: k.insertKey.nonce, sender: k.insertKey.sender}] = k.insertKey
|
||||
}
|
||||
}
|
||||
|
||||
// senderWeight returns the weight of a given tx (t) at senderCursor. Weight is
|
||||
// defined as the first (nonce-wise) same sender tx with a priority not equal to
|
||||
// t. It is used to resolve priority collisions, that is when 2 or more txs from
|
||||
// different senders have the same priority.
|
||||
func senderWeight(senderCursor *skiplist.Element) int64 {
|
||||
if senderCursor == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
weight := senderCursor.Key().(txMeta).priority
|
||||
senderCursor = senderCursor.Next()
|
||||
for senderCursor != nil {
|
||||
p := senderCursor.Key().(txMeta).priority
|
||||
if p != weight {
|
||||
weight = p
|
||||
}
|
||||
|
||||
senderCursor = senderCursor.Next()
|
||||
}
|
||||
|
||||
return weight
|
||||
}
|
||||
|
||||
// CountTx returns the number of transactions in the mempool.
|
||||
func (mp *PriorityNonceMempool) CountTx() int {
|
||||
return mp.priorityIndex.Len()
|
||||
}
|
||||
|
||||
// Remove removes a transaction from the mempool in O(log n) time, returning an
|
||||
// error if unsuccessful.
|
||||
func (mp *PriorityNonceMempool) Remove(tx sdk.Tx) error {
|
||||
sigs, err := tx.(signing.SigVerifiableTx).GetSignaturesV2()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var sender string
|
||||
var nonce uint64
|
||||
if len(sigs) == 0 {
|
||||
msgs := tx.GetMsgs()
|
||||
if len(msgs) != 1 {
|
||||
return fmt.Errorf("attempted to remove a tx with no signatures")
|
||||
}
|
||||
msgEthTx, ok := msgs[0].(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
return fmt.Errorf("attempted to remove a tx with no signatures")
|
||||
}
|
||||
ethTx := msgEthTx.AsTransaction()
|
||||
signer := gethtypes.NewEIP2930Signer(ethTx.ChainId())
|
||||
ethSender, err := signer.Sender(ethTx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("attempted to remove a tx with no signatures")
|
||||
}
|
||||
sender = sdk.AccAddress(ethSender.Bytes()).String()
|
||||
nonce = ethTx.Nonce()
|
||||
} else {
|
||||
sig := sigs[0]
|
||||
sender = sdk.AccAddress(sig.PubKey.Address()).String()
|
||||
nonce = sig.Sequence
|
||||
}
|
||||
|
||||
scoreKey := txMeta{nonce: nonce, sender: sender}
|
||||
score, ok := mp.scores[scoreKey]
|
||||
if !ok {
|
||||
return mempool.ErrTxNotFound
|
||||
}
|
||||
tk := txMeta{nonce: nonce, priority: score.priority, sender: sender, weight: score.weight}
|
||||
|
||||
senderTxs, ok := mp.senderIndices[sender]
|
||||
if !ok {
|
||||
return fmt.Errorf("sender %s not found", sender)
|
||||
}
|
||||
|
||||
mp.priorityIndex.Remove(tk)
|
||||
senderTxs.Remove(tk)
|
||||
delete(mp.scores, scoreKey)
|
||||
mp.priorityCounts[score.priority]--
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsEmpty(mempool mempool.Mempool) error {
|
||||
mp := mempool.(*PriorityNonceMempool)
|
||||
if mp.priorityIndex.Len() != 0 {
|
||||
return fmt.Errorf("priorityIndex not empty")
|
||||
}
|
||||
|
||||
var countKeys []int64
|
||||
for k := range mp.priorityCounts {
|
||||
countKeys = append(countKeys, k)
|
||||
}
|
||||
|
||||
for _, k := range countKeys {
|
||||
if mp.priorityCounts[k] != 0 {
|
||||
return fmt.Errorf("priorityCounts not zero at %v, got %v", k, mp.priorityCounts[k])
|
||||
}
|
||||
}
|
||||
|
||||
var senderKeys []string
|
||||
for k := range mp.senderIndices {
|
||||
senderKeys = append(senderKeys, k)
|
||||
}
|
||||
|
||||
for _, k := range senderKeys {
|
||||
if mp.senderIndices[k].Len() != 0 {
|
||||
return fmt.Errorf("senderIndex not empty for sender %v", k)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -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 (
|
||||
@ -92,9 +93,10 @@ func NewTestAppFromSealed() TestApp {
|
||||
|
||||
encCfg := MakeEncodingConfig()
|
||||
|
||||
bApp := NewBaseApp(log.NewNopLogger(), db, encCfg, baseapp.SetChainID(TestChainId))
|
||||
app := NewApp(
|
||||
log.NewNopLogger(), db, chaincfg.DefaultNodeHome, nil,
|
||||
encCfg, DefaultOptions, baseapp.SetChainID(TestChainId),
|
||||
chaincfg.DefaultNodeHome, nil,
|
||||
encCfg, DefaultOptions, bApp,
|
||||
)
|
||||
return TestApp{App: *app}
|
||||
}
|
||||
@ -118,6 +120,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]
|
||||
@ -457,20 +462,6 @@ func (tApp TestApp) CreateNewUnbondedValidator(ctx sdk.Context, valAddress sdk.V
|
||||
return err
|
||||
}
|
||||
|
||||
func (tApp TestApp) SetInflation(ctx sdk.Context, value sdk.Dec) {
|
||||
mk := tApp.GetMintKeeper()
|
||||
|
||||
mintParams := mk.GetParams(ctx)
|
||||
mintParams.InflationMax = sdk.ZeroDec()
|
||||
mintParams.InflationMin = sdk.ZeroDec()
|
||||
|
||||
if err := mintParams.Validate(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
mk.SetParams(ctx, mintParams)
|
||||
}
|
||||
|
||||
// GeneratePrivKeyAddressPairs generates (deterministically) a total of n private keys and addresses.
|
||||
func GeneratePrivKeyAddressPairs(n int) (keys []cryptotypes.PrivKey, addrs []sdk.AccAddress) {
|
||||
r := rand.New(rand.NewSource(12345)) // make the generation deterministic
|
||||
|
@ -107,18 +107,9 @@ func (ac appCreator) newApp(
|
||||
skipLoadLatest = cast.ToBool(appOpts.Get(flagSkipLoadLatest))
|
||||
}
|
||||
|
||||
return app.NewApp(
|
||||
logger, db, homeDir, traceStore, ac.encodingConfig,
|
||||
app.Options{
|
||||
SkipLoadLatest: skipLoadLatest,
|
||||
SkipUpgradeHeights: skipUpgradeHeights,
|
||||
SkipGenesisInvariants: cast.ToBool(appOpts.Get(crisis.FlagSkipGenesisInvariants)),
|
||||
InvariantCheckPeriod: cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)),
|
||||
MempoolEnableAuth: mempoolEnableAuth,
|
||||
MempoolAuthAddresses: mempoolAuthAddresses,
|
||||
EVMTrace: cast.ToString(appOpts.Get(ethermintflags.EVMTracer)),
|
||||
EVMMaxGasWanted: cast.ToUint64(appOpts.Get(ethermintflags.EVMMaxTxGasWanted)),
|
||||
},
|
||||
mempool := app.NewPriorityMempool()
|
||||
|
||||
bApp := app.NewBaseApp(logger, db, ac.encodingConfig,
|
||||
baseapp.SetPruning(pruningOpts),
|
||||
baseapp.SetMinGasPrices(strings.Replace(cast.ToString(appOpts.Get(server.FlagMinGasPrices)), ";", ",", -1)),
|
||||
baseapp.SetHaltHeight(cast.ToUint64(appOpts.Get(server.FlagHaltHeight))),
|
||||
@ -132,7 +123,28 @@ func (ac appCreator) newApp(
|
||||
baseapp.SetIAVLDisableFastNode(cast.ToBool(iavlDisableFastNode)),
|
||||
baseapp.SetIAVLLazyLoading(cast.ToBool(appOpts.Get(server.FlagIAVLLazyLoading))),
|
||||
baseapp.SetChainID(chainID),
|
||||
baseapp.SetMempool(mempool),
|
||||
)
|
||||
bApp.SetTxEncoder(ac.encodingConfig.TxConfig.TxEncoder())
|
||||
abciProposalHandler := app.NewDefaultProposalHandler(mempool, bApp)
|
||||
bApp.SetPrepareProposal(abciProposalHandler.PrepareProposalHandler())
|
||||
|
||||
newApp := app.NewApp(
|
||||
homeDir, traceStore, ac.encodingConfig,
|
||||
app.Options{
|
||||
SkipLoadLatest: skipLoadLatest,
|
||||
SkipUpgradeHeights: skipUpgradeHeights,
|
||||
SkipGenesisInvariants: cast.ToBool(appOpts.Get(crisis.FlagSkipGenesisInvariants)),
|
||||
InvariantCheckPeriod: cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)),
|
||||
MempoolEnableAuth: mempoolEnableAuth,
|
||||
MempoolAuthAddresses: mempoolAuthAddresses,
|
||||
EVMTrace: cast.ToString(appOpts.Get(ethermintflags.EVMTracer)),
|
||||
EVMMaxGasWanted: cast.ToUint64(appOpts.Get(ethermintflags.EVMMaxTxGasWanted)),
|
||||
},
|
||||
bApp,
|
||||
)
|
||||
|
||||
return newApp
|
||||
}
|
||||
|
||||
// appExport writes out an app's state to json.
|
||||
@ -157,13 +169,15 @@ func (ac appCreator) appExport(
|
||||
|
||||
var tempApp *app.App
|
||||
if height != -1 {
|
||||
tempApp = app.NewApp(logger, db, homePath, traceStore, ac.encodingConfig, options)
|
||||
bApp := app.NewBaseApp(logger, db, ac.encodingConfig)
|
||||
tempApp = app.NewApp(homePath, traceStore, ac.encodingConfig, options, bApp)
|
||||
|
||||
if err := tempApp.LoadHeight(height); err != nil {
|
||||
return servertypes.ExportedApp{}, err
|
||||
}
|
||||
} else {
|
||||
tempApp = app.NewApp(logger, db, homePath, traceStore, ac.encodingConfig, options)
|
||||
bApp := app.NewBaseApp(logger, db, ac.encodingConfig)
|
||||
tempApp = app.NewApp(homePath, traceStore, ac.encodingConfig, options, bApp)
|
||||
}
|
||||
return tempApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport)
|
||||
}
|
||||
|
4
go.mod
4
go.mod
@ -242,7 +242,7 @@ replace (
|
||||
github.com/cometbft/cometbft-db => github.com/kava-labs/cometbft-db v0.9.1-kava.2
|
||||
// Use cosmos-sdk fork with backported fix for unsafe-reset-all, staking transfer events, and custom tally handler support
|
||||
// github.com/cosmos/cosmos-sdk => github.com/0glabs/cosmos-sdk v0.46.11-kava.3
|
||||
github.com/cosmos/cosmos-sdk => github.com/0glabs/cosmos-sdk v0.47.10-0glabs.8
|
||||
github.com/cosmos/cosmos-sdk => github.com/0glabs/cosmos-sdk v0.47.10-0glabs.9
|
||||
github.com/cosmos/iavl => github.com/kava-labs/iavl v1.2.0-kava.1
|
||||
// See https://github.com/cosmos/cosmos-sdk/pull/13093
|
||||
github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2
|
||||
@ -250,7 +250,7 @@ replace (
|
||||
// TODO: Tag before release
|
||||
github.com/ethereum/go-ethereum => github.com/evmos/go-ethereum v1.10.26-evmos-rc2
|
||||
// Use ethermint fork that respects min-gas-price with NoBaseFee true and london enabled, and includes eip712 support
|
||||
github.com/evmos/ethermint => github.com/0glabs/ethermint v0.21.0-0g.v3.1.8
|
||||
github.com/evmos/ethermint => github.com/0glabs/ethermint v0.21.0-0g.v3.1.9
|
||||
// See https://github.com/cosmos/cosmos-sdk/pull/10401, https://github.com/cosmos/cosmos-sdk/commit/0592ba6158cd0bf49d894be1cef4faeec59e8320
|
||||
github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.0
|
||||
// Downgraded to avoid bugs in following commits which causes "version does not exist" errors
|
||||
|
2
go.sum
2
go.sum
@ -211,8 +211,6 @@ git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3/go.mod h1:wMEGFFFN
|
||||
git.sr.ht/~sircmpwn/go-bare v0.0.0-20210406120253-ab86bc2846d9/go.mod h1:BVJwbDfVjCjoFiKrhkei6NdGcZYpkDkdyCdg1ukytRA=
|
||||
github.com/0glabs/cometbft v0.37.9-0glabs.1 h1:KQJG17Y21suKP3QNICLto4b5Ak73XbSmKxeLbg0ZM68=
|
||||
github.com/0glabs/cometbft v0.37.9-0glabs.1/go.mod h1:j0Q3RqrCd+cztWCugs3obbzC4NyHGBPZZjtm/fWV00I=
|
||||
github.com/0glabs/cosmos-sdk v0.47.10-0glabs.8 h1:IaNin0677A6terTnw3WOGmYOY2w4h0LugBhK6VugXMg=
|
||||
github.com/0glabs/cosmos-sdk v0.47.10-0glabs.8/go.mod h1:KskIVnhXTFqrw7CDccMvx7To5KzUsOomIsQV7sPGOog=
|
||||
github.com/0glabs/ethermint v0.21.0-0g.v3.1.8 h1:/jxCtO5B8amXgGZ0MWcoIH32PmoU9Z+WfPxA8nLaZI8=
|
||||
github.com/0glabs/ethermint v0.21.0-0g.v3.1.8/go.mod h1:1GrxH8zkhO/x8sinIxaFtolK50spzSAZISbdP1MDLy8=
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs=
|
||||
|
55
precompiles/interfaces/contracts/IWrappedA0GIBase.sol
Normal file
55
precompiles/interfaces/contracts/IWrappedA0GIBase.sol
Normal file
@ -0,0 +1,55 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
pragma solidity >=0.8.0;
|
||||
|
||||
struct Supply {
|
||||
uint256 cap;
|
||||
uint256 total;
|
||||
}
|
||||
|
||||
/**
|
||||
* @title WrappedA0GIBase is a precompile for wrapped a0gi(wA0GI), it enables wA0GI mint/burn native 0g token directly.
|
||||
*/
|
||||
interface IWrappedA0GIBase {
|
||||
/**
|
||||
* @dev set the wA0GI address.
|
||||
* It is designed to be called by governance module only so it's not implemented at EVM precompile side.
|
||||
* @param addr address of wA0GI
|
||||
*/
|
||||
// function setWA0GI(address addr) external;
|
||||
|
||||
/**
|
||||
* @dev get the wA0GI address.
|
||||
*/
|
||||
function getWA0GI() external view returns (address);
|
||||
|
||||
/**
|
||||
* @dev set the cap for a minter.
|
||||
* It is designed to be called by governance module only so it's not implemented at EVM precompile side.
|
||||
* @param minter minter address
|
||||
* @param cap mint cap
|
||||
*/
|
||||
// function setMinterCap(address minter, uint256 cap) external;
|
||||
|
||||
/**
|
||||
* @dev get the mint supply of given address
|
||||
* @param minter minter address
|
||||
*/
|
||||
function minterSupply(address minter) external view returns (Supply memory);
|
||||
|
||||
/**
|
||||
* @dev mint a0gi to this precompile, add corresponding amount to minter's mint supply.
|
||||
* If sender's final mint supply exceeds its mint cap, the transaction will revert.
|
||||
* Can only be called by WA0GI.
|
||||
* @param minter minter address
|
||||
* @param amount amount to mint
|
||||
*/
|
||||
function mint(address minter, uint256 amount) external;
|
||||
|
||||
/**
|
||||
* @dev burn given amount of a0gi on behalf of minter, reduce corresponding amount from sender's mint supply.
|
||||
* Can only be called by WA0GI.
|
||||
* @param minter minter address
|
||||
* @param amount amount to burn
|
||||
*/
|
||||
function burn(address minter, uint256 amount) external;
|
||||
}
|
82
precompiles/wrapped-a0gi-base/IWrappedA0GIBase.json
Normal file
82
precompiles/wrapped-a0gi-base/IWrappedA0GIBase.json
Normal file
@ -0,0 +1,82 @@
|
||||
[
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "minter",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "burn",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "getWA0GI",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "minter",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "amount",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "mint",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "minter",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "minterSupply",
|
||||
"outputs": [
|
||||
{
|
||||
"components": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "cap",
|
||||
"type": "uint256"
|
||||
},
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "total",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"internalType": "struct Supply",
|
||||
"name": "",
|
||||
"type": "tuple"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
284
precompiles/wrapped-a0gi-base/contract.go
Normal file
284
precompiles/wrapped-a0gi-base/contract.go
Normal file
@ -0,0 +1,284 @@
|
||||
// Code generated - DO NOT EDIT.
|
||||
// This file is a generated binding and any manual changes will be lost.
|
||||
|
||||
package wrappeda0gibase
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
ethereum "github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var (
|
||||
_ = errors.New
|
||||
_ = big.NewInt
|
||||
_ = strings.NewReader
|
||||
_ = ethereum.NotFound
|
||||
_ = bind.Bind
|
||||
_ = common.Big1
|
||||
_ = types.BloomLookup
|
||||
_ = event.NewSubscription
|
||||
)
|
||||
|
||||
// Wrappeda0gibaseMetaData contains all meta data concerning the Wrappeda0gibase contract.
|
||||
var Wrappeda0gibaseMetaData = &bind.MetaData{
|
||||
ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWA0GI\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"minterSupply\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"cap\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"total\",\"type\":\"uint256\"}],\"internalType\":\"structSupply\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
|
||||
}
|
||||
|
||||
// Wrappeda0gibaseABI is the input ABI used to generate the binding from.
|
||||
// Deprecated: Use Wrappeda0gibaseMetaData.ABI instead.
|
||||
var Wrappeda0gibaseABI = Wrappeda0gibaseMetaData.ABI
|
||||
|
||||
// Wrappeda0gibase is an auto generated Go binding around an Ethereum contract.
|
||||
type Wrappeda0gibase struct {
|
||||
Wrappeda0gibaseCaller // Read-only binding to the contract
|
||||
Wrappeda0gibaseTransactor // Write-only binding to the contract
|
||||
Wrappeda0gibaseFilterer // Log filterer for contract events
|
||||
}
|
||||
|
||||
// Wrappeda0gibaseCaller is an auto generated read-only Go binding around an Ethereum contract.
|
||||
type Wrappeda0gibaseCaller struct {
|
||||
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||
}
|
||||
|
||||
// Wrappeda0gibaseTransactor is an auto generated write-only Go binding around an Ethereum contract.
|
||||
type Wrappeda0gibaseTransactor struct {
|
||||
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||
}
|
||||
|
||||
// Wrappeda0gibaseFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
|
||||
type Wrappeda0gibaseFilterer struct {
|
||||
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||
}
|
||||
|
||||
// Wrappeda0gibaseSession is an auto generated Go binding around an Ethereum contract,
|
||||
// with pre-set call and transact options.
|
||||
type Wrappeda0gibaseSession struct {
|
||||
Contract *Wrappeda0gibase // Generic contract binding to set the session for
|
||||
CallOpts bind.CallOpts // Call options to use throughout this session
|
||||
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
|
||||
}
|
||||
|
||||
// Wrappeda0gibaseCallerSession is an auto generated read-only Go binding around an Ethereum contract,
|
||||
// with pre-set call options.
|
||||
type Wrappeda0gibaseCallerSession struct {
|
||||
Contract *Wrappeda0gibaseCaller // Generic contract caller binding to set the session for
|
||||
CallOpts bind.CallOpts // Call options to use throughout this session
|
||||
}
|
||||
|
||||
// Wrappeda0gibaseTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
|
||||
// with pre-set transact options.
|
||||
type Wrappeda0gibaseTransactorSession struct {
|
||||
Contract *Wrappeda0gibaseTransactor // Generic contract transactor binding to set the session for
|
||||
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
|
||||
}
|
||||
|
||||
// Wrappeda0gibaseRaw is an auto generated low-level Go binding around an Ethereum contract.
|
||||
type Wrappeda0gibaseRaw struct {
|
||||
Contract *Wrappeda0gibase // Generic contract binding to access the raw methods on
|
||||
}
|
||||
|
||||
// Wrappeda0gibaseCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
|
||||
type Wrappeda0gibaseCallerRaw struct {
|
||||
Contract *Wrappeda0gibaseCaller // Generic read-only contract binding to access the raw methods on
|
||||
}
|
||||
|
||||
// Wrappeda0gibaseTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
|
||||
type Wrappeda0gibaseTransactorRaw struct {
|
||||
Contract *Wrappeda0gibaseTransactor // Generic write-only contract binding to access the raw methods on
|
||||
}
|
||||
|
||||
// NewWrappeda0gibase creates a new instance of Wrappeda0gibase, bound to a specific deployed contract.
|
||||
func NewWrappeda0gibase(address common.Address, backend bind.ContractBackend) (*Wrappeda0gibase, error) {
|
||||
contract, err := bindWrappeda0gibase(address, backend, backend, backend)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Wrappeda0gibase{Wrappeda0gibaseCaller: Wrappeda0gibaseCaller{contract: contract}, Wrappeda0gibaseTransactor: Wrappeda0gibaseTransactor{contract: contract}, Wrappeda0gibaseFilterer: Wrappeda0gibaseFilterer{contract: contract}}, nil
|
||||
}
|
||||
|
||||
// NewWrappeda0gibaseCaller creates a new read-only instance of Wrappeda0gibase, bound to a specific deployed contract.
|
||||
func NewWrappeda0gibaseCaller(address common.Address, caller bind.ContractCaller) (*Wrappeda0gibaseCaller, error) {
|
||||
contract, err := bindWrappeda0gibase(address, caller, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Wrappeda0gibaseCaller{contract: contract}, nil
|
||||
}
|
||||
|
||||
// NewWrappeda0gibaseTransactor creates a new write-only instance of Wrappeda0gibase, bound to a specific deployed contract.
|
||||
func NewWrappeda0gibaseTransactor(address common.Address, transactor bind.ContractTransactor) (*Wrappeda0gibaseTransactor, error) {
|
||||
contract, err := bindWrappeda0gibase(address, nil, transactor, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Wrappeda0gibaseTransactor{contract: contract}, nil
|
||||
}
|
||||
|
||||
// NewWrappeda0gibaseFilterer creates a new log filterer instance of Wrappeda0gibase, bound to a specific deployed contract.
|
||||
func NewWrappeda0gibaseFilterer(address common.Address, filterer bind.ContractFilterer) (*Wrappeda0gibaseFilterer, error) {
|
||||
contract, err := bindWrappeda0gibase(address, nil, nil, filterer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Wrappeda0gibaseFilterer{contract: contract}, nil
|
||||
}
|
||||
|
||||
// bindWrappeda0gibase binds a generic wrapper to an already deployed contract.
|
||||
func bindWrappeda0gibase(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
|
||||
parsed, err := abi.JSON(strings.NewReader(Wrappeda0gibaseABI))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
|
||||
}
|
||||
|
||||
// Call invokes the (constant) contract method with params as input values and
|
||||
// sets the output to result. The result type might be a single field for simple
|
||||
// returns, a slice of interfaces for anonymous returns and a struct for named
|
||||
// returns.
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
|
||||
return _Wrappeda0gibase.Contract.Wrappeda0gibaseCaller.contract.Call(opts, result, method, params...)
|
||||
}
|
||||
|
||||
// Transfer initiates a plain transaction to move funds to the contract, calling
|
||||
// its default method if one is available.
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
|
||||
return _Wrappeda0gibase.Contract.Wrappeda0gibaseTransactor.contract.Transfer(opts)
|
||||
}
|
||||
|
||||
// Transact invokes the (paid) contract method with params as input values.
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
|
||||
return _Wrappeda0gibase.Contract.Wrappeda0gibaseTransactor.contract.Transact(opts, method, params...)
|
||||
}
|
||||
|
||||
// Call invokes the (constant) contract method with params as input values and
|
||||
// sets the output to result. The result type might be a single field for simple
|
||||
// returns, a slice of interfaces for anonymous returns and a struct for named
|
||||
// returns.
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
|
||||
return _Wrappeda0gibase.Contract.contract.Call(opts, result, method, params...)
|
||||
}
|
||||
|
||||
// Transfer initiates a plain transaction to move funds to the contract, calling
|
||||
// its default method if one is available.
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
|
||||
return _Wrappeda0gibase.Contract.contract.Transfer(opts)
|
||||
}
|
||||
|
||||
// Transact invokes the (paid) contract method with params as input values.
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
|
||||
return _Wrappeda0gibase.Contract.contract.Transact(opts, method, params...)
|
||||
}
|
||||
|
||||
// GetWA0GI is a free data retrieval call binding the contract method 0xa9283a7a.
|
||||
//
|
||||
// Solidity: function getWA0GI() view returns(address)
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseCaller) GetWA0GI(opts *bind.CallOpts) (common.Address, error) {
|
||||
var out []interface{}
|
||||
err := _Wrappeda0gibase.contract.Call(opts, &out, "getWA0GI")
|
||||
|
||||
if err != nil {
|
||||
return *new(common.Address), err
|
||||
}
|
||||
|
||||
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
|
||||
|
||||
return out0, err
|
||||
|
||||
}
|
||||
|
||||
// GetWA0GI is a free data retrieval call binding the contract method 0xa9283a7a.
|
||||
//
|
||||
// Solidity: function getWA0GI() view returns(address)
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseSession) GetWA0GI() (common.Address, error) {
|
||||
return _Wrappeda0gibase.Contract.GetWA0GI(&_Wrappeda0gibase.CallOpts)
|
||||
}
|
||||
|
||||
// GetWA0GI is a free data retrieval call binding the contract method 0xa9283a7a.
|
||||
//
|
||||
// Solidity: function getWA0GI() view returns(address)
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseCallerSession) GetWA0GI() (common.Address, error) {
|
||||
return _Wrappeda0gibase.Contract.GetWA0GI(&_Wrappeda0gibase.CallOpts)
|
||||
}
|
||||
|
||||
// MinterSupply is a free data retrieval call binding the contract method 0x95609212.
|
||||
//
|
||||
// Solidity: function minterSupply(address minter) view returns((uint256,uint256))
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseCaller) MinterSupply(opts *bind.CallOpts, minter common.Address) (Supply, error) {
|
||||
var out []interface{}
|
||||
err := _Wrappeda0gibase.contract.Call(opts, &out, "minterSupply", minter)
|
||||
|
||||
if err != nil {
|
||||
return *new(Supply), err
|
||||
}
|
||||
|
||||
out0 := *abi.ConvertType(out[0], new(Supply)).(*Supply)
|
||||
|
||||
return out0, err
|
||||
|
||||
}
|
||||
|
||||
// MinterSupply is a free data retrieval call binding the contract method 0x95609212.
|
||||
//
|
||||
// Solidity: function minterSupply(address minter) view returns((uint256,uint256))
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseSession) MinterSupply(minter common.Address) (Supply, error) {
|
||||
return _Wrappeda0gibase.Contract.MinterSupply(&_Wrappeda0gibase.CallOpts, minter)
|
||||
}
|
||||
|
||||
// MinterSupply is a free data retrieval call binding the contract method 0x95609212.
|
||||
//
|
||||
// Solidity: function minterSupply(address minter) view returns((uint256,uint256))
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseCallerSession) MinterSupply(minter common.Address) (Supply, error) {
|
||||
return _Wrappeda0gibase.Contract.MinterSupply(&_Wrappeda0gibase.CallOpts, minter)
|
||||
}
|
||||
|
||||
// Burn is a paid mutator transaction binding the contract method 0x9dc29fac.
|
||||
//
|
||||
// Solidity: function burn(address minter, uint256 amount) returns()
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseTransactor) Burn(opts *bind.TransactOpts, minter common.Address, amount *big.Int) (*types.Transaction, error) {
|
||||
return _Wrappeda0gibase.contract.Transact(opts, "burn", minter, amount)
|
||||
}
|
||||
|
||||
// Burn is a paid mutator transaction binding the contract method 0x9dc29fac.
|
||||
//
|
||||
// Solidity: function burn(address minter, uint256 amount) returns()
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseSession) Burn(minter common.Address, amount *big.Int) (*types.Transaction, error) {
|
||||
return _Wrappeda0gibase.Contract.Burn(&_Wrappeda0gibase.TransactOpts, minter, amount)
|
||||
}
|
||||
|
||||
// Burn is a paid mutator transaction binding the contract method 0x9dc29fac.
|
||||
//
|
||||
// Solidity: function burn(address minter, uint256 amount) returns()
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseTransactorSession) Burn(minter common.Address, amount *big.Int) (*types.Transaction, error) {
|
||||
return _Wrappeda0gibase.Contract.Burn(&_Wrappeda0gibase.TransactOpts, minter, amount)
|
||||
}
|
||||
|
||||
// Mint is a paid mutator transaction binding the contract method 0x40c10f19.
|
||||
//
|
||||
// Solidity: function mint(address minter, uint256 amount) returns()
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseTransactor) Mint(opts *bind.TransactOpts, minter common.Address, amount *big.Int) (*types.Transaction, error) {
|
||||
return _Wrappeda0gibase.contract.Transact(opts, "mint", minter, amount)
|
||||
}
|
||||
|
||||
// Mint is a paid mutator transaction binding the contract method 0x40c10f19.
|
||||
//
|
||||
// Solidity: function mint(address minter, uint256 amount) returns()
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseSession) Mint(minter common.Address, amount *big.Int) (*types.Transaction, error) {
|
||||
return _Wrappeda0gibase.Contract.Mint(&_Wrappeda0gibase.TransactOpts, minter, amount)
|
||||
}
|
||||
|
||||
// Mint is a paid mutator transaction binding the contract method 0x40c10f19.
|
||||
//
|
||||
// Solidity: function mint(address minter, uint256 amount) returns()
|
||||
func (_Wrappeda0gibase *Wrappeda0gibaseTransactorSession) Mint(minter common.Address, amount *big.Int) (*types.Transaction, error) {
|
||||
return _Wrappeda0gibase.Contract.Mint(&_Wrappeda0gibase.TransactOpts, minter, amount)
|
||||
}
|
5
precompiles/wrapped-a0gi-base/errors.go
Normal file
5
precompiles/wrapped-a0gi-base/errors.go
Normal file
@ -0,0 +1,5 @@
|
||||
package wrappeda0gibase
|
||||
|
||||
const (
|
||||
ErrSenderNotWA0GI = "sender is not WA0GI"
|
||||
)
|
38
precompiles/wrapped-a0gi-base/query.go
Normal file
38
precompiles/wrapped-a0gi-base/query.go
Normal file
@ -0,0 +1,38 @@
|
||||
package wrappeda0gibase
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
)
|
||||
|
||||
func (w *WrappedA0giBasePrecompile) GetW0GI(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
|
||||
req, err := NewGetW0GIRequest(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
response, err := w.wrappeda0gibaseKeeper.GetWA0GI(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return method.Outputs.Pack(common.BytesToAddress(response.Address))
|
||||
}
|
||||
|
||||
func (w *WrappedA0giBasePrecompile) MinterSupply(ctx sdk.Context, _ *vm.EVM, method *abi.Method, args []interface{}) ([]byte, error) {
|
||||
req, err := NewMinterSupplyRequest(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
response, err := w.wrappeda0gibaseKeeper.MinterSupply(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
supply := Supply{
|
||||
Cap: new(big.Int).SetBytes(response.Cap),
|
||||
Total: new(big.Int).SetBytes(response.Supply),
|
||||
}
|
||||
return method.Outputs.Pack(supply)
|
||||
}
|
147
precompiles/wrapped-a0gi-base/query_test.go
Normal file
147
precompiles/wrapped-a0gi-base/query_test.go
Normal file
@ -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.MsgSetMinterCap{
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
62
precompiles/wrapped-a0gi-base/tx.go
Normal file
62
precompiles/wrapped-a0gi-base/tx.go
Normal file
@ -0,0 +1,62 @@
|
||||
package wrappeda0gibase
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/evmos/ethermint/x/evm/statedb"
|
||||
)
|
||||
|
||||
func (w *WrappedA0giBasePrecompile) Mint(
|
||||
ctx sdk.Context,
|
||||
evm *vm.EVM,
|
||||
stateDB *statedb.StateDB,
|
||||
contract *vm.Contract,
|
||||
method *abi.Method,
|
||||
args []interface{},
|
||||
) ([]byte, error) {
|
||||
msg, err := NewMsgMint(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// validation
|
||||
wa0gi := common.BytesToAddress(w.wrappeda0gibaseKeeper.GetWA0GIAddress(ctx))
|
||||
if contract.CallerAddress != wa0gi {
|
||||
return nil, errors.New(ErrSenderNotWA0GI)
|
||||
}
|
||||
// execute
|
||||
_, err = w.wrappeda0gibaseKeeper.Mint(sdk.WrapSDKContext(ctx), msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return method.Outputs.Pack()
|
||||
}
|
||||
|
||||
func (w *WrappedA0giBasePrecompile) Burn(
|
||||
ctx sdk.Context,
|
||||
evm *vm.EVM,
|
||||
stateDB *statedb.StateDB,
|
||||
contract *vm.Contract,
|
||||
method *abi.Method,
|
||||
args []interface{},
|
||||
) ([]byte, error) {
|
||||
msg, err := NewMsgBurn(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// validation
|
||||
wa0gi := common.BytesToAddress(w.wrappeda0gibaseKeeper.GetWA0GIAddress(ctx))
|
||||
if contract.CallerAddress != wa0gi {
|
||||
return nil, errors.New(ErrSenderNotWA0GI)
|
||||
}
|
||||
// execute
|
||||
_, err = w.wrappeda0gibaseKeeper.Burn(sdk.WrapSDKContext(ctx), msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return method.Outputs.Pack()
|
||||
}
|
218
precompiles/wrapped-a0gi-base/tx_test.go
Normal file
218
precompiles/wrapped-a0gi-base/tx_test.go
Normal file
@ -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.MsgSetMinterCap{
|
||||
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.MsgSetMinterCap{
|
||||
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()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
51
precompiles/wrapped-a0gi-base/types.go
Normal file
51
precompiles/wrapped-a0gi-base/types.go
Normal file
@ -0,0 +1,51 @@
|
||||
package wrappeda0gibase
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
precompiles_common "github.com/0glabs/0g-chain/precompiles/common"
|
||||
"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
type Supply = struct {
|
||||
Cap *big.Int "json:\"cap\""
|
||||
Total *big.Int "json:\"total\""
|
||||
}
|
||||
|
||||
func NewGetW0GIRequest(args []interface{}) (*types.GetWA0GIRequest, error) {
|
||||
if len(args) != 0 {
|
||||
return nil, fmt.Errorf(precompiles_common.ErrInvalidNumberOfArgs, 0, len(args))
|
||||
}
|
||||
return &types.GetWA0GIRequest{}, nil
|
||||
}
|
||||
|
||||
func NewMinterSupplyRequest(args []interface{}) (*types.MinterSupplyRequest, error) {
|
||||
if len(args) != 1 {
|
||||
return nil, fmt.Errorf(precompiles_common.ErrInvalidNumberOfArgs, 1, len(args))
|
||||
}
|
||||
return &types.MinterSupplyRequest{
|
||||
Address: args[0].(common.Address).Bytes(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewMsgMint(args []interface{}) (*types.MsgMint, error) {
|
||||
if len(args) != 2 {
|
||||
return nil, fmt.Errorf(precompiles_common.ErrInvalidNumberOfArgs, 1, len(args))
|
||||
}
|
||||
return &types.MsgMint{
|
||||
Minter: args[0].(common.Address).Bytes(),
|
||||
Amount: args[1].(*big.Int).Bytes(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewMsgBurn(args []interface{}) (*types.MsgBurn, error) {
|
||||
if len(args) != 2 {
|
||||
return nil, fmt.Errorf(precompiles_common.ErrInvalidNumberOfArgs, 1, len(args))
|
||||
}
|
||||
return &types.MsgBurn{
|
||||
Minter: args[0].(common.Address).Bytes(),
|
||||
Amount: args[1].(*big.Int).Bytes(),
|
||||
}, nil
|
||||
}
|
106
precompiles/wrapped-a0gi-base/wrapped_a0gi_base.go
Normal file
106
precompiles/wrapped-a0gi-base/wrapped_a0gi_base.go
Normal file
@ -0,0 +1,106 @@
|
||||
package wrappeda0gibase
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
precompiles_common "github.com/0glabs/0g-chain/precompiles/common"
|
||||
wrappeda0gibasekeeper "github.com/0glabs/0g-chain/x/wrapped-a0gi-base/keeper"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
)
|
||||
|
||||
const (
|
||||
PrecompileAddress = "0x0000000000000000000000000000000000001002"
|
||||
|
||||
// txs
|
||||
WrappedA0GIBaseFunctionMint = "mint"
|
||||
WrappedA0GIBaseFunctionBurn = "burn"
|
||||
// queries
|
||||
WrappedA0GIBaseFunctionGetWA0GI = "getWA0GI"
|
||||
WrappedA0GIBaseFunctionMinterSupply = "minterSupply"
|
||||
)
|
||||
|
||||
var _ vm.PrecompiledContract = &WrappedA0giBasePrecompile{}
|
||||
var _ precompiles_common.PrecompileCommon = &WrappedA0giBasePrecompile{}
|
||||
|
||||
type WrappedA0giBasePrecompile struct {
|
||||
abi abi.ABI
|
||||
wrappeda0gibaseKeeper wrappeda0gibasekeeper.Keeper
|
||||
}
|
||||
|
||||
// Abi implements common.PrecompileCommon.
|
||||
func (w *WrappedA0giBasePrecompile) Abi() *abi.ABI {
|
||||
return &w.abi
|
||||
}
|
||||
|
||||
// IsTx implements common.PrecompileCommon.
|
||||
func (w *WrappedA0giBasePrecompile) IsTx(method string) bool {
|
||||
switch method {
|
||||
case WrappedA0GIBaseFunctionMint,
|
||||
WrappedA0GIBaseFunctionBurn:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// KVGasConfig implements common.PrecompileCommon.
|
||||
func (w *WrappedA0giBasePrecompile) KVGasConfig() storetypes.GasConfig {
|
||||
return storetypes.KVGasConfig()
|
||||
}
|
||||
|
||||
// Address implements vm.PrecompiledContract.
|
||||
func (w *WrappedA0giBasePrecompile) Address() common.Address {
|
||||
return common.HexToAddress(PrecompileAddress)
|
||||
}
|
||||
|
||||
// RequiredGas implements vm.PrecompiledContract.
|
||||
func (w *WrappedA0giBasePrecompile) RequiredGas(input []byte) uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func NewWrappedA0giBasePrecompile(wrappeda0gibaseKeeper wrappeda0gibasekeeper.Keeper) (*WrappedA0giBasePrecompile, error) {
|
||||
abi, err := abi.JSON(strings.NewReader(Wrappeda0gibaseABI))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &WrappedA0giBasePrecompile{
|
||||
abi: abi,
|
||||
wrappeda0gibaseKeeper: wrappeda0gibaseKeeper,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Run implements vm.PrecompiledContract.
|
||||
func (w *WrappedA0giBasePrecompile) Run(evm *vm.EVM, contract *vm.Contract, readonly bool) ([]byte, error) {
|
||||
ctx, stateDB, method, initialGas, args, err := precompiles_common.InitializePrecompileCall(w, evm, contract, readonly)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var bz []byte
|
||||
switch method.Name {
|
||||
// queries
|
||||
case WrappedA0GIBaseFunctionGetWA0GI:
|
||||
bz, err = w.GetW0GI(ctx, evm, method, args)
|
||||
case WrappedA0GIBaseFunctionMinterSupply:
|
||||
bz, err = w.MinterSupply(ctx, evm, method, args)
|
||||
// txs
|
||||
case WrappedA0GIBaseFunctionMint:
|
||||
bz, err = w.Mint(ctx, evm, stateDB, contract, method, args)
|
||||
case WrappedA0GIBaseFunctionBurn:
|
||||
bz, err = w.Burn(ctx, evm, stateDB, contract, method, args)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cost := ctx.GasMeter().GasConsumed() - initialGas
|
||||
|
||||
if !contract.UseGas(cost) {
|
||||
return nil, vm.ErrOutOfGas
|
||||
}
|
||||
return bz, nil
|
||||
}
|
80
precompiles/wrapped-a0gi-base/wrapped_a0gi_base_test.go
Normal file
80
precompiles/wrapped-a0gi-base/wrapped_a0gi_base_test.go
Normal file
@ -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))
|
||||
}
|
15
proto/zgc/wrappeda0gibase/genesis.proto
Normal file
15
proto/zgc/wrappeda0gibase/genesis.proto
Normal file
@ -0,0 +1,15 @@
|
||||
syntax = "proto3";
|
||||
package zgc.wrappeda0gibase;
|
||||
|
||||
import "cosmos_proto/cosmos.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types";
|
||||
|
||||
// GenesisState defines the wrapped a0gi base module's genesis state.
|
||||
message GenesisState {
|
||||
// address of wrapped a0gi contract
|
||||
bytes wrapped_a0gi_address = 1;
|
||||
}
|
36
proto/zgc/wrappeda0gibase/query.proto
Normal file
36
proto/zgc/wrappeda0gibase/query.proto
Normal file
@ -0,0 +1,36 @@
|
||||
syntax = "proto3";
|
||||
package zgc.wrappeda0gibase;
|
||||
|
||||
import "cosmos_proto/cosmos.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types";
|
||||
option (gogoproto.goproto_getters_all) = false;
|
||||
|
||||
// Query defines the gRPC querier service for the wrapped a0gi base module
|
||||
service Query {
|
||||
rpc GetWA0GI(GetWA0GIRequest) returns (GetWA0GIResponse) {
|
||||
option (google.api.http).get = "/0g/wrapped-a0gi-base/get-wa0gi";
|
||||
}
|
||||
rpc MinterSupply(MinterSupplyRequest) returns (MinterSupplyResponse) {
|
||||
option (google.api.http).get = "/0g/wrapped-a0gi-base/minter-supply";
|
||||
}
|
||||
}
|
||||
|
||||
message GetWA0GIRequest {}
|
||||
|
||||
message GetWA0GIResponse {
|
||||
bytes address = 1;
|
||||
}
|
||||
|
||||
message MinterSupplyRequest {
|
||||
bytes address = 1;
|
||||
}
|
||||
|
||||
message MinterSupplyResponse {
|
||||
bytes cap = 1; // big endian
|
||||
bytes supply = 2; // big endian
|
||||
}
|
46
proto/zgc/wrappeda0gibase/tx.proto
Normal file
46
proto/zgc/wrappeda0gibase/tx.proto
Normal file
@ -0,0 +1,46 @@
|
||||
syntax = "proto3";
|
||||
package zgc.wrappeda0gibase;
|
||||
|
||||
import "cosmos_proto/cosmos.proto";
|
||||
import "gogoproto/gogo.proto";
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
option go_package = "github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types";
|
||||
option (gogoproto.goproto_getters_all) = false;
|
||||
|
||||
// Msg defines the wrapped a0gi base Msg service
|
||||
service Msg {
|
||||
rpc SetWA0GI(MsgSetWA0GI) returns (MsgSetWA0GIResponse);
|
||||
rpc SetMinterCap(MsgSetMinterCap) returns (MsgSetMinterCapResponse);
|
||||
rpc Mint(MsgMint) returns (MsgMintResponse);
|
||||
rpc Burn(MsgBurn) returns (MsgBurnResponse);
|
||||
}
|
||||
|
||||
message MsgSetWA0GI {
|
||||
string authority = 1;
|
||||
bytes address = 2;
|
||||
}
|
||||
|
||||
message MsgSetWA0GIResponse {}
|
||||
|
||||
message MsgSetMinterCap {
|
||||
string authority = 1;
|
||||
bytes minter = 2;
|
||||
bytes cap = 3; // big endian
|
||||
}
|
||||
|
||||
message MsgSetMinterCapResponse {}
|
||||
|
||||
message MsgMint {
|
||||
bytes minter = 1;
|
||||
bytes amount = 2; // big endian
|
||||
}
|
||||
|
||||
message MsgMintResponse {}
|
||||
|
||||
message MsgBurn {
|
||||
bytes minter = 1;
|
||||
bytes amount = 2; // big endian
|
||||
}
|
||||
|
||||
message MsgBurnResponse {}
|
23
x/wrapped-a0gi-base/cli/query.go
Normal file
23
x/wrapped-a0gi-base/cli/query.go
Normal file
@ -0,0 +1,23 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
)
|
||||
|
||||
// GetQueryCmd returns the cli query commands for the inflation module.
|
||||
func GetQueryCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: types.ModuleName,
|
||||
Short: "Querying commands for the wrapped a0gi base module",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: client.ValidateCmd,
|
||||
}
|
||||
|
||||
cmd.AddCommand()
|
||||
|
||||
return cmd
|
||||
}
|
22
x/wrapped-a0gi-base/cli/tx.go
Normal file
22
x/wrapped-a0gi-base/cli/tx.go
Normal file
@ -0,0 +1,22 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// GetTxCmd returns the transaction commands for this module
|
||||
func GetTxCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: types.ModuleName,
|
||||
Short: fmt.Sprintf("%s transactions subcommands", types.ModuleName),
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: client.ValidateCmd,
|
||||
}
|
||||
cmd.AddCommand()
|
||||
return cmd
|
||||
}
|
25
x/wrapped-a0gi-base/genesis.go
Normal file
25
x/wrapped-a0gi-base/genesis.go
Normal file
@ -0,0 +1,25 @@
|
||||
package wrappeda0gibase
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/keeper"
|
||||
"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// InitGenesis initializes the store state from a genesis state.
|
||||
func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, gs types.GenesisState) {
|
||||
if err := gs.Validate(); err != nil {
|
||||
panic(fmt.Sprintf("failed to validate %s genesis state: %s", types.ModuleName, err))
|
||||
}
|
||||
keeper.SetWA0GIAddress(ctx, common.BytesToAddress(gs.WrappedA0GiAddress))
|
||||
}
|
||||
|
||||
// ExportGenesis returns a GenesisState for a given context and keeper.
|
||||
func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState {
|
||||
return &types.GenesisState{
|
||||
WrappedA0GiAddress: keeper.GetWA0GIAddress(ctx),
|
||||
}
|
||||
}
|
67
x/wrapped-a0gi-base/genesis_test.go
Normal file
67
x/wrapped-a0gi-base/genesis_test.go
Normal file
@ -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))
|
||||
}
|
8
x/wrapped-a0gi-base/keeper/abci.go
Normal file
8
x/wrapped-a0gi-base/keeper/abci.go
Normal file
@ -0,0 +1,8 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
func (k Keeper) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) {}
|
37
x/wrapped-a0gi-base/keeper/grpc_query.go
Normal file
37
x/wrapped-a0gi-base/keeper/grpc_query.go
Normal file
@ -0,0 +1,37 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
var _ types.QueryServer = Keeper{}
|
||||
|
||||
// MinterSupply implements types.QueryServer.
|
||||
func (k Keeper) MinterSupply(c context.Context, request *types.MinterSupplyRequest) (*types.MinterSupplyResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
account := common.BytesToAddress(request.Address)
|
||||
cap, err := k.getMinterCap(ctx, account)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
supply, err := k.getMinterSupply(ctx, account)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &types.MinterSupplyResponse{
|
||||
Cap: cap.Bytes(),
|
||||
Supply: supply.Bytes(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetWA0GI implements types.QueryServer.
|
||||
func (k Keeper) GetWA0GI(c context.Context, request *types.GetWA0GIRequest) (*types.GetWA0GIResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(c)
|
||||
return &types.GetWA0GIResponse{
|
||||
Address: k.GetWA0GIAddress(ctx),
|
||||
}, nil
|
||||
}
|
71
x/wrapped-a0gi-base/keeper/keeper.go
Normal file
71
x/wrapped-a0gi-base/keeper/keeper.go
Normal file
@ -0,0 +1,71 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
||||
precisebankkeeper "github.com/0glabs/0g-chain/x/precisebank/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/store/prefix"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
type Keeper struct {
|
||||
storeKey storetypes.StoreKey
|
||||
cdc codec.BinaryCodec
|
||||
pbkeeper precisebankkeeper.Keeper
|
||||
authority string // the address capable of changing signers params. Should be the gov module account
|
||||
}
|
||||
|
||||
// NewKeeper creates a new wrapped a0gi base keeper instance
|
||||
func NewKeeper(
|
||||
storeKey storetypes.StoreKey,
|
||||
cdc codec.BinaryCodec,
|
||||
pbkeeper precisebankkeeper.Keeper,
|
||||
authority string,
|
||||
) Keeper {
|
||||
return Keeper{
|
||||
storeKey: storeKey,
|
||||
cdc: cdc,
|
||||
pbkeeper: pbkeeper,
|
||||
authority: authority,
|
||||
}
|
||||
}
|
||||
|
||||
func (k Keeper) SetWA0GIAddress(ctx sdk.Context, addr common.Address) {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
store.Set(types.WA0GIKey, addr.Bytes())
|
||||
}
|
||||
|
||||
func (k Keeper) GetWA0GIAddress(ctx sdk.Context) []byte {
|
||||
store := ctx.KVStore(k.storeKey)
|
||||
bz := store.Get(types.WA0GIKey)
|
||||
return bz
|
||||
}
|
||||
|
||||
func (k Keeper) setMinterCap(ctx sdk.Context, account common.Address, cap *big.Int) error {
|
||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.MinterCapKeyPrefix)
|
||||
store.Set(account.Bytes(), cap.Bytes())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k Keeper) getMinterCap(ctx sdk.Context, account common.Address) (*big.Int, error) {
|
||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.MinterCapKeyPrefix)
|
||||
bz := store.Get(account.Bytes())
|
||||
return new(big.Int).SetBytes(bz), nil
|
||||
}
|
||||
|
||||
func (k Keeper) setMinterSupply(ctx sdk.Context, account common.Address, supply *big.Int) error {
|
||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.MinterSupplyKeyPrefix)
|
||||
store.Set(account.Bytes(), supply.Bytes())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k Keeper) getMinterSupply(ctx sdk.Context, account common.Address) (*big.Int, error) {
|
||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.MinterSupplyKeyPrefix)
|
||||
bz := store.Get(account.Bytes())
|
||||
return new(big.Int).SetBytes(bz), nil
|
||||
}
|
40
x/wrapped-a0gi-base/keeper/keeper_test.go
Normal file
40
x/wrapped-a0gi-base/keeper/keeper_test.go
Normal file
@ -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))
|
||||
}
|
96
x/wrapped-a0gi-base/keeper/msg_server.go
Normal file
96
x/wrapped-a0gi-base/keeper/msg_server.go
Normal file
@ -0,0 +1,96 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
precisebanktypes "github.com/0glabs/0g-chain/x/precisebank/types"
|
||||
"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
gov "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
var _ types.MsgServer = &Keeper{}
|
||||
|
||||
// Burn implements types.MsgServer.
|
||||
func (k Keeper) Burn(goCtx context.Context, msg *types.MsgBurn) (*types.MsgBurnResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
minter := common.BytesToAddress(msg.Minter)
|
||||
supply, err := k.getMinterSupply(ctx, minter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
amount := new(big.Int).SetBytes(msg.Amount)
|
||||
// check & update mint supply
|
||||
supply.Sub(supply, amount)
|
||||
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
|
||||
}
|
||||
|
||||
// Mint implements types.MsgServer.
|
||||
func (k Keeper) Mint(goCtx context.Context, msg *types.MsgMint) (*types.MsgMintResponse, 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
|
||||
}
|
||||
amount := new(big.Int).SetBytes(msg.Amount)
|
||||
// check & update mint supply
|
||||
supply.Add(supply, amount)
|
||||
if supply.Cmp(cap) > 0 {
|
||||
return nil, types.ErrInsufficientMintCap
|
||||
}
|
||||
// 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
|
||||
}
|
||||
|
||||
// SetMinterCap implements types.MsgServer.
|
||||
func (k Keeper) SetMinterCap(goCtx context.Context, msg *types.MsgSetMinterCap) (*types.MsgSetMinterCapResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
minter := common.BytesToAddress(msg.Minter)
|
||||
// validate authority
|
||||
if k.authority != msg.Authority {
|
||||
return nil, errorsmod.Wrapf(gov.ErrInvalidSigner, "expected %s got %s", k.authority, msg.Authority)
|
||||
}
|
||||
// update minter cap
|
||||
if err := k.setMinterCap(ctx, minter, new(big.Int).SetBytes(msg.Cap)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &types.MsgSetMinterCapResponse{}, nil
|
||||
}
|
||||
|
||||
// SetWA0GI implements types.MsgServer.
|
||||
func (k Keeper) SetWA0GI(goCtx context.Context, msg *types.MsgSetWA0GI) (*types.MsgSetWA0GIResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
// validate authority
|
||||
if k.authority != msg.Authority {
|
||||
return nil, errorsmod.Wrapf(gov.ErrInvalidSigner, "expected %s got %s", k.authority, msg.Authority)
|
||||
}
|
||||
// save new address
|
||||
k.SetWA0GIAddress(ctx, common.BytesToAddress(msg.Address))
|
||||
return &types.MsgSetWA0GIResponse{}, nil
|
||||
}
|
284
x/wrapped-a0gi-base/keeper/msg_server_test.go
Normal file
284
x/wrapped-a0gi-base/keeper/msg_server_test.go
Normal file
@ -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.MsgSetMinterCap{
|
||||
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.MsgSetMinterCap{
|
||||
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.MsgSetMinterCap{
|
||||
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.MsgSetMinterCap{
|
||||
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))
|
||||
}
|
168
x/wrapped-a0gi-base/module.go
Normal file
168
x/wrapped-a0gi-base/module.go
Normal file
@ -0,0 +1,168 @@
|
||||
package wrappeda0gibase
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/cli"
|
||||
"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/keeper"
|
||||
"github.com/0glabs/0g-chain/x/wrapped-a0gi-base/types"
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/module"
|
||||
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// consensusVersion defines the current x/council module consensus version.
|
||||
const consensusVersion = 1
|
||||
|
||||
// type check to ensure the interface is properly implemented
|
||||
var (
|
||||
_ module.AppModule = AppModule{}
|
||||
_ module.AppModuleBasic = AppModuleBasic{}
|
||||
)
|
||||
|
||||
// app module Basics object
|
||||
type AppModuleBasic struct{}
|
||||
|
||||
// Name returns the inflation module's name.
|
||||
func (AppModuleBasic) Name() string {
|
||||
return types.ModuleName
|
||||
}
|
||||
|
||||
// RegisterLegacyAminoCodec registers the inflation module's types on the given LegacyAmino codec.
|
||||
func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {}
|
||||
|
||||
// ConsensusVersion returns the consensus state-breaking version for the module.
|
||||
func (AppModuleBasic) ConsensusVersion() uint64 {
|
||||
return consensusVersion
|
||||
}
|
||||
|
||||
// RegisterInterfaces registers interfaces and implementations of the incentives
|
||||
// module.
|
||||
func (AppModuleBasic) RegisterInterfaces(interfaceRegistry codectypes.InterfaceRegistry) {
|
||||
types.RegisterInterfaces(interfaceRegistry)
|
||||
}
|
||||
|
||||
// DefaultGenesis returns default genesis state as raw bytes for the incentives
|
||||
// module.
|
||||
func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
|
||||
return cdc.MustMarshalJSON(types.DefaultGenesisState())
|
||||
}
|
||||
|
||||
// ValidateGenesis performs genesis state validation for the inflation module.
|
||||
func (b AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error {
|
||||
var genesisState types.GenesisState
|
||||
if err := cdc.UnmarshalJSON(bz, &genesisState); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)
|
||||
}
|
||||
|
||||
return genesisState.Validate()
|
||||
}
|
||||
|
||||
// RegisterRESTRoutes performs a no-op as the inflation module doesn't expose REST
|
||||
// endpoints
|
||||
func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {}
|
||||
|
||||
// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the inflation module.
|
||||
func (b AppModuleBasic) RegisterGRPCGatewayRoutes(c client.Context, serveMux *runtime.ServeMux) {
|
||||
if err := types.RegisterQueryHandlerClient(context.Background(), serveMux, types.NewQueryClient(c)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetTxCmd returns the root tx command for the inflation module.
|
||||
func (AppModuleBasic) GetTxCmd() *cobra.Command {
|
||||
return cli.GetTxCmd()
|
||||
}
|
||||
|
||||
// GetQueryCmd returns no root query command for the inflation module.
|
||||
func (AppModuleBasic) GetQueryCmd() *cobra.Command {
|
||||
return cli.GetQueryCmd()
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
|
||||
// AppModule implements an application module for the inflation module.
|
||||
type AppModule struct {
|
||||
AppModuleBasic
|
||||
keeper keeper.Keeper
|
||||
}
|
||||
|
||||
// NewAppModule creates a new AppModule Object
|
||||
func NewAppModule(
|
||||
k keeper.Keeper,
|
||||
) AppModule {
|
||||
return AppModule{
|
||||
AppModuleBasic: AppModuleBasic{},
|
||||
keeper: k,
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns the inflation module's name.
|
||||
func (AppModule) Name() string {
|
||||
return types.ModuleName
|
||||
}
|
||||
|
||||
// QuerierRoute returns wrapped a0gi base module's query routing key.
|
||||
func (AppModule) QuerierRoute() string { return types.QuerierRoute }
|
||||
|
||||
// RegisterInvariants registers the inflation module invariants.
|
||||
func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}
|
||||
|
||||
// RegisterServices registers a gRPC query service to respond to the
|
||||
// module-specific gRPC queries.
|
||||
func (am AppModule) RegisterServices(cfg module.Configurator) {
|
||||
types.RegisterMsgServer(cfg.MsgServer(), am.keeper)
|
||||
types.RegisterQueryServer(cfg.QueryServer(), am.keeper)
|
||||
}
|
||||
|
||||
func (am AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) {
|
||||
am.keeper.BeginBlock(ctx, req)
|
||||
}
|
||||
|
||||
func (am AppModule) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) []abci.ValidatorUpdate {
|
||||
// am.keeper.EndBlock(ctx, req)
|
||||
return []abci.ValidatorUpdate{}
|
||||
}
|
||||
|
||||
// InitGenesis performs genesis initialization for the inflation module. It returns
|
||||
// no validator updates.
|
||||
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate {
|
||||
var genesisState types.GenesisState
|
||||
|
||||
cdc.MustUnmarshalJSON(data, &genesisState)
|
||||
InitGenesis(ctx, am.keeper, genesisState)
|
||||
return []abci.ValidatorUpdate{}
|
||||
}
|
||||
|
||||
// ExportGenesis returns the exported genesis state as raw bytes for the inflation
|
||||
// module.
|
||||
func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage {
|
||||
gs := ExportGenesis(ctx, am.keeper)
|
||||
return cdc.MustMarshalJSON(gs)
|
||||
}
|
||||
|
||||
// ___________________________________________________________________________
|
||||
|
||||
// AppModuleSimulation functions
|
||||
|
||||
// GenerateGenesisState creates a randomized GenState of the inflation module.
|
||||
func (am AppModule) GenerateGenesisState(_ *module.SimulationState) {
|
||||
}
|
||||
|
||||
// RegisterStoreDecoder registers a decoder for inflation module's types.
|
||||
func (am AppModule) RegisterStoreDecoder(_ sdk.StoreDecoderRegistry) {
|
||||
}
|
||||
|
||||
// WeightedOperations doesn't return any inflation module operation.
|
||||
func (am AppModule) WeightedOperations(_ module.SimulationState) []simtypes.WeightedOperation {
|
||||
return []simtypes.WeightedOperation{}
|
||||
}
|
66
x/wrapped-a0gi-base/testutil/suite.go
Normal file
66
x/wrapped-a0gi-base/testutil/suite.go
Normal file
@ -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)
|
||||
}
|
25
x/wrapped-a0gi-base/testutil/types.go
Normal file
25
x/wrapped-a0gi-base/testutil/types.go
Normal file
@ -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))
|
||||
}
|
45
x/wrapped-a0gi-base/types/codec.go
Normal file
45
x/wrapped-a0gi-base/types/codec.go
Normal file
@ -0,0 +1,45 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/msgservice"
|
||||
)
|
||||
|
||||
var (
|
||||
amino = codec.NewLegacyAmino()
|
||||
// ModuleCdc references the global evm module codec. Note, the codec should
|
||||
// ONLY be used in certain instances of tests and for JSON encoding.
|
||||
ModuleCdc = codec.NewProtoCodec(codectypes.NewInterfaceRegistry())
|
||||
|
||||
// AminoCdc is a amino codec created to support amino JSON compatible msgs.
|
||||
AminoCdc = codec.NewAminoCodec(amino)
|
||||
)
|
||||
|
||||
const (
|
||||
// Amino names
|
||||
)
|
||||
|
||||
// NOTE: This is required for the GetSignBytes function
|
||||
func init() {
|
||||
RegisterLegacyAminoCodec(amino)
|
||||
amino.Seal()
|
||||
}
|
||||
|
||||
// RegisterInterfaces register implementations
|
||||
func RegisterInterfaces(registry codectypes.InterfaceRegistry) {
|
||||
registry.RegisterImplementations(
|
||||
(*sdk.Msg)(nil),
|
||||
&MsgSetWA0GI{},
|
||||
&MsgSetMinterCap{},
|
||||
&MsgMint{},
|
||||
&MsgBurn{},
|
||||
)
|
||||
|
||||
msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc)
|
||||
}
|
||||
|
||||
// RegisterLegacyAminoCodec required for EIP-712
|
||||
func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
|
||||
}
|
9
x/wrapped-a0gi-base/types/errors.go
Normal file
9
x/wrapped-a0gi-base/types/errors.go
Normal file
@ -0,0 +1,9 @@
|
||||
package types
|
||||
|
||||
import errorsmod "cosmossdk.io/errors"
|
||||
|
||||
var (
|
||||
ErrTxForbidden = errorsmod.Register(ModuleName, 1, "cosmos tx forbidden")
|
||||
ErrInsufficientMintCap = errorsmod.Register(ModuleName, 2, "insufficient mint cap")
|
||||
ErrInsufficientMintSupply = errorsmod.Register(ModuleName, 3, "insufficient mint supply")
|
||||
)
|
33
x/wrapped-a0gi-base/types/genesis.go
Normal file
33
x/wrapped-a0gi-base/types/genesis.go
Normal file
File diff suppressed because one or more lines are too long
328
x/wrapped-a0gi-base/types/genesis.pb.go
Normal file
328
x/wrapped-a0gi-base/types/genesis.pb.go
Normal file
@ -0,0 +1,328 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: zgc/wrappeda0gibase/genesis.proto
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
_ "github.com/cosmos/cosmos-proto"
|
||||
_ "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
_ "github.com/cosmos/gogoproto/gogoproto"
|
||||
proto "github.com/cosmos/gogoproto/proto"
|
||||
_ "google.golang.org/protobuf/types/known/timestamppb"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
// GenesisState defines the wrapped a0gi base module's genesis state.
|
||||
type GenesisState struct {
|
||||
// address of wrapped a0gi contract
|
||||
WrappedA0GiAddress []byte `protobuf:"bytes,1,opt,name=wrapped_a0gi_address,json=wrappedA0giAddress,proto3" json:"wrapped_a0gi_address,omitempty"`
|
||||
}
|
||||
|
||||
func (m *GenesisState) Reset() { *m = GenesisState{} }
|
||||
func (m *GenesisState) String() string { return proto.CompactTextString(m) }
|
||||
func (*GenesisState) ProtoMessage() {}
|
||||
func (*GenesisState) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_7e056019f61fd820, []int{0}
|
||||
}
|
||||
func (m *GenesisState) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *GenesisState) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GenesisState.Merge(m, src)
|
||||
}
|
||||
func (m *GenesisState) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *GenesisState) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GenesisState.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GenesisState proto.InternalMessageInfo
|
||||
|
||||
func (m *GenesisState) GetWrappedA0GiAddress() []byte {
|
||||
if m != nil {
|
||||
return m.WrappedA0GiAddress
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*GenesisState)(nil), "zgc.wrappeda0gibase.GenesisState")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("zgc/wrappeda0gibase/genesis.proto", fileDescriptor_7e056019f61fd820) }
|
||||
|
||||
var fileDescriptor_7e056019f61fd820 = []byte{
|
||||
// 246 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x90, 0xbd, 0x4e, 0xc3, 0x30,
|
||||
0x10, 0x80, 0xe3, 0x85, 0x21, 0xea, 0x14, 0x3a, 0xd0, 0x0e, 0xe6, 0x67, 0x62, 0x49, 0x6c, 0x09,
|
||||
0x1e, 0x80, 0xb2, 0xb0, 0x31, 0xc0, 0xc6, 0x12, 0xd9, 0x8e, 0xb9, 0x5a, 0x6a, 0x72, 0x56, 0xce,
|
||||
0x15, 0xb4, 0x4f, 0xc1, 0x63, 0x31, 0x76, 0x64, 0x44, 0xc9, 0x8b, 0xa0, 0xc4, 0x61, 0xc9, 0xe6,
|
||||
0xbb, 0xef, 0x93, 0xfc, 0xe9, 0xd2, 0xeb, 0x23, 0x18, 0xf1, 0xd1, 0x2a, 0xef, 0x6d, 0xa5, 0x24,
|
||||
0x38, 0xad, 0xc8, 0x0a, 0xb0, 0x8d, 0x25, 0x47, 0x85, 0x6f, 0x31, 0x60, 0x76, 0x7e, 0x04, 0x53,
|
||||
0xcc, 0x94, 0xf5, 0xca, 0x20, 0xd5, 0x48, 0xe5, 0xa8, 0x88, 0x38, 0x44, 0x7f, 0xbd, 0x04, 0x04,
|
||||
0x8c, 0xfb, 0xe1, 0x35, 0x6d, 0x57, 0x80, 0x08, 0x3b, 0x2b, 0xc6, 0x49, 0xef, 0xdf, 0x85, 0x6a,
|
||||
0x0e, 0x13, 0xba, 0x9c, 0xa3, 0xe0, 0x6a, 0x4b, 0x41, 0xd5, 0x3e, 0x0a, 0x37, 0x0f, 0xe9, 0xe2,
|
||||
0x29, 0x26, 0xbd, 0x06, 0x15, 0x6c, 0x26, 0xd3, 0xe5, 0xd4, 0x53, 0x0e, 0x41, 0xa5, 0xaa, 0xaa,
|
||||
0xd6, 0x12, 0x5d, 0xb0, 0x2b, 0x76, 0xbb, 0x78, 0xc9, 0x26, 0xb6, 0x91, 0xe0, 0x36, 0x91, 0x3c,
|
||||
0x3e, 0x7f, 0x77, 0x9c, 0x9d, 0x3a, 0xce, 0x7e, 0x3b, 0xce, 0xbe, 0x7a, 0x9e, 0x9c, 0x7a, 0x9e,
|
||||
0xfc, 0xf4, 0x3c, 0x79, 0xbb, 0x07, 0x17, 0xb6, 0x7b, 0x5d, 0x18, 0xac, 0x85, 0x84, 0x9d, 0xd2,
|
||||
0x24, 0x24, 0xe4, 0x66, 0xab, 0x5c, 0x23, 0x3e, 0xff, 0x2f, 0x93, 0x0f, 0xdf, 0xe4, 0xe3, 0x6d,
|
||||
0xc2, 0xc1, 0x5b, 0xd2, 0x67, 0x63, 0xd8, 0xdd, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xec, 0x50,
|
||||
0x04, 0x4c, 0x3f, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *GenesisState) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.WrappedA0GiAddress) > 0 {
|
||||
i -= len(m.WrappedA0GiAddress)
|
||||
copy(dAtA[i:], m.WrappedA0GiAddress)
|
||||
i = encodeVarintGenesis(dAtA, i, uint64(len(m.WrappedA0GiAddress)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovGenesis(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *GenesisState) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.WrappedA0GiAddress)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovGenesis(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovGenesis(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozGenesis(x uint64) (n int) {
|
||||
return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *GenesisState) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: GenesisState: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field WrappedA0GiAddress", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.WrappedA0GiAddress = append(m.WrappedA0GiAddress[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.WrappedA0GiAddress == nil {
|
||||
m.WrappedA0GiAddress = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipGenesis(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthGenesis
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipGenesis(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowGenesis
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthGenesis
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupGenesis
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthGenesis
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
27
x/wrapped-a0gi-base/types/keys.go
Normal file
27
x/wrapped-a0gi-base/types/keys.go
Normal file
@ -0,0 +1,27 @@
|
||||
package types
|
||||
|
||||
import "encoding/hex"
|
||||
|
||||
const (
|
||||
// ModuleName The name that will be used throughout the module
|
||||
ModuleName = "wrapped-a0gi-base"
|
||||
|
||||
// StoreKey Top level store key where all module items will be stored
|
||||
StoreKey = ModuleName
|
||||
|
||||
// QuerierRoute Top level query string
|
||||
QuerierRoute = ModuleName
|
||||
)
|
||||
|
||||
var (
|
||||
// prefix
|
||||
MinterCapKeyPrefix = []byte{0x00}
|
||||
MinterSupplyKeyPrefix = []byte{0x01}
|
||||
|
||||
// keys
|
||||
WA0GIKey = []byte{0x02}
|
||||
)
|
||||
|
||||
func GetMinterKeyFromAccount(account string) ([]byte, error) {
|
||||
return hex.DecodeString(account)
|
||||
}
|
70
x/wrapped-a0gi-base/types/msg.go
Normal file
70
x/wrapped-a0gi-base/types/msg.go
Normal file
@ -0,0 +1,70 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
var _, _, _, _ sdk.Msg = &MsgSetWA0GI{}, &MsgSetMinterCap{}, &MsgMint{}, &MsgBurn{}
|
||||
|
||||
func (msg *MsgSetWA0GI) GetSigners() []sdk.AccAddress {
|
||||
addr, _ := sdk.AccAddressFromBech32(msg.Authority)
|
||||
return []sdk.AccAddress{addr}
|
||||
}
|
||||
|
||||
func (msg *MsgSetWA0GI) ValidateBasic() error {
|
||||
if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil {
|
||||
return errorsmod.Wrap(err, "authority")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msg MsgSetWA0GI) GetSignBytes() []byte {
|
||||
return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg))
|
||||
}
|
||||
|
||||
func (msg *MsgSetMinterCap) GetSigners() []sdk.AccAddress {
|
||||
addr, _ := sdk.AccAddressFromBech32(msg.Authority)
|
||||
return []sdk.AccAddress{addr}
|
||||
}
|
||||
|
||||
func (msg *MsgSetMinterCap) ValidateBasic() error {
|
||||
if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil {
|
||||
return errorsmod.Wrap(err, "authority")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msg MsgSetMinterCap) GetSignBytes() []byte {
|
||||
return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg))
|
||||
}
|
||||
|
||||
func (msg *MsgMint) GetSigners() []sdk.AccAddress {
|
||||
return []sdk.AccAddress{}
|
||||
}
|
||||
|
||||
func (msg *MsgMint) ValidateBasic() error {
|
||||
// forbid mint from cosmos tx
|
||||
// it can only be called by wrapped a0gi from EVM
|
||||
return ErrTxForbidden
|
||||
}
|
||||
|
||||
func (msg MsgMint) GetSignBytes() []byte {
|
||||
return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg))
|
||||
}
|
||||
|
||||
func (msg *MsgBurn) GetSigners() []sdk.AccAddress {
|
||||
return []sdk.AccAddress{}
|
||||
}
|
||||
|
||||
func (msg *MsgBurn) ValidateBasic() error {
|
||||
// forbid burn from cosmos tx
|
||||
// it can only be called by wrapped a0gi from EVM
|
||||
return ErrTxForbidden
|
||||
}
|
||||
|
||||
func (msg MsgBurn) GetSignBytes() []byte {
|
||||
return sdk.MustSortJSON(AminoCdc.MustMarshalJSON(&msg))
|
||||
}
|
946
x/wrapped-a0gi-base/types/query.pb.go
Normal file
946
x/wrapped-a0gi-base/types/query.pb.go
Normal file
@ -0,0 +1,946 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: zgc/wrappeda0gibase/query.proto
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
context "context"
|
||||
fmt "fmt"
|
||||
_ "github.com/cosmos/cosmos-proto"
|
||||
_ "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
_ "github.com/cosmos/gogoproto/gogoproto"
|
||||
grpc1 "github.com/cosmos/gogoproto/grpc"
|
||||
proto "github.com/cosmos/gogoproto/proto"
|
||||
_ "google.golang.org/genproto/googleapis/api/annotations"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
_ "google.golang.org/protobuf/types/known/timestamppb"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type GetWA0GIRequest struct {
|
||||
}
|
||||
|
||||
func (m *GetWA0GIRequest) Reset() { *m = GetWA0GIRequest{} }
|
||||
func (m *GetWA0GIRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*GetWA0GIRequest) ProtoMessage() {}
|
||||
func (*GetWA0GIRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_19911faa2ec12c75, []int{0}
|
||||
}
|
||||
func (m *GetWA0GIRequest) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *GetWA0GIRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_GetWA0GIRequest.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *GetWA0GIRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GetWA0GIRequest.Merge(m, src)
|
||||
}
|
||||
func (m *GetWA0GIRequest) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *GetWA0GIRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GetWA0GIRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GetWA0GIRequest proto.InternalMessageInfo
|
||||
|
||||
type GetWA0GIResponse struct {
|
||||
Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
||||
}
|
||||
|
||||
func (m *GetWA0GIResponse) Reset() { *m = GetWA0GIResponse{} }
|
||||
func (m *GetWA0GIResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*GetWA0GIResponse) ProtoMessage() {}
|
||||
func (*GetWA0GIResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_19911faa2ec12c75, []int{1}
|
||||
}
|
||||
func (m *GetWA0GIResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *GetWA0GIResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_GetWA0GIResponse.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *GetWA0GIResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_GetWA0GIResponse.Merge(m, src)
|
||||
}
|
||||
func (m *GetWA0GIResponse) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *GetWA0GIResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_GetWA0GIResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_GetWA0GIResponse proto.InternalMessageInfo
|
||||
|
||||
type MinterSupplyRequest struct {
|
||||
Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
||||
}
|
||||
|
||||
func (m *MinterSupplyRequest) Reset() { *m = MinterSupplyRequest{} }
|
||||
func (m *MinterSupplyRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*MinterSupplyRequest) ProtoMessage() {}
|
||||
func (*MinterSupplyRequest) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_19911faa2ec12c75, []int{2}
|
||||
}
|
||||
func (m *MinterSupplyRequest) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *MinterSupplyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_MinterSupplyRequest.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *MinterSupplyRequest) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_MinterSupplyRequest.Merge(m, src)
|
||||
}
|
||||
func (m *MinterSupplyRequest) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *MinterSupplyRequest) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_MinterSupplyRequest.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_MinterSupplyRequest proto.InternalMessageInfo
|
||||
|
||||
type MinterSupplyResponse struct {
|
||||
Cap []byte `protobuf:"bytes,1,opt,name=cap,proto3" json:"cap,omitempty"`
|
||||
Supply []byte `protobuf:"bytes,2,opt,name=supply,proto3" json:"supply,omitempty"`
|
||||
}
|
||||
|
||||
func (m *MinterSupplyResponse) Reset() { *m = MinterSupplyResponse{} }
|
||||
func (m *MinterSupplyResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*MinterSupplyResponse) ProtoMessage() {}
|
||||
func (*MinterSupplyResponse) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_19911faa2ec12c75, []int{3}
|
||||
}
|
||||
func (m *MinterSupplyResponse) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *MinterSupplyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_MinterSupplyResponse.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *MinterSupplyResponse) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_MinterSupplyResponse.Merge(m, src)
|
||||
}
|
||||
func (m *MinterSupplyResponse) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *MinterSupplyResponse) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_MinterSupplyResponse.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_MinterSupplyResponse proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*GetWA0GIRequest)(nil), "zgc.wrappeda0gibase.GetWA0GIRequest")
|
||||
proto.RegisterType((*GetWA0GIResponse)(nil), "zgc.wrappeda0gibase.GetWA0GIResponse")
|
||||
proto.RegisterType((*MinterSupplyRequest)(nil), "zgc.wrappeda0gibase.MinterSupplyRequest")
|
||||
proto.RegisterType((*MinterSupplyResponse)(nil), "zgc.wrappeda0gibase.MinterSupplyResponse")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("zgc/wrappeda0gibase/query.proto", fileDescriptor_19911faa2ec12c75) }
|
||||
|
||||
var fileDescriptor_19911faa2ec12c75 = []byte{
|
||||
// 410 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0xc1, 0x6e, 0xd3, 0x30,
|
||||
0x18, 0xc7, 0x93, 0x22, 0x0a, 0xb2, 0x2a, 0x51, 0xdc, 0x0a, 0xb5, 0x11, 0x4a, 0x21, 0x50, 0x51,
|
||||
0x04, 0x89, 0x23, 0xe0, 0x01, 0x80, 0x4b, 0xc5, 0x81, 0x03, 0xe5, 0x80, 0xc4, 0x05, 0x39, 0xa9,
|
||||
0x71, 0x23, 0x35, 0xb1, 0x1b, 0x3b, 0xea, 0xda, 0xd3, 0xb4, 0x27, 0xa8, 0xb4, 0xf3, 0xde, 0xa7,
|
||||
0xc7, 0x4a, 0xbb, 0xec, 0xb8, 0xb5, 0x7b, 0x90, 0x29, 0x8e, 0xa3, 0x6d, 0x55, 0xb4, 0xed, 0xe6,
|
||||
0xff, 0xe7, 0xdf, 0xe7, 0xef, 0xef, 0xbf, 0x0d, 0x7a, 0x4b, 0x1a, 0xa2, 0x79, 0x8a, 0x39, 0x27,
|
||||
0x63, 0xec, 0xd3, 0x28, 0xc0, 0x82, 0xa0, 0x59, 0x46, 0xd2, 0x85, 0xc7, 0x53, 0x26, 0x19, 0x6c,
|
||||
0x2d, 0x69, 0xe8, 0xed, 0x01, 0x56, 0x37, 0x64, 0x22, 0x66, 0xe2, 0x9f, 0x42, 0x50, 0x21, 0x0a,
|
||||
0xde, 0x6a, 0x53, 0x46, 0x59, 0x51, 0xcf, 0x57, 0xba, 0xfa, 0x92, 0x32, 0x46, 0xa7, 0x04, 0x61,
|
||||
0x1e, 0x21, 0x9c, 0x24, 0x4c, 0x62, 0x19, 0xb1, 0xa4, 0xec, 0xe9, 0xea, 0x5d, 0xa5, 0x82, 0xec,
|
||||
0x3f, 0xc2, 0x89, 0x1e, 0x6f, 0xf5, 0xf6, 0xb7, 0x64, 0x14, 0x13, 0x21, 0x71, 0xcc, 0x0b, 0xc0,
|
||||
0x79, 0x0e, 0x9e, 0x0d, 0x89, 0xfc, 0xf3, 0xcd, 0x1f, 0xfe, 0x18, 0x91, 0x59, 0x46, 0x84, 0x74,
|
||||
0x3e, 0x82, 0xe6, 0x75, 0x49, 0x70, 0x96, 0x08, 0x02, 0x3b, 0xe0, 0x09, 0x1e, 0x8f, 0x53, 0x22,
|
||||
0x44, 0xc7, 0x7c, 0x65, 0x0e, 0x1a, 0xa3, 0x52, 0x3a, 0x08, 0xb4, 0x7e, 0x46, 0x89, 0x24, 0xe9,
|
||||
0xef, 0x8c, 0xf3, 0xe9, 0x42, 0x1f, 0x72, 0x47, 0xc3, 0x57, 0xd0, 0xbe, 0xdd, 0xa0, 0x47, 0x34,
|
||||
0xc1, 0xa3, 0x10, 0x73, 0x4d, 0xe7, 0x4b, 0xf8, 0x02, 0xd4, 0x85, 0x62, 0x3a, 0x35, 0x55, 0xd4,
|
||||
0xea, 0xd3, 0x49, 0x0d, 0x3c, 0xfe, 0x95, 0x67, 0x0c, 0x0f, 0x4d, 0xf0, 0xb4, 0xf4, 0x0a, 0xdf,
|
||||
0x7a, 0x15, 0x59, 0x7b, 0x7b, 0xb7, 0xb3, 0xfa, 0xf7, 0x50, 0x85, 0x1b, 0xe7, 0xdd, 0xd1, 0xe9,
|
||||
0xe5, 0x71, 0xed, 0x35, 0xec, 0x21, 0x9f, 0x96, 0x0f, 0xec, 0xe6, 0xb8, 0xab, 0x9e, 0x98, 0x12,
|
||||
0xe9, 0xce, 0x73, 0x09, 0x57, 0x26, 0x68, 0xdc, 0xbc, 0x0f, 0x1c, 0x54, 0x0e, 0xa8, 0xc8, 0xc8,
|
||||
0x7a, 0xff, 0x00, 0x52, 0xdb, 0xf9, 0xa0, 0xec, 0xf4, 0xe1, 0x9b, 0x6a, 0x3b, 0xb1, 0xea, 0x71,
|
||||
0x8b, 0x7c, 0xbe, 0x8f, 0xd6, 0x17, 0xb6, 0xb1, 0xde, 0xda, 0xe6, 0x66, 0x6b, 0x9b, 0xe7, 0x5b,
|
||||
0xdb, 0x5c, 0xed, 0x6c, 0x63, 0xb3, 0xb3, 0x8d, 0xb3, 0x9d, 0x6d, 0xfc, 0xfd, 0x42, 0x23, 0x39,
|
||||
0xc9, 0x02, 0x2f, 0x64, 0x31, 0xf2, 0xe9, 0x14, 0x07, 0x02, 0xf9, 0xd4, 0x0d, 0x27, 0x38, 0x4a,
|
||||
0xd0, 0x41, 0xc5, 0xd9, 0x72, 0xc1, 0x89, 0x08, 0xea, 0xea, 0xbb, 0x7c, 0xbe, 0x0a, 0x00, 0x00,
|
||||
0xff, 0xff, 0x14, 0xfb, 0x91, 0x88, 0xf1, 0x02, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ context.Context
|
||||
var _ grpc.ClientConn
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion4
|
||||
|
||||
// QueryClient is the client API for Query service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||
type QueryClient interface {
|
||||
GetWA0GI(ctx context.Context, in *GetWA0GIRequest, opts ...grpc.CallOption) (*GetWA0GIResponse, error)
|
||||
MinterSupply(ctx context.Context, in *MinterSupplyRequest, opts ...grpc.CallOption) (*MinterSupplyResponse, error)
|
||||
}
|
||||
|
||||
type queryClient struct {
|
||||
cc grpc1.ClientConn
|
||||
}
|
||||
|
||||
func NewQueryClient(cc grpc1.ClientConn) QueryClient {
|
||||
return &queryClient{cc}
|
||||
}
|
||||
|
||||
func (c *queryClient) GetWA0GI(ctx context.Context, in *GetWA0GIRequest, opts ...grpc.CallOption) (*GetWA0GIResponse, error) {
|
||||
out := new(GetWA0GIResponse)
|
||||
err := c.cc.Invoke(ctx, "/zgc.wrappeda0gibase.Query/GetWA0GI", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) MinterSupply(ctx context.Context, in *MinterSupplyRequest, opts ...grpc.CallOption) (*MinterSupplyResponse, error) {
|
||||
out := new(MinterSupplyResponse)
|
||||
err := c.cc.Invoke(ctx, "/zgc.wrappeda0gibase.Query/MinterSupply", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// QueryServer is the server API for Query service.
|
||||
type QueryServer interface {
|
||||
GetWA0GI(context.Context, *GetWA0GIRequest) (*GetWA0GIResponse, error)
|
||||
MinterSupply(context.Context, *MinterSupplyRequest) (*MinterSupplyResponse, error)
|
||||
}
|
||||
|
||||
// UnimplementedQueryServer can be embedded to have forward compatible implementations.
|
||||
type UnimplementedQueryServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedQueryServer) GetWA0GI(ctx context.Context, req *GetWA0GIRequest) (*GetWA0GIResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetWA0GI not implemented")
|
||||
}
|
||||
func (*UnimplementedQueryServer) MinterSupply(ctx context.Context, req *MinterSupplyRequest) (*MinterSupplyResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method MinterSupply not implemented")
|
||||
}
|
||||
|
||||
func RegisterQueryServer(s grpc1.Server, srv QueryServer) {
|
||||
s.RegisterService(&_Query_serviceDesc, srv)
|
||||
}
|
||||
|
||||
func _Query_GetWA0GI_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetWA0GIRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).GetWA0GI(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/zgc.wrappeda0gibase.Query/GetWA0GI",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).GetWA0GI(ctx, req.(*GetWA0GIRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_MinterSupply_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(MinterSupplyRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).MinterSupply(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/zgc.wrappeda0gibase.Query/MinterSupply",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).MinterSupply(ctx, req.(*MinterSupplyRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
var _Query_serviceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "zgc.wrappeda0gibase.Query",
|
||||
HandlerType: (*QueryServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetWA0GI",
|
||||
Handler: _Query_GetWA0GI_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "MinterSupply",
|
||||
Handler: _Query_MinterSupply_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "zgc/wrappeda0gibase/query.proto",
|
||||
}
|
||||
|
||||
func (m *GetWA0GIRequest) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *GetWA0GIRequest) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *GetWA0GIRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *GetWA0GIResponse) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *GetWA0GIResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *GetWA0GIResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Address) > 0 {
|
||||
i -= len(m.Address)
|
||||
copy(dAtA[i:], m.Address)
|
||||
i = encodeVarintQuery(dAtA, i, uint64(len(m.Address)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *MinterSupplyRequest) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *MinterSupplyRequest) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *MinterSupplyRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Address) > 0 {
|
||||
i -= len(m.Address)
|
||||
copy(dAtA[i:], m.Address)
|
||||
i = encodeVarintQuery(dAtA, i, uint64(len(m.Address)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func (m *MinterSupplyResponse) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *MinterSupplyResponse) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.Size()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *MinterSupplyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Supply) > 0 {
|
||||
i -= len(m.Supply)
|
||||
copy(dAtA[i:], m.Supply)
|
||||
i = encodeVarintQuery(dAtA, i, uint64(len(m.Supply)))
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
if len(m.Cap) > 0 {
|
||||
i -= len(m.Cap)
|
||||
copy(dAtA[i:], m.Cap)
|
||||
i = encodeVarintQuery(dAtA, i, uint64(len(m.Cap)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintQuery(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovQuery(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *GetWA0GIRequest) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *GetWA0GIResponse) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Address)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovQuery(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *MinterSupplyRequest) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Address)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovQuery(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *MinterSupplyResponse) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Cap)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovQuery(uint64(l))
|
||||
}
|
||||
l = len(m.Supply)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovQuery(uint64(l))
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovQuery(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozQuery(x uint64) (n int) {
|
||||
return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *GetWA0GIRequest) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: GetWA0GIRequest: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: GetWA0GIRequest: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipQuery(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *GetWA0GIResponse) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: GetWA0GIResponse: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: GetWA0GIResponse: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Address = append(m.Address[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.Address == nil {
|
||||
m.Address = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipQuery(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *MinterSupplyRequest) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: MinterSupplyRequest: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: MinterSupplyRequest: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Address = append(m.Address[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.Address == nil {
|
||||
m.Address = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipQuery(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *MinterSupplyResponse) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: MinterSupplyResponse: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: MinterSupplyResponse: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Cap", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Cap = append(m.Cap[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.Cap == nil {
|
||||
m.Cap = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Supply", wireType)
|
||||
}
|
||||
var byteLen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
byteLen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if byteLen < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
postIndex := iNdEx + byteLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Supply = append(m.Supply[:0], dAtA[iNdEx:postIndex]...)
|
||||
if m.Supply == nil {
|
||||
m.Supply = []byte{}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipQuery(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthQuery
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipQuery(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowQuery
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthQuery
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupQuery
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthQuery
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
236
x/wrapped-a0gi-base/types/query.pb.gw.go
Normal file
236
x/wrapped-a0gi-base/types/query.pb.gw.go
Normal file
@ -0,0 +1,236 @@
|
||||
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
|
||||
// source: zgc/wrappeda0gibase/query.proto
|
||||
|
||||
/*
|
||||
Package types is a reverse proxy.
|
||||
|
||||
It translates gRPC into RESTful JSON APIs.
|
||||
*/
|
||||
package types
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/golang/protobuf/descriptor"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/utilities"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// Suppress "imported and not used" errors
|
||||
var _ codes.Code
|
||||
var _ io.Reader
|
||||
var _ status.Status
|
||||
var _ = runtime.String
|
||||
var _ = utilities.NewDoubleArray
|
||||
var _ = descriptor.ForMessage
|
||||
var _ = metadata.Join
|
||||
|
||||
func request_Query_GetWA0GI_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GetWA0GIRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := client.GetWA0GI(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_GetWA0GI_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq GetWA0GIRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.GetWA0GI(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
filter_Query_MinterSupply_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
|
||||
)
|
||||
|
||||
func request_Query_MinterSupply_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq MinterSupplyRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_MinterSupply_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.MinterSupply(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Query_MinterSupply_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq MinterSupplyRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
if err := req.ParseForm(); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_MinterSupply_0); err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.MinterSupply(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterQueryHandlerServer registers the http handlers for service Query to "mux".
|
||||
// UnaryRPC :call QueryServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead.
|
||||
func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error {
|
||||
|
||||
mux.Handle("GET", pattern_Query_GetWA0GI_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Query_GetWA0GI_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_GetWA0GI_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_MinterSupply_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Query_MinterSupply_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_MinterSupply_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
conn, err := grpc.Dial(endpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
return RegisterQueryHandler(ctx, mux, conn)
|
||||
}
|
||||
|
||||
// RegisterQueryHandler registers the http handlers for service Query to "mux".
|
||||
// The handlers forward requests to the grpc endpoint over "conn".
|
||||
func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||
return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn))
|
||||
}
|
||||
|
||||
// RegisterQueryHandlerClient registers the http handlers for service Query
|
||||
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient".
|
||||
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient"
|
||||
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
|
||||
// "QueryClient" to call the correct interceptors.
|
||||
func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error {
|
||||
|
||||
mux.Handle("GET", pattern_Query_GetWA0GI_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Query_GetWA0GI_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_GetWA0GI_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Query_MinterSupply_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Query_MinterSupply_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Query_MinterSupply_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_Query_GetWA0GI_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"0g", "wrapped-a0gi-base", "get-wa0gi"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Query_MinterSupply_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"0g", "wrapped-a0gi-base", "minter-supply"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_Query_GetWA0GI_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Query_MinterSupply_0 = runtime.ForwardResponseMessage
|
||||
)
|
1719
x/wrapped-a0gi-base/types/tx.pb.go
Normal file
1719
x/wrapped-a0gi-base/types/tx.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user