I have a canister where I want to enable my users to deposit and withdraw usdt. How can I do that using the EVM?
There are a couple of different ways to do this:
-
Wait until ckUSDT is released
-
Create an ETH address based on a public key controlled by your canister, see e.g. oisy-wallet/src/backend/src/lib.rs at cd8e3096a0549fe65aba376189d62718e8daae7f · dfinity/oisy-wallet · GitHub.
Ideally, you let the payer give you the transaction of the payment. Then you can check the amount and verify the transaction inclusion with the EVM RPC canister. -
Another way is to use the
eth_getLogs
RPC method via the EVM RPC canister and fetch the transfer events from the USDT ERC-20 account with your ETH address as the recipient.
do U know when the ckUSDT
will be released?
Hi @AliSci
See this post form Manu
Our current very rough estimate is ~3 months, but of course we may run into unexpected issues that delay things.
Create an ETH address based on a public key controlled by your canister, see e.g. [oisy-wallet/src/backend/src/lib.rs at cd8e3096a0549fe65aba376189d62718e8daae7f · dfinity/oisy-wallet · GitHub ](https://github.com/dfinity/oisy-wallet/blob/cd8e3096a0549fe65aba376189d62718e8daae7f/src/backend/src/lib.rs#L212C4-L212C27).
Hello Dominic, does this mean that:
(1) Create an ETH address based on a public key controlled by my canister;
(2) The payer transfers the asset to the canister-controlled ETH address (this transaction is executed on Ethereum).
BTW, I suppose the gas fee in term of ETH is required when the EVM RPC canister calls the eth_sendRawTransaction
function, right? If this is correct, who and how the gas fee is paid to the Ethereum?
Thank you very much.
Exactly!
The canister-controlled ETH address needs ETH to pay for the gas fees.
The most important completely controlled smart contract ETH wallet we have is the ckETH Minter Canister.
@domwoe @cryptoschindler @franrappazzini
ckUSDC is released now, but still no documentations Also, I have to make few more steps like swapping?
Also, I talked to mortz and he says
- deposit usdc via eth net
- swap usdc to ckusdc
- conform transaction vis done by particular caller
is it somthing like this
use ic_cdk::export::Principal;
use ic_cdk_macros::{query, update};
use ic_eth::Ethereum;
use std::collections::HashMap;
type EthereumAddress = String;
#[derive(Default)]
struct USDCWallet {
ethereum_addresses: HashMap<Principal, EthereumAddress>,
usdc_balances: HashMap<EthereumAddress, u64>,
ckusdc_balances: HashMap<EthereumAddress, u64>,
}
impl USDCWallet {
fn new() -> Self {
Self {
ethereum_addresses: HashMap::new(),
usdc_balances: HashMap::new(),
ckusdc_balances: HashMap::new(),
}
}
fn generate_ethereum_address(&mut self, principal: Principal) -> EthereumAddress {
let eth_address = self.create_ethereum_address();
self.ethereum_addresses.insert(principal, eth_address.clone());
eth_address
}
fn create_ethereum_address(&self) -> EthereumAddress {
// Use ic-eth library to generate a real Ethereum address
Ethereum::generate_address()
}
fn swap_usdc_to_ckusdc(&mut self, eth_address: &EthereumAddress, amount: u64) -> bool {
if let Some(balance) = self.usdc_balances.get_mut(eth_address) {
if *balance >= amount {
*balance -= amount;
let ckusdc_balance = self.ckusdc_balances.entry(eth_address.clone()).or_insert(0);
*ckusdc_balance += amount;
return true;
}
}
false
}
fn swap_ckusdc_to_usdc(&mut self, eth_address: &EthereumAddress, amount: u64) -> bool {
if let Some(balance) = self.ckusdc_balances.get_mut(eth_address) {
if *balance >= amount {
*balance -= amount;
let usdc_balance = self.usdc_balances.entry(eth_address.clone()).or_insert(0);
*usdc_balance += amount;
return true;
}
}
false
}
}
#[update]
fn generate_ethereum_address(principal: Principal) -> EthereumAddress {
let mut wallet = USDCWallet::new();
wallet.generate_ethereum_address(principal)
}
#[update]
fn swap_usdc_to_ckusdc(eth_address: EthereumAddress, amount: u64) -> bool {
let mut wallet = USDCWallet::new();
wallet.swap_usdc_to_ckusdc(ð_address, amount)
}
#[update]
fn swap_ckusdc_to_usdc(eth_address: EthereumAddress, amount: u64) -> bool {
let mut wallet = USDCWallet::new();
wallet.swap_ckusdc_to_usdc(ð_address, amount)
}