cosmos / cosmos/evm

Precompile Request: BankSend and ERC20 ConvertCoin / ConvertERC20

Open
#754 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
164
Forks
213
Avg merge
3d 58m
Merged PRs (30d)
12

Description

## Summary

### Bank

Right now the bank precompile is query only. It should allow for sending tokens as well from the caller of the precompile

```solidity
function send(string memory sdk_token, uint256 amount, address to_addr) external returns (bool success);
```

Roughly something like

```go
func (p Precompile) BankSend(
ctx sdk.Context,
caller common.Address,
contract *vm.Contract,
stateDB vm.StateDB,
method *abi.Method,
args []interface{},
) ([]byte, error) {
if len(args) != 3 {
fmt.Printf("Precompile || ERROR: BankSend expects 3 arguments, got %d\n", len(args))
return nil, fmt.Errorf("BankSend expects 3 arguments, got %d", len(args))
}

token, ok := args[0].(string)
if !ok {
return nil, fmt.Errorf("first argument must be an address")
}

amount, ok := args[1].(*big.Int)
if !ok {
return nil, fmt.Errorf("second argument must be a *big.Int")
}

receiver, ok := args[2].(common.Address)
if !ok {
return nil, fmt.Errorf("third argument must be an address")
}

senderSDK := sdk.AccAddress(caller.Bytes())
receiverSDK := sdk.AccAddress(receiver.Bytes())

if err := p.bankKeeper.SendCoins(
ctx,
senderSDK,
receiverSDK,
sdk.NewCoins(sdk.NewCoin(token, sdkmath.NewIntFromBigInt(amount))),
); err != nil {
return nil, fmt.Errorf("error sending coins: %w", err)
}

return method.Outputs.Pack(true)
}
```

### Convert To Native

Currently you can only convert a native / erc20 to the other with the cli or cosmos msg server. This should be extended to a precompile

```solidity
// converts within the callers account, so works for direct call or within contracts as the .Caller()
function convertERC20ToNative(address erc20Token, uint256 amount) external returns (bool success);
function convertNativeToERC20(string memory tokenAddress, uint256 amount) external returns (bool success);
```

Rough impl of 1 here

```go
func (p Precompile) ConvertERC20ToNativeCoin(
ctx sdk.Context,
caller common.Address,
contract *vm.Contract,
stateDB vm.StateDB,
method *abi.Method,
args []interface{},
) ([]byte, error) {
if len(args) != 2 {
fmt.Printf("Precompile || ERROR: ConvertERC20ToNativeCoin expects 2 arguments, got %d\n", len(args))
return nil, fmt.Errorf("ConvertERC20ToNativeCoin expects 2 arguments, got %d", len(args))
}

tokenAddress, ok := args[0].(common.Address)
if !ok {
return nil, fmt.Errorf("first argument must be an address")
}

amount, ok := args[1].(*big.Int)
if !ok {
return nil, fmt.Errorf("second argument must be a *big.Int")
}

receiverSDK := sdk.AccAddress(caller.Bytes())

convertMsg := &erc20types.MsgConvertERC20{
ContractAddress: tokenAddress.Hex(),
Amount: sdkmath.NewIntFromBigInt(amount),
Sender: caller.Hex(),
Receiver: receiverSDK.String(),
}
if err := convertMsg.ValidateBasic(); err != nil {
return nil, fmt.Errorf("invalid convert ERC20 message: %w", err)
}

handler := p.keeper.Router().Handler(convertMsg)
if _, err := handler(ctx, convertMsg); err != nil {
return nil, fmt.Errorf("error executing convert ERC20 message: %w", err)
}

return method.Outputs.Pack(true)
}
```

Contributor guide

Open the contributing guide

Research direction

Start by reading the existing bank precompile and the CLI or Cosmos message-server conversion paths mentioned in the issue, then trace MsgConvertERC20 and the proposed BankSend and ConvertERC20ToNativeCoin entry points. Done means the precompile exposes token sending and both native/ERC20 conversion functions with the stated Solidity signatures, validates arguments, and returns success for valid calls.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, solidity
Domain
backend-api-design, blockchain
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.