VMBridge provides OKBC with a channel for exchanging EVM's ERC20 tokens and WASM's CW20 tokens. You can circulate your tokens in EVM and WASM by compiling a contract pair. Below is a schematic design diagram of VMBridge:
EVM contracts follow 2 kinds of protocols:
Wasm contracts follow 2 kinds of protocols:
We provide an example contract of how to use VMBridge
ERC20 and CW20 contracts follow VMBridge rules (suitable for newly issued token projects). When the user exchanges ERC20 for CW20 tokens, the call for the method of exchanging CW20 tokens in the ERC20 contract is initiated. The ERC20 side burns the corresponding token and calls the CW20 contract, and the CW20 side mints the corresponding token. The same applies vice versa.
For the existing ERC20 contracts on the chain, if you do not want to upgrade the ERC20 contracts, you can choose the method in example 2. To implement an exchange contract, when the user needs to exchange ERC20 for CW20, approve the corresponding tokens to the exchange contract. Then, when the user calls the exchange contract to exchange with the CW20 token method, the user's ERC20 token is transferred into the lock account by means of transferfrom, and the CW20 contract is called, causing the CW20 side contract to mint out the corresponding token. The same applies vice versa.
To make your contract initiate CW20 exchange for ERC20, you must develop an EVM ERC20 contract and a wasm CW20 contract; each contract must obey the following rules.
Rid of the following actions in order to exchange ERC20 for CW20 tokens. (equivalent to calling the mintCW20 method of the CW20 contract, wasmAddr is the wasm contract address, recipient is the cw20 token receiving address, and amount is the number of cw20 tokens)
event __OKBCSendToWasm(string wasmAddr, string recipient, uint256 amount);
Define unique module account in OKBC
address public constant moduleAddress = address(0xc63cf6c8E1f3DF41085E9d8Af49584dae1432b4f);
The EVM contract must define the mintERC20 method for receiving the ERC20 request for CW20 token conversion. Caller is the caller's address (usually the wasm contract address), recipient is the erc20 token receiving address, and amount is the number of erc20 tokens.
function mintERC20(string calldata caller, address recipient,uint256 amount) public returns (bool) {
require(msg.sender == moduleAddress);
require(keccak256(abi.encodePacked(caller)) == keccak256(abi.encodePacked(wasmContractAddress)));
_mint(recipient, amount);
return true;
}
The execution of the wasm contract is to throw out the Msg type to exchange CW20 for ERC20 (equivalent to calling the mintERC20 method of ERC20)
pub struct SendToEvmMsg {
pub sender: String,
pub contract: String,
pub recipient: String,
pub amount: Uint128,
}
impl Into<CosmosMsg<SendToEvmMsg>> for SendToEvmMsg {
fn into(self) -> CosmosMsg<SendToEvmMsg> {
CosmosMsg::Custom(self)
}
}
impl CustomMsg for SendToEvmMsg {}
Wasm contract must initiate this method to be used for receiving the request of exchanging ERC20 to CW20.
pub enum ExecuteMsg {
MintCW20 {
recipient: String,
amount: Uint128,
}
}