package app
import (
"encoding/json"
wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
)
type ProofExemptDecorator struct {
inner ante.DeductFeeDecorator
exemptContracts map[string]struct{}
}
func NewProofExemptDecorator(
opts ante.HandlerOptions,
exemptContracts []string,
) ProofExemptDecorator {
contracts := make(map[string]struct{}, len(exemptContracts))
for _, c := range exemptContracts {
if c != "" {
contracts[c] = struct{}{}
}
}
return ProofExemptDecorator{
inner: ante.NewDeductFeeDecorator(opts.AccountKeeper, opts.BankKeeper, opts.FeegrantKeeper, opts.TxFeeChecker),
exemptContracts: contracts,
}
}
func (d ProofExemptDecorator) AnteHandle(
ctx sdk.Context,
tx sdk.Tx,
simulate bool,
next sdk.AnteHandler,
) (sdk.Context, error) {
if d.isProofSubmission(tx) {
return next(ctx, tx, simulate)
}
return d.inner.AnteHandle(ctx, tx, simulate, next)
}
func (d ProofExemptDecorator) isProofSubmission(tx sdk.Tx) bool {
if len(d.exemptContracts) == 0 {
return false
}
msgs := tx.GetMsgs()
if len(msgs) == 0 {
return false
}
for _, msg := range msgs {
execMsg, ok := msg.(*wasmtypes.MsgExecuteContract)
if !ok {
return false
}
if _, exempt := d.exemptContracts[execMsg.Contract]; !exempt {
return false
}
var payload map[string]json.RawMessage
if err := json.Unmarshal(execMsg.Msg, &payload); err != nil {
return false
}
if _, ok := payload["submit_proof"]; !ok {
return false
}
}
return true
}