github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/evm/types/proposal.go (about)

     1  package types
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     8  	"github.com/fibonacci-chain/fbc/libs/tendermint/global"
     9  	"github.com/fibonacci-chain/fbc/libs/tendermint/types"
    10  	govtypes "github.com/fibonacci-chain/fbc/x/gov/types"
    11  )
    12  
    13  const (
    14  	maxAddressListLength = 100
    15  	// proposalTypeManageContractDeploymentWhitelist defines the type for a ManageContractDeploymentWhitelist
    16  	proposalTypeManageContractDeploymentWhitelist = "ManageContractDeploymentWhitelist"
    17  	// proposalTypeManageContractBlockedList defines the type for a ManageContractBlockedListProposal
    18  	proposalTypeManageContractBlockedList = "ManageContractBlockedList"
    19  	// proposalTypeManageContractMethodBlockedList defines the type for a ManageContractMethodBlockedList
    20  	proposalTypeManageContractMethodBlockedList = "ManageContractMethodBlockedList"
    21  	// proposalTypeManageSysContractAddress defines the type for a ManageSysContractAddress
    22  	proposalTypeManageSysContractAddress = "ManageSysContractAddress"
    23  	proposalTypeManageContractByteCode   = "ManageContractByteCode"
    24  )
    25  
    26  func init() {
    27  	govtypes.RegisterProposalType(proposalTypeManageContractDeploymentWhitelist)
    28  	govtypes.RegisterProposalType(proposalTypeManageContractBlockedList)
    29  	govtypes.RegisterProposalType(proposalTypeManageContractMethodBlockedList)
    30  	govtypes.RegisterProposalType(proposalTypeManageSysContractAddress)
    31  	govtypes.RegisterProposalType(proposalTypeManageContractByteCode)
    32  
    33  	govtypes.RegisterProposalTypeCodec(ManageContractDeploymentWhitelistProposal{}, "fbexchain/evm/ManageContractDeploymentWhitelistProposal")
    34  	govtypes.RegisterProposalTypeCodec(ManageContractBlockedListProposal{}, "fbexchain/evm/ManageContractBlockedListProposal")
    35  	govtypes.RegisterProposalTypeCodec(ManageContractMethodBlockedListProposal{}, "fbexchain/evm/ManageContractMethodBlockedListProposal")
    36  	govtypes.RegisterProposalTypeCodec(ManageSysContractAddressProposal{}, "fbexchain/evm/ManageSysContractAddressProposal")
    37  	govtypes.RegisterProposalTypeCodec(ManageContractByteCodeProposal{}, "fbexchain/evm/ManageContractBytecode")
    38  
    39  }
    40  
    41  var (
    42  	_ govtypes.Content = (*ManageContractDeploymentWhitelistProposal)(nil)
    43  	_ govtypes.Content = (*ManageContractBlockedListProposal)(nil)
    44  	_ govtypes.Content = (*ManageContractMethodBlockedListProposal)(nil)
    45  	_ govtypes.Content = (*ManageSysContractAddressProposal)(nil)
    46  	_ govtypes.Content = (*ManageContractByteCodeProposal)(nil)
    47  )
    48  
    49  // ManageContractDeploymentWhitelistProposal - structure for the proposal to add or delete deployer addresses from whitelist
    50  type ManageContractDeploymentWhitelistProposal struct {
    51  	Title            string      `json:"title" yaml:"title"`
    52  	Description      string      `json:"description" yaml:"description"`
    53  	DistributorAddrs AddressList `json:"distributor_addresses" yaml:"distributor_addresses"`
    54  	IsAdded          bool        `json:"is_added" yaml:"is_added"`
    55  }
    56  
    57  // NewManageContractDeploymentWhitelistProposal creates a new instance of ManageContractDeploymentWhitelistProposal
    58  func NewManageContractDeploymentWhitelistProposal(title, description string, distributorAddrs []sdk.AccAddress, isAdded bool,
    59  ) ManageContractDeploymentWhitelistProposal {
    60  	return ManageContractDeploymentWhitelistProposal{
    61  		Title:            title,
    62  		Description:      description,
    63  		DistributorAddrs: distributorAddrs,
    64  		IsAdded:          isAdded,
    65  	}
    66  }
    67  
    68  // GetTitle returns title of a manage contract deployment whitelist proposal object
    69  func (mp ManageContractDeploymentWhitelistProposal) GetTitle() string {
    70  	return mp.Title
    71  }
    72  
    73  // GetDescription returns description of a manage contract deployment whitelist proposal object
    74  func (mp ManageContractDeploymentWhitelistProposal) GetDescription() string {
    75  	return mp.Description
    76  }
    77  
    78  // ProposalRoute returns route key of a manage contract deployment whitelist proposal object
    79  func (mp ManageContractDeploymentWhitelistProposal) ProposalRoute() string {
    80  	return RouterKey
    81  }
    82  
    83  // ProposalType returns type of a manage contract deployment whitelist proposal object
    84  func (mp ManageContractDeploymentWhitelistProposal) ProposalType() string {
    85  	return proposalTypeManageContractDeploymentWhitelist
    86  }
    87  
    88  // ValidateBasic validates a manage contract deployment whitelist proposal
    89  func (mp ManageContractDeploymentWhitelistProposal) ValidateBasic() sdk.Error {
    90  	if len(strings.TrimSpace(mp.Title)) == 0 {
    91  		return govtypes.ErrInvalidProposalContent("title is required")
    92  	}
    93  	if len(mp.Title) > govtypes.MaxTitleLength {
    94  		return govtypes.ErrInvalidProposalContent("title length is longer than the maximum title length")
    95  	}
    96  
    97  	if len(mp.Description) == 0 {
    98  		return govtypes.ErrInvalidProposalContent("description is required")
    99  	}
   100  
   101  	if len(mp.Description) > govtypes.MaxDescriptionLength {
   102  		return govtypes.ErrInvalidProposalContent("description length is longer than the maximum description length")
   103  	}
   104  
   105  	if mp.ProposalType() != proposalTypeManageContractDeploymentWhitelist {
   106  		return govtypes.ErrInvalidProposalType(mp.ProposalType())
   107  	}
   108  
   109  	distributorAddrLen := len(mp.DistributorAddrs)
   110  	if distributorAddrLen == 0 {
   111  		return ErrEmptyAddressList
   112  	}
   113  
   114  	if distributorAddrLen > maxAddressListLength {
   115  		return ErrOversizeAddrList(distributorAddrLen)
   116  	}
   117  
   118  	if isAddrDuplicated(mp.DistributorAddrs) {
   119  		return ErrDuplicatedAddr
   120  	}
   121  
   122  	return nil
   123  }
   124  
   125  // String returns a human readable string representation of a ManageContractDeploymentWhitelistProposal
   126  func (mp ManageContractDeploymentWhitelistProposal) String() string {
   127  	var builder strings.Builder
   128  	builder.WriteString(
   129  		fmt.Sprintf(`ManageContractDeploymentWhitelistProposal:
   130   Title:					%s
   131   Description:        	%s
   132   Type:                	%s
   133   IsAdded:				%t
   134   DistributorAddrs:
   135  `,
   136  			mp.Title, mp.Description, mp.ProposalType(), mp.IsAdded),
   137  	)
   138  
   139  	for i := 0; i < len(mp.DistributorAddrs); i++ {
   140  		builder.WriteString("\t\t\t\t\t\t")
   141  		builder.WriteString(mp.DistributorAddrs[i].String())
   142  		builder.Write([]byte{'\n'})
   143  	}
   144  
   145  	return strings.TrimSpace(builder.String())
   146  }
   147  
   148  func isAddrDuplicated(addrs []sdk.AccAddress) bool {
   149  	lenAddrs := len(addrs)
   150  	filter := make(map[string]struct{}, lenAddrs)
   151  	for i := 0; i < lenAddrs; i++ {
   152  		key := addrs[i].String()
   153  		if _, ok := filter[key]; ok {
   154  			return true
   155  		}
   156  		filter[key] = struct{}{}
   157  	}
   158  
   159  	return false
   160  }
   161  
   162  // ManageContractBlockedListProposal - structure for the proposal to add or delete a contract address from blocked list
   163  type ManageContractBlockedListProposal struct {
   164  	Title         string      `json:"title" yaml:"title"`
   165  	Description   string      `json:"description" yaml:"description"`
   166  	ContractAddrs AddressList `json:"contract_addresses" yaml:"contract_addresses"`
   167  	IsAdded       bool        `json:"is_added" yaml:"is_added"`
   168  }
   169  
   170  // NewManageContractBlockedListProposal creates a new instance of ManageContractBlockedListProposal
   171  func NewManageContractBlockedListProposal(title, description string, contractAddrs AddressList, isAdded bool,
   172  ) ManageContractBlockedListProposal {
   173  	return ManageContractBlockedListProposal{
   174  		Title:         title,
   175  		Description:   description,
   176  		ContractAddrs: contractAddrs,
   177  		IsAdded:       isAdded,
   178  	}
   179  }
   180  
   181  // GetTitle returns title of a manage contract blocked list proposal object
   182  func (mp ManageContractBlockedListProposal) GetTitle() string {
   183  	return mp.Title
   184  }
   185  
   186  // GetDescription returns description of a manage contract blocked list proposal object
   187  func (mp ManageContractBlockedListProposal) GetDescription() string {
   188  	return mp.Description
   189  }
   190  
   191  // ProposalRoute returns route key of a manage contract blocked list proposal object
   192  func (mp ManageContractBlockedListProposal) ProposalRoute() string {
   193  	return RouterKey
   194  }
   195  
   196  // ProposalType returns type of a manage contract blocked list proposal object
   197  func (mp ManageContractBlockedListProposal) ProposalType() string {
   198  	return proposalTypeManageContractBlockedList
   199  }
   200  
   201  // ValidateBasic validates a manage contract blocked list proposal
   202  func (mp ManageContractBlockedListProposal) ValidateBasic() sdk.Error {
   203  	if len(strings.TrimSpace(mp.Title)) == 0 {
   204  		return govtypes.ErrInvalidProposalContent("title is required")
   205  	}
   206  	if len(mp.Title) > govtypes.MaxTitleLength {
   207  		return govtypes.ErrInvalidProposalContent("title length is longer than the maximum title length")
   208  	}
   209  
   210  	if len(mp.Description) == 0 {
   211  		return govtypes.ErrInvalidProposalContent("description is required")
   212  	}
   213  
   214  	if len(mp.Description) > govtypes.MaxDescriptionLength {
   215  		return govtypes.ErrInvalidProposalContent("description length is longer than the maximum description length")
   216  	}
   217  
   218  	if mp.ProposalType() != proposalTypeManageContractBlockedList {
   219  		return govtypes.ErrInvalidProposalType(mp.ProposalType())
   220  	}
   221  
   222  	contractAddrLen := len(mp.ContractAddrs)
   223  	if contractAddrLen == 0 {
   224  		return ErrEmptyAddressList
   225  	}
   226  
   227  	if contractAddrLen > maxAddressListLength {
   228  		return ErrOversizeAddrList(contractAddrLen)
   229  	}
   230  
   231  	if isAddrDuplicated(mp.ContractAddrs) {
   232  		return ErrDuplicatedAddr
   233  	}
   234  
   235  	return nil
   236  }
   237  
   238  // String returns a human readable string representation of a ManageContractBlockedListProposal
   239  func (mp ManageContractBlockedListProposal) String() string {
   240  	var builder strings.Builder
   241  	builder.WriteString(
   242  		fmt.Sprintf(`ManageContractBlockedListProposal:
   243   Title:					%s
   244   Description:        	%s
   245   Type:                	%s
   246   IsAdded:				%t
   247   ContractAddrs:
   248  `,
   249  			mp.Title, mp.Description, mp.ProposalType(), mp.IsAdded),
   250  	)
   251  
   252  	for i := 0; i < len(mp.ContractAddrs); i++ {
   253  		builder.WriteString("\t\t\t\t\t\t")
   254  		builder.WriteString(mp.ContractAddrs[i].String())
   255  		builder.Write([]byte{'\n'})
   256  	}
   257  
   258  	return strings.TrimSpace(builder.String())
   259  }
   260  
   261  // ManageContractMethodBlockedListProposal - structure for the proposal to add or delete a contract method from blocked list
   262  type ManageContractMethodBlockedListProposal struct {
   263  	Title        string              `json:"title" yaml:"title"`
   264  	Description  string              `json:"description" yaml:"description"`
   265  	ContractList BlockedContractList `json:"contract_addresses" yaml:"contract_addresses"`
   266  	IsAdded      bool                `json:"is_added" yaml:"is_added"`
   267  }
   268  
   269  // NewManageContractMethodBlockedListProposal creates a new instance of ManageContractMethodBlockedListProposal
   270  func NewManageContractMethodBlockedListProposal(title, description string, contractList BlockedContractList, isAdded bool,
   271  ) ManageContractMethodBlockedListProposal {
   272  	return ManageContractMethodBlockedListProposal{
   273  		Title:        title,
   274  		Description:  description,
   275  		ContractList: contractList,
   276  		IsAdded:      isAdded,
   277  	}
   278  }
   279  
   280  // GetTitle returns title of a manage contract blocked list proposal object
   281  func (mp ManageContractMethodBlockedListProposal) GetTitle() string {
   282  	return mp.Title
   283  }
   284  
   285  // GetDescription returns description of a manage contract blocked list proposal object
   286  func (mp ManageContractMethodBlockedListProposal) GetDescription() string {
   287  	return mp.Description
   288  }
   289  
   290  // ProposalRoute returns route key of a manage contract blocked list proposal object
   291  func (mp ManageContractMethodBlockedListProposal) ProposalRoute() string {
   292  	return RouterKey
   293  }
   294  
   295  // ProposalType returns type of a manage contract blocked list proposal object
   296  func (mp ManageContractMethodBlockedListProposal) ProposalType() string {
   297  	return proposalTypeManageContractMethodBlockedList
   298  }
   299  
   300  // ValidateBasic validates a manage contract blocked list proposal
   301  func (mp ManageContractMethodBlockedListProposal) ValidateBasic() sdk.Error {
   302  	if len(strings.TrimSpace(mp.Title)) == 0 {
   303  		return govtypes.ErrInvalidProposalContent("title is required")
   304  	}
   305  	if len(mp.Title) > govtypes.MaxTitleLength {
   306  		return govtypes.ErrInvalidProposalContent("title length is longer than the maximum title length")
   307  	}
   308  
   309  	if len(mp.Description) == 0 {
   310  		return govtypes.ErrInvalidProposalContent("description is required")
   311  	}
   312  
   313  	if len(mp.Description) > govtypes.MaxDescriptionLength {
   314  		return govtypes.ErrInvalidProposalContent("description length is longer than the maximum description length")
   315  	}
   316  
   317  	if mp.ProposalType() != proposalTypeManageContractMethodBlockedList {
   318  		return govtypes.ErrInvalidProposalType(mp.ProposalType())
   319  	}
   320  
   321  	contractAddrLen := len(mp.ContractList)
   322  	if contractAddrLen == 0 {
   323  		return ErrEmptyAddressList
   324  	}
   325  
   326  	if contractAddrLen > maxAddressListLength {
   327  		return ErrOversizeAddrList(contractAddrLen)
   328  	}
   329  
   330  	if err := mp.ContractList.ValidateBasic(); err != nil {
   331  		return err
   332  	}
   333  
   334  	return nil
   335  }
   336  
   337  // String returns a human readable string representation of a ManageContractMethodBlockedListProposal
   338  func (mp ManageContractMethodBlockedListProposal) String() string {
   339  	var builder strings.Builder
   340  	builder.WriteString(
   341  		fmt.Sprintf(`ManageContractMethodBlockedListProposal:
   342   Title:					%s
   343   Description:        	%s
   344   Type:                	%s
   345   IsAdded:				%t
   346   ContractList:
   347  `,
   348  			mp.Title, mp.Description, mp.ProposalType(), mp.IsAdded),
   349  	)
   350  
   351  	for i := 0; i < len(mp.ContractList); i++ {
   352  		builder.WriteString("\t\t\t\t\t\t")
   353  		builder.WriteString(mp.ContractList[i].String())
   354  		builder.Write([]byte{'\n'})
   355  	}
   356  
   357  	return strings.TrimSpace(builder.String())
   358  }
   359  
   360  // FixShortAddr is to fix the short address problem in the OKC test-net.
   361  // The normal len(BlockedContract.Address) should be 20,
   362  // but there are some BlockedContract.Address in OKC test-net that have a length of 4.
   363  // The fix is to pad the leading bits of the short address with zeros until the length is 20.
   364  func (mp *ManageContractMethodBlockedListProposal) FixShortAddr() {
   365  	for i := 0; i < len(mp.ContractList); i++ {
   366  		if len(mp.ContractList[i].Address) < 20 {
   367  			validAddress := make([]byte, 20-len(mp.ContractList[i].Address), 20)
   368  			validAddress = append(validAddress, mp.ContractList[i].Address...)
   369  			mp.ContractList[i].Address = validAddress
   370  		}
   371  	}
   372  }
   373  
   374  type ManageSysContractAddressProposal struct {
   375  	Title       string `json:"title" yaml:"title"`
   376  	Description string `json:"description" yaml:"description"`
   377  	// Contract Address
   378  	ContractAddr sdk.AccAddress `json:"contract_address" yaml:"contract_address"`
   379  	IsAdded      bool           `json:"is_added" yaml:"is_added"`
   380  }
   381  
   382  // NewManageSysContractAddressProposal creates a new instance of NewManageSysContractAddressProposal
   383  func NewManageSysContractAddressProposal(title, description string, addr sdk.AccAddress, isAdded bool,
   384  ) ManageSysContractAddressProposal {
   385  	return ManageSysContractAddressProposal{
   386  		Title:        title,
   387  		Description:  description,
   388  		ContractAddr: addr,
   389  		IsAdded:      isAdded,
   390  	}
   391  }
   392  
   393  // GetTitle returns title of a manage system contract address proposal object
   394  func (mp ManageSysContractAddressProposal) GetTitle() string {
   395  	return mp.Title
   396  }
   397  
   398  // GetDescription returns description of a manage system contract address proposal object
   399  func (mp ManageSysContractAddressProposal) GetDescription() string {
   400  	return mp.Description
   401  }
   402  
   403  // ProposalRoute returns route key of a manage system contract address proposal object
   404  func (mp ManageSysContractAddressProposal) ProposalRoute() string {
   405  	return RouterKey
   406  }
   407  
   408  // ProposalType returns type of a manage system contract address proposal object
   409  func (mp ManageSysContractAddressProposal) ProposalType() string {
   410  	return proposalTypeManageSysContractAddress
   411  }
   412  
   413  // ValidateBasic validates a manage system contract address proposal
   414  func (mp ManageSysContractAddressProposal) ValidateBasic() sdk.Error {
   415  	//will delete it after upgrade venus3
   416  	if global.GetGlobalHeight() > 0 && !types.HigherThanVenus3(global.GetGlobalHeight()) {
   417  		return govtypes.ErrInvalidProposalContent("not support system contract address proposal")
   418  	}
   419  
   420  	if len(strings.TrimSpace(mp.Title)) == 0 {
   421  		return govtypes.ErrInvalidProposalContent("title is required")
   422  	}
   423  
   424  	if len(mp.Title) > govtypes.MaxTitleLength {
   425  		return govtypes.ErrInvalidProposalContent("title length is longer than the maximum title length")
   426  	}
   427  
   428  	if len(mp.Description) == 0 {
   429  		return govtypes.ErrInvalidProposalContent("description is required")
   430  	}
   431  
   432  	if len(mp.Description) > govtypes.MaxDescriptionLength {
   433  		return govtypes.ErrInvalidProposalContent("description length is longer than the maximum description length")
   434  	}
   435  
   436  	if mp.ProposalType() != proposalTypeManageSysContractAddress {
   437  		return govtypes.ErrInvalidProposalType(mp.ProposalType())
   438  	}
   439  
   440  	if mp.IsAdded && mp.ContractAddr.Empty() {
   441  		return govtypes.ErrInvalidProposalContent("is_added true, contract address required")
   442  	}
   443  
   444  	return nil
   445  }
   446  
   447  // String returns a human readable string representation of a ManageSysContractAddressProposal
   448  func (mp ManageSysContractAddressProposal) String() string {
   449  	var builder strings.Builder
   450  	builder.WriteString(
   451  		fmt.Sprintf(`ManageSysContractAddressProposal:
   452   Title:					%s
   453   Description:        	%s
   454   Type:                	%s
   455   ContractAddr:          %s
   456   IsAdded:				%t
   457  `,
   458  			mp.Title, mp.Description, mp.ProposalType(), mp.ContractAddr.String(), mp.IsAdded),
   459  	)
   460  	return strings.TrimSpace(builder.String())
   461  }
   462  
   463  type ManageContractByteCodeProposal struct {
   464  	Title              string         `json:"title" yaml:"title"`
   465  	Description        string         `json:"description" yaml:"description"`
   466  	Contract           sdk.AccAddress `json:"contract" yaml:"contract"`
   467  	SubstituteContract sdk.AccAddress `json:"substitute_contract" yaml:"substitute_contract"`
   468  }
   469  
   470  func NewManageContractByteCodeProposal(title, description string, Contract sdk.AccAddress, SubstituteContract sdk.AccAddress) ManageContractByteCodeProposal {
   471  	return ManageContractByteCodeProposal{
   472  		Title:              title,
   473  		Description:        description,
   474  		Contract:           Contract,
   475  		SubstituteContract: SubstituteContract,
   476  	}
   477  }
   478  
   479  func (mp ManageContractByteCodeProposal) GetTitle() string {
   480  	return mp.Title
   481  }
   482  
   483  func (mp ManageContractByteCodeProposal) GetDescription() string {
   484  	return mp.Description
   485  }
   486  
   487  func (mp ManageContractByteCodeProposal) ProposalRoute() string {
   488  	return RouterKey
   489  }
   490  
   491  func (mp ManageContractByteCodeProposal) ProposalType() string {
   492  	return proposalTypeManageContractByteCode
   493  }
   494  
   495  func (mp ManageContractByteCodeProposal) ValidateBasic() sdk.Error {
   496  
   497  	if len(strings.TrimSpace(mp.Title)) == 0 {
   498  		return govtypes.ErrInvalidProposalContent("title is required")
   499  	}
   500  	if len(mp.Title) > govtypes.MaxTitleLength {
   501  		return govtypes.ErrInvalidProposalContent("title length is longer than the maximum title length")
   502  	}
   503  
   504  	if len(mp.Description) == 0 {
   505  		return govtypes.ErrInvalidProposalContent("description is required")
   506  	}
   507  
   508  	if len(mp.Description) > govtypes.MaxDescriptionLength {
   509  		return govtypes.ErrInvalidProposalContent("description length is longer than the maximum description length")
   510  	}
   511  
   512  	if mp.ProposalType() != proposalTypeManageContractByteCode {
   513  		return govtypes.ErrInvalidProposalType(mp.ProposalType())
   514  	}
   515  
   516  	return nil
   517  }
   518  func (mp ManageContractByteCodeProposal) String() string {
   519  	var builder strings.Builder
   520  	builder.WriteString(
   521  		fmt.Sprintf(`ManageContractByteCodeProposal:
   522   Title:					%s
   523   Description:        	%s
   524   Type:                	%s
   525   Contract:          %s
   526   SubstituteContract:				%s
   527  `,
   528  			mp.Title, mp.Description, mp.ProposalType(), mp.Contract.String(), mp.SubstituteContract.String()),
   529  	)
   530  	return strings.TrimSpace(builder.String())
   531  }