Explicación detallada de la construcción del objeto de transacción Ethereum en Js

       Este artículo utiliza la ethersbiblioteca como implementación subyacente y describe las propiedades detalladas del objeto de transacción Ethereum construido en Javascript. Este artículo asume que el lector tiene ciertos conocimientos básicos de Ethereum.

1. ¿Qué es una ethersbiblioteca?

       La siguiente es una introducción original de su documento:

       La biblioteca ethers.js pretende ser una biblioteca completa y compacta para interactuar con Ethereum Blockchain y su ecosistema. Originalmente fue diseñado para usarse con ethers.io y desde entonces se ha expandido a una biblioteca mucho más de uso general.

       El significado aproximado es ethers.jsuna biblioteca completa y compacta aplicada a Ethereum y su ecosistema. Originalmente fue diseñado para ser utilizado en ethers.io y poco a poco se expandió a una biblioteca multifuncional.

       ethersLa biblioteca tiene las siguientes características:

  • La clave privada se almacena en el cliente, segura y sin riesgos.
  • Admite carteras de importación y exportación en formato json (se puede usar para Geth o Parity)
  • Admite importar y exportar palabras mnemotécnicas y billetera de hardware, las palabras mnemotécnicas admiten varios idiomas
  • Admite múltiples formatos ABI, incluidos ABIv2 y ABI legible por humanos
  • Admite múltiples formas de conectarse a los nodos de Ethereum, como JSON-RPC, INFURA, Etherscan o MetaMask.
  • Los nombres ENS son totalmente compatibles como primera categoría de elementos.
  • La biblioteca es muy pequeña (versión sin comprimir 284kb, versión comprimida 88kb)
  • Funciones completas para satisfacer todas sus necesidades de Ethereum
  • Documentación detallada
  • Se agregaron muchos casos de prueba.
  • TypeScript legible
  • Certificado MIT (incluidas sus dependencias), código completamente abierto

En segundo lugar, construya un objeto comercial

       En ethers.js, un objeto de transacción de Ethereum es un objeto ordinario {}, que contiene los siguientes atributos opcionales:

  • a
  • gasLimit
  • GasPrice
  • mientras tanto
  • datos
  • valor
  • chainId

       Los atributos anteriores son todos opcionales, lo que significa que se pueden omitir, pero no todos, debe haber al menos un atributo. Creamos un objeto de transacción de la siguiente manera:

// All properties are optional
let transaction = {
    
    
    nonce: 0,
    gasLimit: 21000,
    gasPrice: utils.bigNumberify("20000000000"),

    to: "0x88a5C2d9919e46F883EB62F7b8Dd9d0CC45bc290",
    // ... or supports ENS names
    // to: "ricmoo.firefly.eth",

    value: utils.parseEther("1.0"),
    data: "0x",

    // This ensures the transaction cannot be replayed on different networks
    chainId: ethers.utils.getNetwork('homestead').chainId
}

       A continuación, explicamos estos atributos a través de transacciones reales en la red de prueba de Kovan.

3. Explicación detallada de los atributos del objeto de transacción

       Existen los siguientes fragmentos de código, que modificaremos o agregaremos a este fragmento en transacciones futuras. Esta es una transacción que crea un contrato:

let data='0x60....'
let provider = ethers.getDefaultProvider('kovan')
let wallet_new = wallet.connect(provider)
let trans = {
    
    
    data:inputData
}
wallet_new.sendTransaction(trans).then( tx => {
    
    
    console.log(tx)
}).catch( err => {
    
    
    console.log(err)
})

Como puede ver, nuestro objeto de transacción solo tiene un atributo datay su valor es el código de bytes para crear el contrato. Nota: El código de bytes al crear el contrato no es el código de bytes compilado por el contrato de creación, sino el código de bytes que se puede obtener ejecutando el código de bytes del contrato creado.

       Echemos un vistazo a la respuesta de transacción impresa (Respuesta de transacción):
