Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(x/ecocredit): add BurnRegen method #2107

Merged
merged 8 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
664 changes: 643 additions & 21 deletions api/regen/ecocredit/v1/events.pulsar.go

Large diffs are not rendered by default.

1,777 changes: 1,405 additions & 372 deletions api/regen/ecocredit/v1/tx.pulsar.go

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions api/regen/ecocredit/v1/tx_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions proto/regen/ecocredit/v1/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,15 @@ message EventBridgeReceive {
// Since Revision 3
OriginTx origin_tx = 4;
}

// EventBurnRegen is an event emitted when REGEN is burned to account for credit origination, transfer, etc.
message EventBurnRegen {
// burner is the address that burned REGEN.
string burner = 1;

// amount is the integer amount of uregen burned.
string amount = 2;

// reason is the reason for the burn.
string reason = 3;
}
29 changes: 29 additions & 0 deletions proto/regen/ecocredit/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,12 @@ service Msg {
// Since Revision 2
rpc RemoveAllowedBridgeChain(MsgRemoveAllowedBridgeChain)
returns (MsgRemoveAllowedBridgeChainResponse);


// BurnRegen burns REGEN tokens to account for platform fees when creating or transferring credits.
//
// Since Revision 3
rpc BurnRegen(MsgBurnRegen) returns (MsgBurnRegenResponse);
}

