I cam across the example for basic_ethereum I want to extend it and implement ERC20 transfer and so write this code:
const USDC_ADDRESS: &str = "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238";
#[update]
pub async fn send_usdc(to: String, amount: Nat) -> String {
let caller = validate_caller_not_anonymous();
let to_address = Address::from_str(&to).unwrap_or_else(|e| {
ic_cdk::trap(&format!("failed to parse the recipient address: {:?}", e))
});
let usdc_contract_address = Address::from_str(USDC_ADDRESS).expect("Invalid USDC address");
let usdc_contract_address_alloy = alloy_primitives::Address::from_slice(&usdc_contract_address.as_ref());
let amount_u256 = nat_to_u256(amount);
let transfer_data = format!(
"0xa9059cbb{}{}",
hex::encode(to_address.as_ref()), // recipient address
hex::encode(&amount_u256.to_be_bytes::<32>()) // specify 32 bytes for U256
);
let chain_id = read_state(|s| s.ethereum_network().chain_id());
let nonce = nat_to_u64(transaction_count(Some(caller), Some(BlockTag::Latest)).await);
let (gas_limit, max_fee_per_gas, max_priority_fee_per_gas) = estimate_transaction_fees();
let transaction = TxEip1559 {
chain_id,
nonce,
gas_limit,
max_fee_per_gas,
max_priority_fee_per_gas,
to: TxKind::Call(usdc_contract_address_alloy),
value: U256::from(0), // No ETH is sent, only USDC
access_list: Default::default(),
input: transfer_data.into(),
};
let wallet = EthereumWallet::new(caller).await;
let tx_hash = transaction.signature_hash().0;
let (raw_signature, recovery_id) = wallet.sign_with_ecdsa(tx_hash).await;
let signature = Signature::from_bytes_and_parity(&raw_signature, recovery_id.is_y_odd())
.expect("BUG: failed to create a signature");
let signed_tx = transaction.into_signed(signature);
let raw_transaction_hash = *signed_tx.hash();
let mut tx_bytes: Vec<u8> = vec![];
TxEnvelope::from(signed_tx).encode_2718(&mut tx_bytes);
let raw_transaction_hex = format!("0x{}", hex::encode(&tx_bytes));
ic_cdk::println!(
"Sending raw transaction hex {} with transaction hash {}",
raw_transaction_hex,
raw_transaction_hash
);
let single_rpc_service = read_state(|s| s.single_evm_rpc_service());
let (result,) = EVM_RPC
.eth_send_raw_transaction(
single_rpc_service,
None,
raw_transaction_hex.clone(),
2_000_000_000_u128,
)
.await
.unwrap_or_else(|e| {
panic!(
"failed to send raw transaction {}, error: {:?}",
raw_transaction_hex, e
)
});
ic_cdk::println!(
"Result of sending raw transaction {}: {:?}.",
raw_transaction_hex,
result
);
raw_transaction_hash.to_string()
}
But the transactions are not success, they are failing, what could I do to correct it?