Precompile Request: BankSend and ERC20 ConvertCoin / ConvertERC20
- 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
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