Inserte la descripción de la imagen aquí
       puede ver que en el objeto de respuesta de transacción, además de los toatributos, existen otros atributos. Entonces, el atributo mencionado anteriormente se puede omitir significa que se puede omitir al construir el objeto de transacción. Si se omite, la ethersbiblioteca subyacente la configurará automáticamente. Comencemos con este objeto comercial más simple, aumentemos y expliquemos sus propiedades paso a paso.

3.1 to

       Dado que el toatributo es null, comenzaremos con el toatributo. toRepresenta la dirección del destinatario de la llamada en la transacción.

       Una transacción en Ethereum debe tener un iniciador (cuenta externa, cuenta sin contrato), generalmente from. Debido a que la ethersbiblioteca que usamos usa la billetera para firmar transacciones, quien firma es quien firma from. La transacción generalmente tiene un receptor (tanto la cuenta externa como la cuenta del contrato), es decir to. ¿Por qué es habitual? Porque como en nuestro ejemplo de ahora, no hay un receptor cuando se crea el contrato. Aunque la dirección del contrato se todevolverá como un atributo después de que se cree el contrato , esta todirección está vacía cuando se crea . Echemos un vistazo a la captura de pantalla en etherscan para profundizar en esta impresión:
Inserte la descripción de la imagen aquí
       puede ver que después de que se ejecuta la transacción, este toatributo es la dirección del nuevo contrato. Permítanme agregar que la dirección del contrato se calcula en función de la dirección de la persona que llama y el número de transacciones (nonce) que la persona que llama ha completado. Por lo tanto, antes del despliegue real de un contrato, se establece la dirección y se puede obtener.

       Para resumir, el toatributo es la dirección del destinatario de la transacción. Específicamente: si está transfiriendo ETH a una cuenta externa, es la dirección de recepción de ETH; si está llamando a un contrato (transferir ETH a una cuenta de contrato también es un contrato de llamada), es la dirección del contrato; si está creando un contrato, porque no hay ningún destinatario en este momento, Solo lo predeterminado.

3.2 data

       A continuación se habla de que el código anterior utiliza la propiedad: data. Durante la transacción, podemos enviar datos de la transacción junto con la transacción. Los datos de transacción pueden ser llamadas a métodos al contrato, o algunos datos sin sentido, que a veces se llaman payload. En el ejemplo anterior, datael valor del atributo es el código de bytes del contrato que creamos. Agreguemos un toatributo al objeto de transacción anterior y modifiquemos datael valor del atributo:

let trans = {
    
    
    data:"0x496c6f7665457468657265756d",
    to:"0xDD55634e1027d706a235374e01D69c2D121E1CCb"
}

       Aquí tohay una dirección de cuenta externa, que dataes la cadena de "Me encanta Ethereum" convertida en valor hexadecimal ( datadebe 0xcomenzar con). La respuesta después de que se envía la transacción es la siguiente:
Inserte la descripción de la imagen aquí
       Veamos el resultado en etherscan: en
Inserte la descripción de la imagen aquí
       el fragmento de código, podemos ver que enviamos directamente un mensaje (cadena) a una cuenta. En la parte inferior de InputData, muestra datos nativos de forma predeterminada. Seleccione Ver entrada como UTF-8, y se mostrará IloveEthereum. No se muestran espacios aquí porque la herramienta que utilicé no codificó espacios. ¿Esta función de enviar una cadena a una cuenta parece enviar un mensaje corto a un número de teléfono móvil? Incluso puedes enviar un artículo (pero con muchas tarifas), ¿Ethereum es interesante?

       Si los datos enviados son los datos cuando se llama al método de contrato, generalmente tiene un formato fijo y no pueden ser datos arbitrarios. Los ejemplos son los siguientes:

