github.com/Finschia/finschia-sdk@v0.48.1/x/foundation/keeper/internal/msg_server.go (about)

     1  package internal
     2  
     3  import (
     4  	"context"
     5  
     6  	sdk "github.com/Finschia/finschia-sdk/types"
     7  	sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
     8  	"github.com/Finschia/finschia-sdk/x/foundation"
     9  )
    10  
    11  const gasCostPerIteration = uint64(20)
    12  
    13  type msgServer struct {
    14  	keeper Keeper
    15  }
    16  
    17  // NewMsgServer returns an implementation of the token MsgServer interface
    18  // for the provided Keeper.
    19  func NewMsgServer(keeper Keeper) foundation.MsgServer {
    20  	return &msgServer{
    21  		keeper: keeper,
    22  	}
    23  }
    24  
    25  var _ foundation.MsgServer = msgServer{}
    26  
    27  // FundTreasury defines a method to fund the treasury.
    28  func (s msgServer) FundTreasury(c context.Context, req *foundation.MsgFundTreasury) (*foundation.MsgFundTreasuryResponse, error) {
    29  	ctx := sdk.UnwrapSDKContext(c)
    30  	from := sdk.MustAccAddressFromBech32(req.From)
    31  	if err := s.keeper.FundTreasury(ctx, from, req.Amount); err != nil {
    32  		return nil, err
    33  	}
    34  
    35  	if err := ctx.EventManager().EmitTypedEvent(&foundation.EventFundTreasury{
    36  		From:   req.From,
    37  		Amount: req.Amount,
    38  	}); err != nil {
    39  		panic(err)
    40  	}
    41  
    42  	return &foundation.MsgFundTreasuryResponse{}, nil
    43  }
    44  
    45  // WithdrawFromTreasury defines a method to withdraw coins from the treasury.
    46  func (s msgServer) WithdrawFromTreasury(c context.Context, req *foundation.MsgWithdrawFromTreasury) (*foundation.MsgWithdrawFromTreasuryResponse, error) {
    47  	ctx := sdk.UnwrapSDKContext(c)
    48  
    49  	if err := s.keeper.validateAuthority(req.Authority); err != nil {
    50  		return nil, err
    51  	}
    52  
    53  	to := sdk.MustAccAddressFromBech32(req.To)
    54  	if err := s.keeper.Accept(ctx, to, req); err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	if err := s.keeper.WithdrawFromTreasury(ctx, to, req.Amount); err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	if err := ctx.EventManager().EmitTypedEvent(&foundation.EventWithdrawFromTreasury{
    63  		To:     req.To,
    64  		Amount: req.Amount,
    65  	}); err != nil {
    66  		panic(err)
    67  	}
    68  
    69  	return &foundation.MsgWithdrawFromTreasuryResponse{}, nil
    70  }
    71  
    72  func (s msgServer) UpdateMembers(c context.Context, req *foundation.MsgUpdateMembers) (*foundation.MsgUpdateMembersResponse, error) {
    73  	ctx := sdk.UnwrapSDKContext(c)
    74  
    75  	if err := s.keeper.validateAuthority(req.Authority); err != nil {
    76  		return nil, err
    77  	}
    78  
    79  	if err := s.keeper.UpdateMembers(ctx, req.MemberUpdates); err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	if err := ctx.EventManager().EmitTypedEvent(&foundation.EventUpdateMembers{
    84  		MemberUpdates: req.MemberUpdates,
    85  	}); err != nil {
    86  		panic(err)
    87  	}
    88  
    89  	return &foundation.MsgUpdateMembersResponse{}, nil
    90  }
    91  
    92  func (s msgServer) UpdateDecisionPolicy(c context.Context, req *foundation.MsgUpdateDecisionPolicy) (*foundation.MsgUpdateDecisionPolicyResponse, error) {
    93  	ctx := sdk.UnwrapSDKContext(c)
    94  
    95  	if err := s.keeper.validateAuthority(req.Authority); err != nil {
    96  		return nil, err
    97  	}
    98  
    99  	policy := req.GetDecisionPolicy()
   100  	if err := s.keeper.UpdateDecisionPolicy(ctx, policy); err != nil {
   101  		return nil, err
   102  	}
   103  
   104  	event := &foundation.EventUpdateDecisionPolicy{}
   105  	if err := event.SetDecisionPolicy(policy); err != nil {
   106  		return nil, err
   107  	}
   108  	if err := ctx.EventManager().EmitTypedEvent(event); err != nil {
   109  		panic(err)
   110  	}
   111  
   112  	return &foundation.MsgUpdateDecisionPolicyResponse{}, nil
   113  }
   114  
   115  func (s msgServer) SubmitProposal(c context.Context, req *foundation.MsgSubmitProposal) (*foundation.MsgSubmitProposalResponse, error) {
   116  	ctx := sdk.UnwrapSDKContext(c)
   117  
   118  	if err := s.keeper.validateMembers(ctx, req.Proposers); err != nil {
   119  		return nil, err
   120  	}
   121  
   122  	id, err := s.keeper.SubmitProposal(ctx, req.Proposers, req.Metadata, req.GetMsgs())
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  
   127  	proposal, err := s.keeper.GetProposal(ctx, *id)
   128  	if err != nil {
   129  		panic(err)
   130  	}
   131  	if err := ctx.EventManager().EmitTypedEvent(&foundation.EventSubmitProposal{
   132  		Proposal: *proposal,
   133  	}); err != nil {
   134  		panic(err)
   135  	}
   136  
   137  	// Try to execute proposal immediately
   138  	if req.Exec == foundation.Exec_EXEC_TRY {
   139  		// Consider proposers as Yes votes
   140  		for _, proposer := range req.Proposers {
   141  			ctx.GasMeter().ConsumeGas(gasCostPerIteration, "vote on proposal")
   142  
   143  			vote := foundation.Vote{
   144  				ProposalId: *id,
   145  				Voter:      proposer,
   146  				Option:     foundation.VOTE_OPTION_YES,
   147  			}
   148  			err = s.keeper.Vote(ctx, vote)
   149  			if err != nil {
   150  				return &foundation.MsgSubmitProposalResponse{ProposalId: *id}, sdkerrors.Wrap(err, "The proposal was created but failed on vote")
   151  			}
   152  		}
   153  
   154  		// Then try to execute the proposal
   155  		if err = s.keeper.Exec(ctx, *id); err != nil {
   156  			return &foundation.MsgSubmitProposalResponse{ProposalId: *id}, sdkerrors.Wrap(err, "The proposal was created but failed on exec")
   157  		}
   158  	}
   159  
   160  	return &foundation.MsgSubmitProposalResponse{ProposalId: *id}, nil
   161  }
   162  
   163  func (s msgServer) WithdrawProposal(c context.Context, req *foundation.MsgWithdrawProposal) (*foundation.MsgWithdrawProposalResponse, error) {
   164  	ctx := sdk.UnwrapSDKContext(c)
   165  	id := req.ProposalId
   166  
   167  	proposal, err := s.keeper.GetProposal(ctx, id)
   168  	if err != nil {
   169  		return nil, err
   170  	}
   171  
   172  	// authority may withdraw any proposal.
   173  	if err := s.keeper.validateAuthority(req.Address); err != nil {
   174  		// check whether the address is in proposers list.
   175  		if err := validateActorForProposal(req.Address, *proposal); err != nil {
   176  			return nil, err
   177  		}
   178  	}
   179  
   180  	if err := s.keeper.WithdrawProposal(ctx, id); err != nil {
   181  		return nil, err
   182  	}
   183  
   184  	if err := ctx.EventManager().EmitTypedEvent(&foundation.EventWithdrawProposal{
   185  		ProposalId: id,
   186  	}); err != nil {
   187  		panic(err)
   188  	}
   189  
   190  	return &foundation.MsgWithdrawProposalResponse{}, nil
   191  }
   192  
   193  func (s msgServer) Vote(c context.Context, req *foundation.MsgVote) (*foundation.MsgVoteResponse, error) {
   194  	ctx := sdk.UnwrapSDKContext(c)
   195  
   196  	if err := s.keeper.validateMembers(ctx, []string{req.Voter}); err != nil {
   197  		return nil, err
   198  	}
   199  
   200  	vote := foundation.Vote{
   201  		ProposalId: req.ProposalId,
   202  		Voter:      req.Voter,
   203  		Option:     req.Option,
   204  		Metadata:   req.Metadata,
   205  	}
   206  	if err := s.keeper.Vote(ctx, vote); err != nil {
   207  		return nil, err
   208  	}
   209  
   210  	// Try to execute proposal immediately
   211  	if req.Exec == foundation.Exec_EXEC_TRY {
   212  		if err := s.keeper.Exec(ctx, req.ProposalId); err != nil {
   213  			return nil, err
   214  		}
   215  	}
   216  
   217  	return &foundation.MsgVoteResponse{}, nil
   218  }
   219  
   220  func (s msgServer) Exec(c context.Context, req *foundation.MsgExec) (*foundation.MsgExecResponse, error) {
   221  	ctx := sdk.UnwrapSDKContext(c)
   222  
   223  	if err := s.keeper.validateMembers(ctx, []string{req.Signer}); err != nil {
   224  		return nil, err
   225  	}
   226  
   227  	if err := s.keeper.Exec(ctx, req.ProposalId); err != nil {
   228  		return nil, err
   229  	}
   230  
   231  	return &foundation.MsgExecResponse{}, nil
   232  }
   233  
   234  func (s msgServer) LeaveFoundation(c context.Context, req *foundation.MsgLeaveFoundation) (*foundation.MsgLeaveFoundationResponse, error) {
   235  	ctx := sdk.UnwrapSDKContext(c)
   236  
   237  	if err := s.keeper.validateMembers(ctx, []string{req.Address}); err != nil {
   238  		return nil, err
   239  	}
   240  
   241  	update := foundation.MemberRequest{
   242  		Address: req.Address,
   243  		Remove:  true,
   244  	}
   245  	if err := s.keeper.UpdateMembers(ctx, []foundation.MemberRequest{update}); err != nil {
   246  		return nil, err
   247  	}
   248  
   249  	if err := ctx.EventManager().EmitTypedEvent(&foundation.EventLeaveFoundation{
   250  		Address: req.Address,
   251  	}); err != nil {
   252  		panic(err)
   253  	}
   254  
   255  	return &foundation.MsgLeaveFoundationResponse{}, nil
   256  }
   257  
   258  func (s msgServer) UpdateCensorship(c context.Context, req *foundation.MsgUpdateCensorship) (*foundation.MsgUpdateCensorshipResponse, error) {
   259  	ctx := sdk.UnwrapSDKContext(c)
   260  
   261  	url := req.Censorship.MsgTypeUrl
   262  	if err := s.keeper.validateCensorshipAuthority(ctx, url, req.Authority); err != nil {
   263  		return nil, err
   264  	}
   265  
   266  	if err := s.keeper.UpdateCensorship(ctx, req.Censorship); err != nil {
   267  		return nil, err
   268  	}
   269  
   270  	if err := ctx.EventManager().EmitTypedEvent(&foundation.EventUpdateCensorship{
   271  		Censorship: req.Censorship,
   272  	}); err != nil {
   273  		panic(err)
   274  	}
   275  
   276  	return &foundation.MsgUpdateCensorshipResponse{}, nil
   277  }
   278  
   279  func (s msgServer) Grant(c context.Context, req *foundation.MsgGrant) (*foundation.MsgGrantResponse, error) {
   280  	ctx := sdk.UnwrapSDKContext(c)
   281  
   282  	authorization := req.GetAuthorization()
   283  
   284  	url := authorization.MsgTypeURL()
   285  	if err := s.keeper.validateCensorshipAuthority(ctx, url, req.Authority); err != nil {
   286  		return nil, err
   287  	}
   288  
   289  	grantee := sdk.MustAccAddressFromBech32(req.Grantee)
   290  	if err := s.keeper.Grant(ctx, grantee, authorization); err != nil {
   291  		return nil, err
   292  	}
   293  
   294  	return &foundation.MsgGrantResponse{}, nil
   295  }
   296  
   297  func (s msgServer) Revoke(c context.Context, req *foundation.MsgRevoke) (*foundation.MsgRevokeResponse, error) {
   298  	ctx := sdk.UnwrapSDKContext(c)
   299  
   300  	url := req.MsgTypeUrl
   301  	if err := s.keeper.validateCensorshipAuthority(ctx, url, req.Authority); err != nil {
   302  		return nil, err
   303  	}
   304  
   305  	grantee := sdk.MustAccAddressFromBech32(req.Grantee)
   306  	if err := s.keeper.Revoke(ctx, grantee, req.MsgTypeUrl); err != nil {
   307  		return nil, err
   308  	}
   309  
   310  	return &foundation.MsgRevokeResponse{}, nil
   311  }