// MsgAddCreditType is the Msg/AddCreditType request type.
Expand Down Expand Up @@ -783,3 +789,26 @@ message MsgRemoveAllowedBridgeChain {
//
// Since Revision 2
message MsgRemoveAllowedBridgeChainResponse {}

// MsgBurnRegen is the Msg/BurnRegen request type.
//
// Since Revision 3
message MsgBurnRegen {
option (cosmos.msg.v1.signer) = "burner";

// burner is the address of the account burning REGEN tokens.
string burner = 1;

// amount is the integer amount of uregen tokens to burn.
string amount = 2;

// reason is any arbitrary string that specifies the reason for burning
// REGEN tokens. It may be at most 256 characters long.
string reason = 3;
}

// MsgBurnResponse is the Msg/Burn response type.
//
// Since Revision 3
message MsgBurnRegenResponse {}

2 changes: 0 additions & 2 deletions scripts/protocgen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,4 @@ cd ..
cp -r github.com/regen-network/regen-ledger/* ./
rm -rf github.com

go mod tidy

./scripts/protocgen2.sh
2 changes: 1 addition & 1 deletion scripts/protocgen2.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ set -eo pipefail
protoc_gen_install() {
go install github.com/cosmos/cosmos-proto/cmd/protoc-gen-go-pulsar@latest #2>/dev/null
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest #2>/dev/null
go install github.com/cosmos/cosmos-sdk/orm/cmd/protoc-gen-go-cosmos-orm@latest #2>/dev/null
go install github.com/cosmos/cosmos-sdk/orm/cmd/protoc-gen-go-cosmos-orm@v1.0.0-alpha.12 #2>/dev/null
}

protoc_gen_install
Expand Down
23 changes: 23 additions & 0 deletions x/ecocredit/base/keeper/features/msg_burn_regen.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Feature: Msg/Regen

Scenario: burning regen
Given the message
"""
{
"burner": "regen1depk54cuajgkzea6zpgkq36tnjwdzv4ak663u6",
"amount":"1000000000",
"reason":"for selling credits"
}
"""
Then expect "1000000000uregen" are sent from "regen1depk54cuajgkzea6zpgkq36tnjwdzv4ak663u6" to the ecocredit module
* expect "1000000000uregen" are burned by the ecocredit module
When it is executed
And expect the event is emitted
"""
{
"burner": "regen1depk54cuajgkzea6zpgkq36tnjwdzv4ak663u6",
"amount":"1000000000",
"reason":"for selling credits"
}
"""
And expect no error
49 changes: 49 additions & 0 deletions x/ecocredit/base/keeper/msg_burn_regen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package keeper

import (
"context"
"fmt"

"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/regen-network/regen-ledger/x/ecocredit/v3"
types "github.com/regen-network/regen-ledger/x/ecocredit/v3/base/types/v1"
)

func (k Keeper) BurnRegen(ctx context.Context, regen *types.MsgBurnRegen) (*types.MsgBurnRegenResponse, error) {
from, err := sdk.AccAddressFromBech32(regen.Burner)
if err != nil {
return nil, err
}

amount, ok := math.NewIntFromString(regen.Amount)
if !ok {
return nil, fmt.Errorf("invalid amount: %s", regen.Amount)
}
if !amount.IsPositive() {
return nil, fmt.Errorf("amount must be positive: %s", regen.Amount)
}

sdkCtx := sdk.UnwrapSDKContext(ctx)

coins := sdk.NewCoins(sdk.NewCoin("uregen", amount))

err = k.bankKeeper.SendCoinsFromAccountToModule(sdkCtx, from, ecocredit.ModuleName, coins)
if err != nil {
return nil, err
}

err = k.bankKeeper.BurnCoins(sdkCtx, ecocredit.ModuleName, coins)
if err != nil {
return nil, err
}

err = sdkCtx.EventManager().EmitTypedEvent(&types.EventBurnRegen{
Burner: regen.Burner,
Amount: regen.Amount,
Reason: regen.Reason,
})

return &types.MsgBurnRegenResponse{}, err
}
67 changes: 67 additions & 0 deletions x/ecocredit/base/keeper/msg_burn_regen_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package keeper

import (
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/gogo/protobuf/jsonpb"
"github.com/regen-network/gocuke"
"github.com/stretchr/testify/require"

"github.com/regen-network/regen-ledger/types/v2/testutil"
"github.com/regen-network/regen-ledger/x/ecocredit/v3"
types "github.com/regen-network/regen-ledger/x/ecocredit/v3/base/types/v1"
)

type burnRegenSuite struct {
*baseSuite
msg *types.MsgBurnRegen
err error
}

func TestBurnRegen(t *testing.T) {
gocuke.NewRunner(t, &burnRegenSuite{}).Path("./features/msg_burn_regen.feature").Run()
}

func (s *burnRegenSuite) Before(t gocuke.TestingT) {
s.baseSuite = setupBase(t)
}

func (s *burnRegenSuite) TheMessage(a gocuke.DocString) {
s.msg = &types.MsgBurnRegen{}
err := jsonpb.UnmarshalString(a.Content, s.msg)
require.NoError(s.t, err)
}
func (s *burnRegenSuite) ItIsExecuted() {
_, s.err = s.k.BurnRegen(s.ctx, s.msg)
}

func (s *burnRegenSuite) ExpectAreSentFromToTheEcocreditModule(coinsStr, addrStr string) {
coins, err := sdk.ParseCoinsNormalized(coinsStr)
require.NoError(s.t, err)
addr, err := sdk.AccAddressFromBech32(addrStr)
require.NoError(s.t, err)
s.bankKeeper.EXPECT().SendCoinsFromAccountToModule(s.ctx, addr, ecocredit.ModuleName, coins).Return(nil)
}

func (s *burnRegenSuite) ExpectAreBurnedByTheEcocreditModule(coinsStr string) {
coins, err := sdk.ParseCoinsNormalized(coinsStr)
require.NoError(s.t, err)
s.bankKeeper.EXPECT().BurnCoins(s.ctx, ecocredit.ModuleName, coins).Return(nil)
}

func (s *burnRegenSuite) ExpectTheEventIsEmitted(a gocuke.DocString) {
event := &types.EventBurnRegen{}
err := jsonpb.UnmarshalString(a.Content, event)
require.NoError(s.t, err)

sdkEvent, found := testutil.GetEvent(event, s.sdkCtx.EventManager().Events())
require.True(s.t, found)

err = testutil.MatchEvent(event, sdkEvent)
require.NoError(s.t, err)
}

func (s *burnRegenSuite) ExpectNoError() {
require.NoError(s.t, s.err)
}
Loading
Loading