data:0x07391dd6000000000000000000000000000000000000000000000000000000000000000a

       Aquí, los primeros 8 bits 07391dd6de los primeros 32 bytes son selectores de funciones, y después de 32 bytes son los tipos de datos correspondientes. Los lectores interesados ​​pueden leer artículos relacionados sobre la codificación de Ethereum por sí mismos.

       Bueno, para resumir: el dataatributo son los datos enviados con la llamada. Si el objeto llamado es un contrato, generalmente es el código del método de llamada del contrato; si es para crear un contrato, es el bytecode creado; si el objeto llamado es una cuenta externa, el contenido de estos datos es arbitrario (la cuenta externa no tiene código , Y no ejecutará los datos enviados).

3.3 value

       valueEl atributo representa la cantidad de Ether enviada con esta transacción. Independientemente de si el tipo de transacción es transferencia directa de ETH (incluida la transferencia al contrato y transferencia a una cuenta externa), creación de un contrato (en este caso, ETH se utilizará como ETH inicial del contrato creado) o llamada de contrato (el método de contrato es payable), se registra fielmente La cantidad de ETH que envió en la transacción (sin incluir la tarifa de manejo, la tarifa de manejo es un consumo adicional). Agreguemos una valuepropiedad de objeto de transacción , su valor son las weiunidades de atención . Y, por lo general, cuando estamos en una referencia general a las etherunidades monetarias de Ethernet , debemos hacer uso de una conversión.

let trans = {
    
    
    data:"0x496c6f7665457468657265756d",
    value:ethers.utils.parseEther('0.1'),
    to:"0xDD55634e1027d706a235374e01D69c2D121E1CCb"
}

valueEl valor en el código es 0.1 ETH. Enviemos esta transacción:
Inserte la descripción de la imagen aquí
       en JS, si el número es relativamente grande, excederá el límite superior de la representación decimal js (aproximadamente 10 ** 15), por lo que BigNumber se usa generalmente para interactuar con Ethereum. Puede ver que el número de WEI enviado se convierte en un BigNumber. Veamos nuevamente el resultado de etherscan:
Inserte la descripción de la imagen aquí
       no se muestra aquí dataporque no hice clic en Haga clic para ver Más para expandir. Como puede ver, enviamos 0.1 ETH con la transacción.

3.4 gasLimitygasPrice

       A continuación, presentaremos dos atributos relacionados con el gas: gasLimity gasPrice. Se gasLimitrefiere al consumo máximo de gas de esta transacción y gasPriceal precio que está dispuesto a pagar por el gas consumido real. La cantidad específica de gas consumida se multiplica por gasPricela tarifa que está dispuesto a pagar al minero. Una vez ejecutada la transacción, se le devolverá el gas no consumido (la situación de error de transacción no se discutirá aquí, en este caso, a veces no se reembolsará el gas no consumido).

       gasLimitSuele utilizarse para limitar una determinada transacción que no puede consumir demasiados recursos. Aquí hay un escenario de uso: A menudo usamos MetaMask para transferir fondos directamente a cuentas externas. El gasLimitvalor predeterminado en MetaMask es 23000 y el mínimo no puede ser inferior a 21000.
Inserte la descripción de la imagen aquí

       Veamos una transacción de transferencia específica en etherscan:
Inserte la descripción de la imagen aquí
       como puede ver en la figura anterior, cuando no enviamos ningún dato con la transacción (el dataatributo está vacío, si no está vacío, se consumirá gas adicional), a un externo La transferencia de cuenta consumirá 21.000 gas, que es básicamente fijo. Por lo tanto, gasLimittambién se establece 21000el límite superior de esta transacción , la tasa de utilización 100%.

       El nuestro en la imagen de arriba gasPricees 5 Gwei. Cuanto mayor sea el precio que ofrezca, más rápida será la transacción y, por supuesto, mayor será su tarifa de gestión. Por lo general gasPrice, cuando hablamos de él, todos lo usamos Gweicomo una unidad, pero aún tenemos que convertirlo cuando lo usamos wei. Esto 5 Gweimultiplicado por el gas consumido 21000es exactamente lo que se muestra en la figura anterior Transaction Fee: 0.000105ETH. Cuando el autor escribe aquí, el precio de ETH es de alrededor de $ 205, por lo que la tarifa de manejo para enviarlo es aproximadamente 0.15RMB.

       Agreguemos estos dos atributos al objeto de transacción para ver si se consume el exceso de gas. Nuestro gasLimit está configurado en 100000, gasPriceconfigurado en 3 Gwei, reenvíemos la transacción:

let trans = {
    
    
    data:"0x496c6f7665457468657265756d",
    value:ethers.utils.parseEther('0.1'),
    gasLimit:100000,
    gasPrice:ethers.utils.parseUnits("3",'gwei'),
    to:"0xDD55634e1027d706a235374e01D69c2D121E1CCb"
}

       Aquí, debido a que el nuestro gasLimitno puede exceder el límite decimal de JS, el sistema decimal se usa directamente 100000. La respuesta de la transacción es:
Inserte la descripción de la imagen aquí
       miramos directamente el resultado de la transacción en etherscan:
Inserte la descripción de la imagen aquí
       debido a que enviamos I love Ethereumesta cadena con la transacción , consumimos 208 gas más. Según la tarifa que deducimos, el gas no utilizado no está incluido en el costo.

       Para gasLimithablar en general en uso ethers, no es necesario configurar la biblioteca, déjela por defecto en la línea. Si desea configurarlo manualmente, puede usarlo para estimar primero y luego expandirlo hacia arriba de manera apropiada, como el siguiente fragmento de código:

let args = [_address,amount]
let gasLimit = await contract.estimate.transfer(...args)
let step = ethers.utils.bigNumberify(1000)
gasLimit = gasLimit.add(step)

       Para gasPricehablar, generalmente establecido en 5 Gweio en circunstancias normales 6 Gwei. Se puede configurar en 1.5 Gweio cuando el gas consume mucho o la red está inactiva 2 Gwei. Sin embargo, el tiempo de la transacción se extenderá de esta manera e incluso puede fallar. Si desea operar rápidamente, configúrelo en 10 Gweio 20 Gweiincluso más alto, pero esto costará más. Si tiene más dinero, será rápido, y si no tiene suficiente dinero, será lento. Y tenga cuidado: una tarifa demasiado baja puede hacer que ningún minero empaquete la transacción y la transacción fallará. Por supuesto, si está en la red de prueba, puede configurarlo más alto, porque realmente no tiene que gastar dinero.

3,5 nonce

       En el objeto de transacción, noncerepresenta el número de transacciones completadas por la dirección. Comienza desde 0 y es un número entero que aumenta automáticamente. Por lo general, no es necesario configurarlo. Pero en algunos casos especiales, se puede configurar manualmente. Un escenario es cuando se cubren las transacciones. Puede establecer manualmente el valor nonce en el valor nonce de una transacción que se ha enviado pero aún no se ha completado para sobrescribir la transacción. Por lo general, el propósito de esto es acelerar la transacción (aumentar gasPrice) o utilizar una nueva transacción por completo. Esto también es fácil de entender. Por ejemplo, mi transacción No. 122 es para enviar un ETH a A, pero antes de que esta transacción no se envíe o no se complete, hice una modificación urgente para cambiar esta transacción No. 122 para enviar un ETH a B. En este punto, solo necesito establecer el nonce de la nueva transacción en 122.

       Si desea establecer en el objeto de transacción de uso común, debe consultar el número de transacciones que ha completado. Este número es el valor nonce que debe usar. Utilice el siguiente código:

let address = "0x02F024e0882B310c6734703AB9066EdD3a10C6e0";

