Questa pagina è una traduzione della community e ha solo scopo informativo; fa fede la versione originale in inglese.
Versione originale ↗

USDC

CCTP è il metodo preferito per la creazione nativa di USDC sulla L1 Hyperliquid. Per i contratti e i flussi pubblicati da Circle, consultare https://github.com/circlefin/hyperevm-circle-contracts.

Bridge legacy

CCTP supporta più chain e più funzionalità. Il bridge legacy è deprecato.

Contratto: https://arbiscan.io/address/0x2df1c51e09aecf9cacb7bc98cb1742757f163df7

Sorgente: https://github.com/hyperliquid-dex/contracts/blob/master/Bridge2.sol

Deposito

Il flusso di deposito per il bridge è semplice. L'utente invia USDC nativo al bridge e l'importo viene accreditato sull'account che lo ha inviato in meno di 1 minuto. L'importo minimo di deposito è 5 USDC. Se si invia un importo inferiore, questo non verrà accreditato e andrà perso definitivamente.

Prelievo

Il flusso di prelievo richiede unicamente la firma del wallet dell'utente su Hyperliquid e nessuna transazione su Arbitrum. Il prelievo da Arbitrum è gestito interamente dai validatori e i fondi arrivano nel wallet dell'utente in 3-4 minuti. Il payload per signTypedData è il seguente:

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
pub(crate) struct WithdrawAction3 {
    pub(crate) signature_chain_id: U256,
    pub(crate) hyperliquid_chain: Chain,
    pub(crate) destination: String,
    pub(crate) amount: String,
    pub(crate) time: u64,
}

impl Eip712 for WithdrawAction3 {
    type Error = Eip712Error;

    fn domain(&self) -> StdResult<EIP712Domain, Self::Error> {
        Ok(eip_712_domain(self.signature_chain_id))
    }

    fn type_hash() -> StdResult<[u8; 32], Self::Error> {
        Ok(eip712::make_type_hash(
            format!("{HYPERLIQUID_EIP_PREFIX}Withdraw"),
            &[
                ("hyperliquidChain".to_string(), ParamType::String),
                ("destination".to_string(), ParamType::String),
                ("amount".to_string(), ParamType::String),
                ("time".to_string(), ParamType::Uint(64)),
            ],
        ))
    }

    fn struct_hash(&self) -> StdResult<[u8; 32], Self::Error> {
        let Self { signature_chain_id: _, hyperliquid_chain, destination, amount, time } = self;
        let items = vec![
            ethers::abi::Token::Uint(Self::type_hash()?.into()),
            encode_eip712_type(hyperliquid_chain.to_string().into_token()),
            encode_eip712_type(destination.clone().into_token()),
            encode_eip712_type(amount.clone().into_token()),
            encode_eip712_type(time.into_token()),
        ];
        Ok(keccak256(encode(&items)))
    }
}

Esempio di azione Hyperliquid firmata:

{
    "action": {
        "type": "withdraw3",
        "signatureChainId": "0xa4b1",
        "hyperliquidChain": "Mainnet" or "Testnet" 
        "destination": "0x000....0",
        "amount": "12.3",
        "time": 1698693262
    },
    "nonce": 1698693262 // IMPORTANT: this must match "time",
    "signature": {"r": ..., "s": ..., "v": ... } // signedTypedData output based on Eip712 implementation above. See python sdk for equivalent python code
}

Deposito con permit

Il bridge supporta il deposito per conto di un altro utente tramite la funzione batchedDepositWithPermit. Di seguito il codice di esempio per la firma del PermitPayload da parte dell'utente

const payload: PermitPayload = {
  owner, // The address of the user with funds they want to deposit
  spender, // The address of the bridge 0x2df1c51e09aecf9cacb7bc98cb1742757f163df7 on mainnet and 0x08cfc1B6b2dCF36A1480b99353A354AA8AC56f89 on testnet
  value,
  nonce,
  deadline,
};

const isMainnet = true;

const domain = {
  name: isMainnet ? "USD Coin" : "USDC2",
  version: isMainnet ? "2" : "1",
  chainId: isMainnet ? 42161 : 421614,
  verifyingContract: isMainnet ? "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" : "0x1baAbB04529D43a73232B713C0FE471f7c7334d5",
};

const permitTypes = {
  Permit: [
    { name: "owner", type: "address" },
    { name: "spender", type: "address" },
    { name: "value", type: "uint256" },
    { name: "nonce", type: "uint256" },
    { name: "deadline", type: "uint256" },
  ],
};

const dataToSign = {
  domain,
  types: permitTypes,
  primaryType: "Permit",
  message: payload,
} as const;

const data = await walletClient.signTypedData(dataToSign);
const signature = splitSig(data);
Traduzione non ufficiale della community della documentazione Hyperliquid. Contenuti © Hyperliquid; fa fede la versione inglese. Fonte: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/usdc