Is ckERC20 is done? Can I use it for my custom token?

Rest assured that DFINITY will always be reviewing any SCM proposals!

The reality today is that there is already nothing technically stopping anyone submitting such proposals. DFINITY itself uses a diverse set of neuron IDs which are not cryptographically verified to be acting on DFINITY’s behalf. So we all have to be on guard for the inevitable eventuality that someone else submits an SCM proposal.

Which leads me to think it’s better to normalize the process which we will need to safeguard the system, than rely on it not happening and being a rare event which catches people off guard.

I also agree that one of the possible trust signals is “do I know who the proposer is”, but given that compromising a “trusted account” is a major vector of cyberattacks today, I would not place too much emphasis on it. When it comes to critical parts of the system, better not to trust & verify.

3 Likes

Hi everyone!

A follow-up regarding Pete’s message

Anyone in the community with a neuron may submit proposals. DFINITY will publish a clearer help guide soon.

We just added some guidelines on how to add a new ckERC20 token. I hope this will clarify any misunderstanding regarding how to submit a NNS proposal for this use-case. As usual, feel free to ask any clarifying question on the forum.

3 Likes

Thanks @gregory-demay for the detailed guidelines, and thanks @Pete for your response.

I think it’s right that anyone should be able to submit SCM proposals (when their intention is actually to update the binary that a system canister is running). I’m not suggesting otherwise.

Which leads me to think it’s better to normalize the process which we will need to safeguard the system, than rely on it not happening and being a rare event which catches people off guard.

I respect where you’re coming from. I’d just like to make sure that I’m clear on this philosophy if that’s okay. You’re suggesting keeping the potential attack surface of proposals for NNS canister configuration updates unnecessarily large, intentionally, to keep the community on it’s toes and train greater due diligence?

Here's a slightly more detailed description of my concerns

Unless I’m mistaken, as it stands the configuration update process requires the proposer to build and deploy the canister WASM despite the fact that the WASM hasn’t changed (hence why the hashes are the same for the last two canister upgrades - 658c5786cf89ce77a0bb3b17fe855c30f00171de0dc946cc463c9f19c348cb5e).

If this type of proposal becomes greater in frequency (which hopefully they will given that the intention is to encourage community participation), can’t you imagine members of the community getting used to the fact that the WASM doesn’t change for these types of proposals and just eyeballing it (visually checking that the first few and last few digits look right), and spending the majority of their time reviewing the more salient aspects of the proposal?

There’s a low chance of the first few and last few digits in the hash matching by chance. But a bad actor could code any sort of nefarious behaviour into the WASM, then tweak the binary at a point that strategically doesn’t alter the intended behaviour, and keep computing the SHA2-256 until a handful of the first few and last few digits look close enough to the one that the community is expecting (the longer they’re willing to go at this, the more similar they can make the hash look).

Rest assured that DFINITY will always be reviewing any SCM proposals

Wouldn’t it be better to not rely on that?

If a new NNS function that has a smaller blast radius is out of the question, why not make the WASM and hash in SCM proposals optional? When they’re not provided, then the proposal just restarts the canister and passes along the payload.

This would be much easier to verify correctness of the proposal and reduces potential for reviewer fatigue (if there are to be many of these proposals in the future). Probably more importantly, it means the proposal will no longer misleadingly indicate that it’s updating the WASM when it’s not (with terms like ‘New compressed Wasm hash’, and ‘Upgrade Nns Canister: … to wasm with hash …’ when in fact that’s not at all what the proposal is really about).

Thanks for taking the time to read this if you got this far :slightly_smiling_face:

1 Like

I think that security philosophy would be easier to accept if it were explicitly put to community, and agreed that the VP majority would like to avoid slices of Swiss cheese in the security sandwich (even when the cheese is cheap and there’s a clear space for it).

1 Like

Is there a good way to compile just the minter canister? It looks like source code requires that you install dependencies at the top level for ALL ic rust projects.
It would be great to have a “here’s how to deploy your own ERC-20 to the ICP” guide that shows just how to compile that canister.
I’m running into a build error for “ic/rs/canister_sandbox”. I feel I shouldn’t have to make things compile for all rust canisters and be able to build and deploy just the 1 I want.

I largely agree with your suggestion. It would indeed be much cleaner if a proposal which only updates args and does not touch the wasm would not require a copy of the wasm to also be submitted.

