-
Notifications
You must be signed in to change notification settings - Fork 585
-
Call Native Modules From EVM
To improve interoperanility between EVM and native modules, and inspired by the cosmwasm messaging system, we can introduce a similar messaging system between EVM and native modules.
Call native modules
Logs can be used for evm contract to send and execute messages to native modules, for example:
emit CosmosNative("bank.send", recipient, 1, "denom");
This log can tell the host to do a native token transfer from the contract address to the recipient after the evm contract succesfully executed, if the native message execution failed, the whole tx is reverted.
Why not use precompiled contract to call native module synchronously
In current go-ethereum evm implementation, precompiled contract don't have access to the current caller, thus we can't do the authentication. https://github.com/ethereum/go-ethereum/blob/master/core/vm/contracts.go#L40
Tx post processing
We need to add tx post processing logic to execute the message, the new tx processing procedure would be like this:
k.ctx, commit = ctx.CacheContext() err := k.ApplyMessage(ethMsg) # execute the evm transaction if err != nil { // Could check the bloom filter first for log := range(k.GetLogs(txHash)) { if log.Topics.Contains(CosmosNative_Signature) { // log.Address is the address of calling contract err = execute_message(log.Address, log.Data) if err != nil { break } } } } if err == nil { commit() }
Query native modules
might need to change the evm api in go-ethereum to support custom precompiled contract
State querying can be implemented by precompiled smart contract directly, since we don't need to do the authentication:
balance = cosmos_native_query("bank.balance", addr, "denom");
The precompiled contract would be something like this:
type NativeQueryContract struct{ k EvmKeeper } func (c *NativeQueryContract) RequiredGas(input []byte) uint64 { return ... } func (c *NativeQueryContract) Run(input []byte) ([]byte, error) { (action, args) := parse_args(input) do the query on current context and return the result }
Allow Sending Native Tokens to EVM Contract
By allow sending native tokens to EVM contract, it enables more interoperability between EVM contract and native modules.
Contract can query the native tokens sent to it by calling some precompiled contract.
type QueryTxTokensContract struct{ tx Tx } func (c *QueryTxTokensContract) RequiredGas(input []byte) uint64 { return ... } func (c *QueryTxTokensContract) Run(input []byte) ([]byte, error) { if input == tx.To { return tx.ExtraTokens, nil } return nil, nil }
So a erc20 contract that wrapping a native token would look like this:
contract ERC20 { string _denom; mapping(address => uint256) private _balances; function deposit() public payable { coin = query_tx_tokens(address(this)); if coin.denom == _denom { // FIXME handle overflow _balances[msg.sender] += coin.amount; } } function withdraw(amount uint256) public { // FIXME handle underflow _balances[msg.sender] -= amount; emit CosmosNative("bank.send", msg.sender, amount, _denom); } }
If gravity bridge module is embed, one can even call gravity message directly from the contract, and send the token to ethereum:
function send_to_eth(amount uint256, eth_dest address) public { // FIXME handle underflow _balances[msg.sender] -= amount; emit CosmosNative("gravity.send", eth_dest, amount, _denom); }
https://gist.github.com/yihuang/f072e6d91d4845105b7698f52171053a
Some pseudocode to how how this could work together with gravity bridge to make transparent evm to evm bridge.
Mint Native Tokens from EVM Contract
For an exiting smart contract to convert to native token, it needs to have some native token minting ability. We can provide a call for contract to mint native token whose denomination is just the contract address prefixed with evm/.
contract ERC20 { mapping(address => uint256) private _balances; function withdraw(amount uint256) public { // FIXME handle underflow _balances[msg.sender] -= amount; emit CosmosNative("bank.mint", msg.sender, amount); } }
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 3 comments 9 replies
-
I think there are potential drawback having the module listening to EVM logs
- Its an extra cost in term of operation for the chain.
- It is not secure. You are breaking the isolation layer between EVM and main chain execution.
For the second point , anyone can emit any kind of event within the smart contract. We need a strong mechanism to be sure it is a log emitted by a "contract" module wont break anything.
Overall even though I like the idea to have contract interacting with module in cosmos, there could be some security concern because SC has been designed to be run in an isolated context to prevent any wrong behavior that could break the main chain execution. Need to think carefully.
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1
-
Ok got it, It guess is fine to use an arbitrary address for contract. But use case might be quite limited at the moment.
Beta Was this translation helpful? Give feedback.
All reactions
-
Ok got it, It guess is fine to use an arbitrary address for contract. But use case might be quite limited at the moment.
This could be useful for cosmos users but not so much for Ethereum users.
one use case is to complete the bridge puzzle:
- evm <-> local native token, this proposal
- native token <-> native token, ibc
- native token <-> ethereum, gravity bridge
Another use case could be contract controlled staking, something like:
emit CosmosNative("staking.delegate", validator_address, amount)
Beta Was this translation helpful? Give feedback.
All reactions
-
evm <-> local native token, this proposal
I think this proposal would only support evm -> native token but not native token -> evm (you will need the other proposal?)
For evm <-> native token <-> ibc/gravity bridge etc, another level of complexity is interfacing as the coin denom is often dictated by the bridge and sometime the supply as well.
Chaining might not be that trivial
Beta Was this translation helpful? Give feedback.
All reactions
-
evm <-> local native token, this proposalI think this proposal would only support evm -> native token but not native token -> evm (you will need the other proposal?)
Yeah, with this proposal we can manage exiting native tokens in contract, to support contract minting new native tokens, we'll need something from the other proposal.
For evm <-> native token <-> ibc/gravity bridge etc, another level of complexity is interfacing as the coin denom is often dictated by the bridge and sometime the supply as well.
Chaining might not be that trivial
hmm, could you elaborate?
Beta Was this translation helpful? Give feedback.
All reactions
-
Regarding the potential use cases, we can consult cosmwasm, what's done there could also done here:
- bank module: send and burn native tokens
- staking module: delegate/undelegate
- distribution module: reward withdraw
- ibc module: send ibc transfer message from contract
- gov module: voting in smart contract, maybe some multisig contract?
- if gravity bridge is used as a module, we could also execute gravity message from contract
Beta Was this translation helpful? Give feedback.
All reactions
-
We need to add tx post processing logic to execute the message, the new tx processing procedure would be like this:
I think we can implement hooks (pre-post tx) to make more the implementation cleaner and with the same result. Then, we can create a separate module that implements this hooks and just unpacks the logs using the abi
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1
-
(削除) How hard do you think it'll be to add a parameter like caller to this interface: https://github.com/ethereum/go-ethereum/blob/master/core/vm/contracts.go#L42? with that we could just implement a custom precompiled contract. (削除ここまで)
I guess we can't just add new precompiled contract with current evm api.
Beta Was this translation helpful? Give feedback.
All reactions
-
https://gist.github.com/yihuang/f072e6d91d4845105b7698f52171053a
Some pseudocode to show how this could work together with gravity bridge to make transparent evm to evm bridge.
Beta Was this translation helpful? Give feedback.