provider.getTransactionCount(address).then((transactionCount) => {
    
    
    console.log("Total Transactions Ever Sent: " + transactionCount);
});

       Vale la pena señalar que: nonce tiene un uso especial, puede especificar un valor futuro. Por ejemplo, si el número de transacciones que ha completado actualmente es 2096, entonces el valor nonce para la próxima transacción debe ser 2097. En este punto, también puede omitir 2097 y configurarlo en 2098, entonces, ¿qué sucederá? En este momento, la transacción con el número 2098 equivale a una transacción retrasada, que se enviará, pero no se ejecutará, y no podrá consultarla en etherscan. Luego, realizamos una transacción normal con el valor nonce establecido en 2097, y la transacción se enviará y ejecutará. Aquí viene el punto: en el siguiente bloque también se ejecutará la transacción con un nonce de 2098 (porque ya se ha ejecutado 2097, es su turno).

3.6 chainId

       chainIdRepresenta el ID de red que desea iniciar una transacción. Con tres redes principales y una red de prueba, por ejemplo, la red principal (mainnet, pero en ethersla todavía llamada a homesteadcasa) es 1, Ropstenla red de prueba 3, la Rinkebyred de prueba 4, Kovanla red de prueba a 42. La red personalizada la puede configurar usted mismo, etc.

       En términos generales, no es necesario configurar esto al usar la billetera chainId. Debido a que el inicio de sesión de la billetera vinculará una red, es la red de su objeto de transacción. Pero también puede establecer manualmente un valor específico para evitar transacciones en la red incorrecta. Puede usar directamente el valor numérico decimal anterior, o puede usar ethersel código de muestra en:

chainId: ethers.utils.getNetwork('homestead').chainId

       Si operamos en la red de prueba de Kovan, los parámetros del método deben cambiarse kovan. Agreguemos chainIdy noncea la transacción. Y cambie el valor a 0.01ETH para distinguir.

let count = await provider.getTransactionCount(wallet_new.address)
let trans = {
    
    
    data:"0x496c6f7665457468657265756d",
    value:ethers.utils.parseEther('0.01'),
    gasLimit:100000,
    nonce: count,
    chainId:ethers.utils.getNetwork('kovan').chainId,
    gasPrice:ethers.utils.parseUnits("3",'gwei'),
    to:"0xDD55634e1027d706a235374e01D69c2D121E1CCb"
}

Aquí está la respuesta de la transacción:
Inserte la descripción de la imagen aquí
       debido a que los números 2097 y 2098 noncese consumen cuando se usan valores futuros , el número ahora es 2099. Echemos un vistazo a los resultados en etherscan:
Inserte la descripción de la imagen aquí
       puede ver que la cantidad de ETH enviada es 0.01 ETH, y el nonce es 2099. Alguien puede preguntar por qué no se muestra en etherscan chainId, porque etherscan está dividido en varios sitios basados ​​en la red principal y la red de prueba, y cada sitio solo muestra transacciones en su propia red. Por ejemplo, la URL real de etherscan que visité es:

https://kovan.etherscan.io/tx/0x4db8e6b4096d6c27be341b73af99a8d0477e19ba483248c1fdb6fb431fbb3646

       Todas las transacciones que se muestran en este sitio chainIdson 42.

Cuatro, resumen

       En este artículo, damos una introducción detallada a las propiedades específicas del objeto de transacción Ethereum creado manualmente. Estos atributos se pueden omitir, pero no se pueden omitir (porque no tiene sentido omitirlos todos). Los más utilizados son to, valuey dataatributos. Nota: Este es solo un atributo que debe configurarse al crear manualmente un objeto de transacción en el código; si usa directamente una billetera común (como MetaMask o Trust billetera), la billetera tendrá una interfaz de usuario para ayudarlo a configurar todo. Sin embargo, es necesario aclarar la base de la implementación. Espero que este artículo pueda proporcionar un poco de ayuda a los desarrolladores de Ethereum.

Invitamos a todos a dejar un mensaje para señalar errores o sugerir mejoras.

Supongo que te gusta

Origin blog.csdn.net/weixin_39430411/article/details/104188489
Recomendado
Clasificación