There’s probably a few components which would need to be updated to make that change. Something for the team to definitely consider doing though.

1 Like

I found erc20-icp/ic at main · dfinity/erc20-icp · GitHub which looks like an easier way to do tokens. If I understand this project, it’s a way to more an erc 20 to and from IC. On IC it uses the ICRC-1 standard. Has anyone used this?

I am trying to interact with ckSepoliaUSDC from my rust canister but getting a few errors while performing a withdrawal of ckSepoliaUSDC to USDC

The first step is approving ckETH minter to burn some of the user’s ckETH tokens as payment, this function is failing with the error I have insufficient balance. And yet I have minted roughly 0.1 ckETH tokens to my principal ID

This is what my function looks like:

const CKETH_MINTER: &str = "jzenf-aiaaa-aaaar-qaa7q-cai";

#[ic_cdk::update] 
async fn approve_cketh_burning(user_principal: Principal, amount: Nat) -> ICRC2ApproveResult {
    let from_subaccount = Subaccount::from(user_principal);
    
    // Use the ckETH minter as the spender
    let minter_principal = Principal::from_text(CKETH_MINTER).expect("Invalid minter principal");
    let spender = ICRCAccount::new(minter_principal, None);

    let approve_args = ICRC2ApproveArgs {
        from_subaccount: Some(from_subaccount), 
        spender, 
        amount, 
        expected_allowance: None,
        expires_at: None,
        fee: None, 
        created_at_time: None, 
        memo: None 
    }; 

    InterCall::from(CKETH_LEDGER).call(
        "icrc2_approve", 
        approve_args, 
        CallCycles::NoPay
    )
    .await 
    .unwrap()
}

This is the error I am getting when I try to approve burning of ckETH tokens from this particular canister ID: 4p7ji-qaaaa-aaaal-qjabq-cai

The second error I am getting is when I try to call icrc2_approve function on the USDC_LEDGER to approve the minter to burn some of the user's ckUSDC tokens.
(I am not sure whether I am doing this the right way)

This is what my function looks like:

const CKETH_MINTER: &str = "jzenf-aiaaa-aaaar-qaa7q-cai";
const USDC_LEDGER: &str = "2s5qh-7aaaa-aaaar-qadya-cai"; 

#[ic_cdk::update]
async fn approve_usdc_burning(user_principal: Principal, amount: Nat) -> ICRC2ApproveResult {
    let from_subaccount = Subaccount::from(user_principal);
    
    // Convert minter Principal to ICRCAccount
    let minter_principal = Principal::from_text(CKETH_MINTER).expect("Invalid minter principal");
    let spender = ICRCAccount::new(minter_principal, None);

    let approve_args = ICRC2ApproveArgs {
        from_subaccount: Some(from_subaccount),
        spender,
        amount,
        expected_allowance: None,
        expires_at: None,
        fee: None,
        created_at_time: None,
        memo: None
    };

    InterCall::from(USDC_LEDGER).call(
        "icrc2_approve",
        approve_args,
        CallCycles::NoPay
    )
    .await
    .unwrap()
}

But when calling the function I am getting the error:

Err` value: CallError("icrc2_approve", "IC0536: Error from Canister 2s5qh-7aaaa-aaaar-qadya-cai: Canister has no update method 'icrc2_approve'

The final error I am getting is when I try to get the balance of ckSepoliaUSDC on my principal ID
This is how I’ve implemented the functionality

const USDC_LEDGER: &str = "2s5qh-7aaaa-aaaar-qadya-cai"; 

#[ic_cdk::update]
async fn balance(principal_id: Principal) -> Nat {
  let account = ICRCAccount::new(principal_id, None);

  ICRC1::from(USDC_LEDGER).balance_of(account).await.unwrap()
}

But I am getting the error:

`Err` value: CallError("icrc1_balance_of", "IC0536: Error from Canister 2s5qh-7aaaa-aaaar-qadya-cai: Canister has no update method 'icrc1_balance_of'

I would really appreciate if I got some assistance on this

This is the wrong canister id for test usdc, you can get the canister ids from ic dashboard or from b3forge.

1 Like

This is impressive, thank you!

Is it open source?

Thank you, Not yet, but i did use ic-reactor to creating it.

1 Like

@pete and @Manu How are the fees determined for the ckERC20 tokens. Do we expect these to change regularly? Do people just pick them when they make the proposal? I saw that ckXAUT has a fee of 1 and that seems like it could be spammy.