Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
jackzampolin committed Apr 27, 2022
1 parent bf17da6 commit 093dcad
Show file tree
Hide file tree
Showing 4 changed files with 468 additions and 125 deletions.
23 changes: 21 additions & 2 deletions docs/proto/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- [AbsoluteTxPosition](#cosmwasm.wasm.v1.AbsoluteTxPosition)
- [AccessConfig](#cosmwasm.wasm.v1.AccessConfig)
- [AccessTypeParam](#cosmwasm.wasm.v1.AccessTypeParam)
- [AllowedContract](#cosmwasm.wasm.v1.AllowedContract)
- [CodeInfo](#cosmwasm.wasm.v1.CodeInfo)
- [ContractCodeHistoryEntry](#cosmwasm.wasm.v1.ContractCodeHistoryEntry)
- [ContractInfo](#cosmwasm.wasm.v1.ContractInfo)
Expand Down Expand Up @@ -138,6 +139,25 @@ AccessTypeParam



<a name="cosmwasm.wasm.v1.AllowedContract"></a>

### AllowedContract



| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `contract_address` | [string](#string) | | required |
| `allowed_messages` | [string](#string) | repeated | optional |
| `once` | [bool](#bool) | | optional

if true, the contract is only allowed to be called once |






<a name="cosmwasm.wasm.v1.CodeInfo"></a>

### CodeInfo
Expand Down Expand Up @@ -203,8 +223,7 @@ the provided method on behalf of the granter's account.

| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `target_contracts` | [string](#string) | repeated | Msg, identified by it's type URL, to grant unrestricted permissions to execute |
| `allowed_functions` | [string](#string) | repeated | |
| `allowed_contracts` | [AllowedContract](#cosmwasm.wasm.v1.AllowedContract) | repeated | |



Expand Down
14 changes: 11 additions & 3 deletions proto/cosmwasm/wasm/v1/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,19 @@ option (gogoproto.equal_all) = true;
message ExecuteContractAuthorization {
option (cosmos_proto.implements_interface) = "Authorization";

// Msg, identified by it's type URL, to grant unrestricted permissions to execute
repeated string target_contracts = 1;
repeated string allowed_functions = 2;
repeated AllowedContract allowed_contracts = 1;
}

message AllowedContract {
// required
string contract_address = 1;

// optional
repeated string allowed_messages = 2;

// optional
bool once = 3; // if true, the contract is only allowed to be called once
}

// AccessType permission types
enum AccessType {
Expand Down
87 changes: 84 additions & 3 deletions x/wasm/types/types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package types

import (
"encoding/base64"
"encoding/json"
"fmt"
"reflect"

Expand All @@ -27,9 +29,18 @@ var (
_ authztypes.Authorization = &ExecuteContractAuthorization{}
)

func NewAllowedContract(contractAddr sdk.AccAddress, allowedMessages []string) *AllowedContract {
return &AllowedContract{
ContractAddress: contractAddr.String(),
AllowedMessages: allowedMessages,
}
}

// NewExecuteContractAuthorization creates a new ExecuteContractAuthorization object.
func NewExecuteContractAuthorization(targetContracts, AllowedFunctions []string) *ExecuteContractAuthorization {
return &ExecuteContractAuthorization{}
func NewExecuteContractAuthorization(allowedContracts []*AllowedContract) *ExecuteContractAuthorization {
return &ExecuteContractAuthorization{
AllowedContracts: allowedContracts,
}
}

// MsgTypeURL implements Authorization.MsgTypeURL.
Expand All @@ -39,11 +50,81 @@ func (a ExecuteContractAuthorization) MsgTypeURL() string {

// Accept implements Authorization.Accept.
func (a ExecuteContractAuthorization) Accept(ctx sdk.Context, msg sdk.Msg) (authztypes.AcceptResponse, error) {
return authztypes.AcceptResponse{Accept: true}, nil
exec, ok := msg.(*MsgExecuteContract)
if !ok {
return authztypes.AcceptResponse{}, sdkerrors.ErrInvalidType.Wrap("type mismatch")
}

update := []*AllowedContract{}
for _, allowedContract := range a.AllowedContracts {
if allowedContract.ContractAddress == exec.Contract {
// if the allowed contract contains the contract address and there aren't allowed messages,
// then we accept the message.
if len(allowedContract.AllowedMessages) == 0 && !allowedContract.Once {
// if the permission is for multiple executions, we accept the message and keep
// it in the update array
update = append(update, allowedContract)
continue
} else if len(allowedContract.AllowedMessages) > 0 {
// otherwise we exclude it from the update array
continue
}

// NOTE: exec.Msg is base64 encoded, so we need to decode it first
// If there are allowedMessages then decode the call and check if the message is allowed
callBz := []byte{}
if _, err := base64.RawStdEncoding.Decode(exec.Msg.Bytes(), callBz); err != nil {
return authztypes.AcceptResponse{}, sdkerrors.Wrap(err, "failed to decode base64")
}

messageName := map[string]interface{}{}
if err := json.Unmarshal(callBz, &messageName); err != nil {
return authztypes.AcceptResponse{}, sdkerrors.Wrap(err, "failed to unmarshal json")
}

for _, allowedFunction := range allowedContract.AllowedMessages {
if len(messageName) != 1 {
return authztypes.AcceptResponse{}, sdkerrors.ErrInvalidRequest.Wrap("too many message calls in the same transaction")
}
for k := range messageName {
if allowedFunction == k {
if allowedContract.Once {
continue
} else {
update = append(update, allowedContract)
continue
}
}
}
}
} else {
// if the allowed contract doesn't contain the contract address, we add it to the update array
update = append(update, allowedContract)
}
}
if len(update) == 0 {
return authztypes.AcceptResponse{Accept: true, Delete: true}, nil
}
return authztypes.AcceptResponse{Accept: true, Updated: NewExecuteContractAuthorization(update)}, nil
}

// ValidateBasic implements Authorization.ValidateBasic.
func (a ExecuteContractAuthorization) ValidateBasic() error {
for _, allowedContract := range a.AllowedContracts {
if err := allowedContract.ValidateBasic(); err != nil {
return sdkerrors.Wrap(err, "allowed contract")
}
}
return nil
}

func (a AllowedContract) ValidateBasic() error {
if len(a.ContractAddress) == 0 {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "contract address cannot be empty")
}
if _, err := sdk.AccAddressFromBech32(a.ContractAddress); err != nil {
return sdkerrors.Wrap(err, "contract address")
}
return nil
}

Expand Down
Loading

0 comments on commit 093dcad

Please sign in to comment.