En la carga de los recursos... Cargando...

Comience con el desarrollo web3 Basado en Ethereum Usando FMZ

El autor:FMZ~Lydia, Creado: 2023-06-25 09:17:53, Actualizado: 2024-11-11 22:34:49

[TOC] ¿Qué quieres decir?

img

Comience con el desarrollo web3 Basado en Ethereum Usando FMZ

Tutorial de EtherEaseWithFMZ

Comience con el desarrollo web3 basado en Ethereum usando FMZ fácilmente

Ethereum es una plataforma de contratos inteligentes basada en la tecnología blockchain, que proporciona una forma descentralizada de escribir e implementar contratos inteligentes.

Plataforma de negociación cuantitativa FMZ (FMZ.COMLa plataforma proporciona una API fácil de usar, que permite a los desarrolladores interactuar más fácilmente con la cadena de bloques Ethereum y su ecosistema.

En este tutorial, los ejemplos están escritos enJavaScriptEn el contexto de la evaluación de la calidad de la información, el entorno de prueba utilizaLa red principal de EthereumyRed de prueba de Goerli. Y también puede ver las interfaces API y descripciones relacionadas, ejemplos de código utilizados en el tutorial en la documentación API de la plataforma FMZ.


Comienza el FMZ

Antes de aprender a usar la plataforma de comercio de FMZ Quant, necesitamos familiarizarnos con algunos conceptos básicos:

1. Arquitectura de la plataforma de negociación cuántica FMZ

Después de registrarse y iniciar sesión en el sitio web oficial de la Plataforma de Comercio Cuántico de FMZ (https://www.fmz.comEl sitio web de FMZ es el extremo de administración de todo el sistema, y los programas escritos por el usuario se ejecutan en el docker en realidad. El programa de software de docker se puede implementar en varios dispositivos, como servidores, computadoras, etc. Cuando un usuario escribe un programa y crea una instancia en ejecución en el sitio web de FMZ, la plataforma FMZ se comunicará con el docker y comenzará una instancia de programa en él.

2. Docker

Si desea ejecutar una instancia de programa, debe implementar un docker. La implementación del docker también es muy simple, y hay tutoriales de implementación en la plataforma. También puede usar el One-click Deployment proporcionado por FMZ para implementar automáticamente en servidores alquilados en nombre de FMZ.

  • Despliegue docker en dispositivos personales

Puede implementar y ejecutar el programa docker en servidores, computadoras personales y otros dispositivos, siempre que la red sea normal (necesita poder acceder al objetivo correspondiente, como una determinada interfaz de intercambio, dirección de nodo, etc.).

  1. Inicie sesión o abra el dispositivo donde se despliegue el programa docker, comoiniciar sesión en un servidoro bienencender una computadora para entrar en el sistema operativo.
  2. Descargar la versión correspondiente del programa docker (dependiendo del sistema operativo del dispositivo), página de descarga:https://www.fmz.com/m/add-node

img

  1. Lo que descargaste es un paquete comprimido, necesita descomprimirse.
  2. Ejecute el programa docker, el programa docker es un archivo ejecutable llamadorobot. Configure la dirección de comunicación docker, que es única para cada cuenta FMZ, después de iniciar sesión en FMZ, puede ver su propia dirección enhttps://www.fmz.com/m/add-nodepágina (es decir,./robot -s node.fmz.com/xxxxxesta cadena de direcciones, donde el contenido enxxxxxla posición es diferente para cada cuenta FMZ). Finalmente, debe introducir la contraseña de su cuenta FMZ. Después de configurar estas configuraciones, ejecute el programa docker.
  • Utilice la función One-Click Deployment de la plataforma FMZ

    Añadir una página de docker en la plataforma FMZ, dirección:https://www.fmz.com/m/add-node

    img

3. Herramienta de depuración

FMZ Quant Trading Platform proporciona una herramienta de depuración gratuita que admiteJavaScript, TypeScript, y la página es:https://www.fmz.com/m/debug. Porque la creación de instancias para ejecutar se factura. Durante el período de aprendizaje inicial, puede usar esta herramienta de depuración para probar y aprender. Excepto por el límite máximo de tiempo de ejecución de 3 minutos, no hay diferencia entre usar la herramienta de depuración y crear una instancia para ejecutar.

Cuando se utiliza elTypeScriptlenguaje, usted necesita escribir// @ts-checken la primera línea de código para cambiar aTypeScriptmodo; si no está activado, el valor predeterminado esJavaScript language.

4. Las plataformas

En FMZ, Platform es un concepto general. Para los intercambios CEX, se refiere a una configuración de cuenta de intercambio específica. Para web3, este intercambio se refiere a una información de configuración que incluye la dirección del nodo y la configuración de la clave privada.

En el estado de inicio de sesión de la plataforma FMZ,https://www.fmz.com/m/add-platformpágina, se puede configurar información de intercambio, donde el intercambio es un concepto general.

img

SeleccionarWeb3, configure la dirección del nodo RPC, configure la clave privada, puede hacer clic en la esquina inferior derecha La información sensible se almacenará encriptada para ver el mecanismo de seguridad.

Los nodos pueden ser nodos autoconstruidos o nodos proporcionados por proveedores de servicios de nodos.Infura. Después de registrarse, puede ver la dirección de nodo de su propia cuenta. Tanto mainnet como testnet están disponibles, lo cual es bastante conveniente. Configure esta dirección de nodo en elRpc AddressLa etiqueta puede ser nombrada por usted mismo para distinguir entre los objetos de intercambio configurados.

img

En la foto,https://mainnet.infura.io/v3/xxxxxxxxxxxxxes la dirección privada del nodo RPC de la red principal de Infura ETH.


Interactúa con Ethereum usando FMZ

Después de desplegar el programa docker y configurar el objeto de intercambio, se puede utilizarFMZ.COMs Debugging Tool para pruebas. Llama a los métodos Ethereum RPC e interactúa con Ethereum, además de los varios métodos RPC enumerados e introducidos en este capítulo, otros métodos RPC se pueden encontrar consultando materiales, como:https://www.quicknode.com/docs.

Para varios lenguajes y herramientas, hay formas de acceder a web3, como se muestra en la imagen:

img

En FMZ, las llamadas al método RPC también están encapsuladas, y estas funciones están encapsuladas en la función FMZ APIexchange.IOEl método de llamada esexchange.IO("api", "eth", ...). El primer parámetro está fijado a"api", el segundo parámetro se fija en"eth", y otros parámetros dependen del método RPC específico que se esté llamando.

Para la información de salida, utilizaremos elLogLa función de la plataforma FMZ.LogLa función puede aceptar múltiples parámetros y luego emitirlos en el área de registro de la página Debug Tool o Bot en la plataforma FMZ. La página Debug Tool será nuestra principal herramienta de prueba.

el_getBalance

Eleth_getBalanceEl método de Ethereum se utiliza para consultar el saldo de ETH de una dirección en Ethereum, y este método requiere dos parámetros.

  • La dirección para ser consultada.
  • Etiqueta, usualmente usamos último. Vamos a comprobar el fundador de EthereumVitalik Buterinla dirección de la billetera de ETH, la dirección conocida es:0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045.
function main() {
    let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
    Log("ethBalance:", ethBalance)
}

Ya desplegado el docker (en la imagen: linux/amd64...) y configurado el objeto de intercambio (en la imagen: prueba Web3), prueba de código en la herramienta de depuración:

img

Haga clic en el botón Execute para ejecutar el código y mostrar los resultados:

EthBalance: 0x117296558f185bbc4c6

EllogLa función imprime elethBalancevalor de la variable como0x117296558f185bbc4c6, que es un tipo de cadena.el valor hexadecimal del saldo del ETHEn elweiunidades, con1e18 weisiendo igual a 1ETHPor lo tanto, necesita ser convertido para convertirse en un saldo decimal de ETH legible.

ConversiónethBalanceen datos legibles:

function main() {
    let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")
    Log("ethBalance:", ethBalance)
    
    // Converting ethBalance into readable data
    let vitalikEthBalance = parseInt(ethBalance.substring(2), 16) / 1e18
    Log("vitalikEthBalance:", vitalikEthBalance)
}

Busca enhttps://etherscan.io/:

img

Sin embargo, debido al problema de precisión del lenguaje en sí, habrá desviaciones en esta forma de procesamiento.

  • BigInt: Convierte una cadena hexadecimal a un objeto BigInt.
  • BigDecimal: Convierte objetos de tipo numérico en objetos BigDecimal computables.

Ajusta el código otra vez:

function main() {
    let ethBalance = exchange.IO("api", "eth", "eth_getBalance", "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest")

    // The precision unit of ETH is 1e18
    let ethDecimal = 18
    Log("vitalikEthBalance:", Number((BigDecimal(BigInt(ethBalance)) / BigDecimal(Math.pow(10, ethDecimal))).toString()))
}

El saldo de la vida es de 5149,6244846875215.

Etiqueta de la cadena

eth_chainIdynet_versionAmbas funciones devuelven la ID de la cadena de bloques a la que está conectado el nodo RPC actual, con la diferencia de quenet_versiondevuelve un Id decimal yeth_chainIdDevuelve una ID hexadecimal.

Nombre de red correspondiente a chainId

1 - ethereum mainnet
2 - morden testnet (deprecated)
3 - ropsten testnet
4 - rinkeby testnet
5 - goerli testnet
11155111 - sepolia testnet
10 - optimism mainnet
69 - optimism kovan testnet
42 - kovan testnet
137 - matic/polygon mainnet
80001 - matic/polygon mumbai testnet
250 - fantom mainnet
100 - xdai mainnet
56 - bsc mainnet

Prueba con la red de pruebas de Ethereum configuradagoerliNodo:

function main() {
    let netVersionId = exchange.IO("api", "eth", "net_version")
    let ethChainId = exchange.IO("api", "eth", "eth_chainId")

    Log("netVersionId:", netVersionId)
    Log("ethChainId:", ethChainId, " , conversion:", parseInt(ethChainId.substring(2), 16))
}

el precio de gas

Llama aleth_gasPricemétodo para consultar el corrientegas priceen la cadena.

function toAmount(s, decimals) {
    return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}

function main() {
    let gasPrice = exchange.IO("api", "eth", "eth_gasPrice")
    Log("gasPrice:", gasPrice, " , conversion:", toAmount(gasPrice, 0))
}

Aquí escribimos una función para convertir la cadena hexadecimal en un valor numérico legible:toAmountAdemás, hay que tener en cuenta que la unidad degasPriceeswei, así pasar el valor 0 al parámetro real correspondiente al parámetro formaldecimals.

Número de bloque

"eth_blockNumberse utiliza para consultar la altura del bloque.

function toAmount(s, decimals) {
    return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}

function main() {
    let blockNumber = exchange.IO("api", "eth", "eth_blockNumber")
    Log(toAmount(blockNumber, 0))
}

Ejecute la herramienta de depuración:

img

Busca enhttps://etherscan.io/:

img

eth_getBlockByNumber (El bloque por número)

Información del bloque de búsqueda.

function main() {
    let blockNumber = exchange.IO("api", "eth", "eth_blockNumber")    
    Log(blockNumber)
    let blockMsg = exchange.IO("api", "eth", "eth_getBlockByNumber", blockNumber, true)
    Log(typeof(blockMsg), blockMsg)
    
    // Due to the excessive content of Log output, it will be truncated automatically, so traverse each field of the returned block information and print them one by one
    for (let key in blockMsg) {
        Log("key:", key, ", val:", blockMsg[key])
    }
}

La ejecución en la Herramienta de depuración puede obtener la siguiente información:

img

Leer la información del contrato

Muchas aplicaciones de contratos inteligentes funcionan en Ethereum, yENSes uno de ellos.ENS, o Ethereum Name Service, es un servicio descentralizado de resolución de nombres de dominio basado en la cadena de bloques Ethereum. ¿Recuerdas el ejemplo en el tutorial donde verificamos el saldo de la billetera del fundador de Ethereum, Vitalik Buterin?0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045De hecho, se puede consultar a través de laENScontrato inteligente con un nombre intuitivovitalik.eth.

El siguiente contenido de este capítulo utiliza el entorno de la red principal de Ethereum, de acuerdo con elENSla documentación,Hashing Namesse requieren para consultar nombres de dominio de Ethereum. Utilice el siguiente código para procesarvitalik.eth.

function nameHash(name) {
    if (name == "") {
        return "0000000000000000000000000000000000000000000000000000000000000000"
    } else {
        let arr = name.split(".")
        let label = arr[0]
        
        arr.shift()
        let remainder = arr.join(".")
        return Encode("sha3.keccak256", "hex", "hex", nameHash(remainder) + Encode("sha3.keccak256", "raw", "hex", label))
    }
}

En el ejemplo de código anterior, vimos otra función desconocidaEncodeEsta función es una función API de la plataforma FMZ y se utiliza específicamente para codificar operaciones en la plataforma FMZ. La función admite múltiples métodos de codificación y varios algoritmos de hash.

Encode(algo, inputFormat, outputFormat, data, keyFormat, key string)

De acuerdo con la descripción del documento ENS, utilice elsha3.keccak256algoritmo para procesar datos.

Llama alnameHashfunción, por ejemplo:Log(nameHash("vitalik.eth")), puede obtener:ee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835, y necesitas añadir el prefijo 0x.0xee6c4522aab0003e8d14cd40a6af439055fd2577951148c14b6cea9a53475835se utiliza como parámetro delresolvermétodo en el contrato inteligente ENS.

let ensNode = "0x" + nameHash("vitalik.eth")    // Prepare the parameters ensNode for calling the resolver method

Según la documentación ENS, la dirección del contrato para las aplicaciones de contratos inteligentes ENS es:0x00000000000C2E074eC69A0dFb2997BA6C7d2e1eAntes de llamar a laresolverEn la actualidad, la mayoría de los contratos inteligentes están en el mercado.ABIdel contrato.

Registro de la ABI

Al saber esto, usted puede preguntar: ¿cuál es laABI¿De un contrato inteligente?

ABI, or Application Binary Interface, is the interface standard for smart contracts to communicate with the external world.
The ABI of a smart contract defines the contract's function interfaces, parameter types, return values, and other information, as well as specifications for calling the contract and passing parameters.

The ABI of a smart contract is usually stored in JSON format and contains the following information:

Contract function interfaces: function names, parameter lists, return values, etc.
Function parameter types: such as uint256, bool, string etc.
Encoding methods for input and output parameters of functions: Smart contracts use an encoding method called Solidity ABI to encode input and output parameters of functions so that they can interact with Ethereum network.
In Ethereum network ,the ABI of a smart contract is used to call its functions. When you need to call a contract function, you need to provide the name of the function, its parameters, and bytecode encoded according to ABI encoding method.
Ethereum nodes will package this information into transactions and send them out on Ethereum network for execution.

In Solidity language,the keyword 'interface' can be used define ABIs for smart contracts. Ethereum development tools like Remix IDE ,Truffle also provide editing & generation tools making it easier developers create & use ABIs.

Extraer elresolverEn el caso de los contratos, el ABI de los contratos se puede consultar en el siguiente enlace:https://etherscan.io/o obtener el ABI a través de otros canales (por ejemplo, documentación del proyecto pertinente).

img

let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`

Aquí vamos a aprender un nuevo método de invocación en la plataforma FMZ,exchange.IO("abi", address, abiContent), que se utiliza para registrar ABI.addressParámetro es la dirección del contrato inteligente y elabiContentel parámetro es el correspondiente contrato inteligente ABI (cuadrícula).

let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", abiENS_resolver)  // 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e is the address of the ENS smart contract deployed on the Ethereum mainnet

Métodos para llamar a los contratos inteligentes

A continuación, puede llamar a laresolverEl método del contrato inteligente ENS, que devuelve la dirección de laENS: Public Resolver contract.

img

let resolverAddress = exchange.IO("api", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", "resolver", ensNode)

Utilice elENS: Public ResolverLos contratosaddrPara obtener la dirección de la billetera de Vitalik Buterin.ENS: Public ResolverLa información de ABI para este contrato inteligente todavía se puede obtener dehttps://etherscan.io/.

let abiENSPublicResolver = `[{"inputs":[{"internalType":"contract ENS","name":"_ens","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"coinType","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newAddress","type":"bytes"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"AuthorisationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"hash","type":"bytes"}],"name":"ContenthashChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"record","type":"bytes"}],"name":"DNSRecordChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"}],"name":"DNSRecordDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"DNSZoneCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"indexed":false,"internalType":"address","name":"implementer","type":"address"}],"name":"InterfaceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"x","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"string","name":"indexedKey","type":"string"},{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"TextChanged","type":"event"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"}],"name":"addr","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"authorisations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"clearDNSZone","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"contenthash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint16","name":"resource","type":"uint16"}],"name":"dnsRecord","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"hasDNSRecords","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"interfaceImplementer","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentType","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"},{"internalType":"bytes","name":"a","type":"bytes"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"a","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"setAuthorisation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"hash","type":"bytes"}],"name":"setContenthash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setDNSRecords","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"internalType":"address","name":"implementer","type":"address"}],"name":"setInterface","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setText","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"}],"name":"text","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]`
exchange.IO("abi", resolverAddress, abiENSPublicResolver)

img

Por último, llama alENS: Public ResolverLos contratosaddrmétodo, siendo el parámetroensNode.

let vitalikAddress = exchange.IO("api", resolverAddress, "addr", ensNode)
Log("vitalikAddress:", vitalikAddress)

Salida de la función de registro:

vitalikAddress: 0xd8da6bf26964af9d7eed9e03e53415d37aa96045

Llama al código completo del ENS

function nameHash(name) {
    if (name == "") {
        return "0000000000000000000000000000000000000000000000000000000000000000"
    } else {
        let arr = name.split(".")
        let label = arr[0]
        
        arr.shift()
        let remainder = arr.join(".")
        return Encode("sha3.keccak256", "hex", "hex", nameHash(remainder) + Encode("sha3.keccak256", "raw", "hex", label))
    }
}

function main() {
    // Calculate the name
    let ensNode = "0x" + nameHash("vitalik.eth")    

    // Register ENS contract
    let abiENS_resolver = `[{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]`
    exchange.IO("abi", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", abiENS_resolver)
    let resolverAddress = exchange.IO("api", "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", "resolver", ensNode)
    
    // Register ENS Public Resolver contract
    let abiENSPublicResolver = `[{"inputs":[{"internalType":"contract ENS","name":"_ens","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"contentType","type":"uint256"}],"name":"ABIChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"a","type":"address"}],"name":"AddrChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"coinType","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newAddress","type":"bytes"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"AuthorisationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"hash","type":"bytes"}],"name":"ContenthashChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"record","type":"bytes"}],"name":"DNSRecordChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"name","type":"bytes"},{"indexed":false,"internalType":"uint16","name":"resource","type":"uint16"}],"name":"DNSRecordDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"DNSZoneCleared","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"indexed":false,"internalType":"address","name":"implementer","type":"address"}],"name":"InterfaceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"NameChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"x","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"PubkeyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"string","name":"indexedKey","type":"string"},{"indexed":false,"internalType":"string","name":"key","type":"string"}],"name":"TextChanged","type":"event"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentTypes","type":"uint256"}],"name":"ABI","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"addr","outputs":[{"internalType":"address payable","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"}],"name":"addr","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"authorisations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"clearDNSZone","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"contenthash","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint16","name":"resource","type":"uint16"}],"name":"dnsRecord","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"name","type":"bytes32"}],"name":"hasDNSRecords","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"interfaceImplementer","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"pubkey","outputs":[{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"contentType","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setABI","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint256","name":"coinType","type":"uint256"},{"internalType":"bytes","name":"a","type":"bytes"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"a","type":"address"}],"name":"setAddr","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"isAuthorised","type":"bool"}],"name":"setAuthorisation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"hash","type":"bytes"}],"name":"setContenthash","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setDNSRecords","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes4","name":"interfaceID","type":"bytes4"},{"internalType":"address","name":"implementer","type":"address"}],"name":"setInterface","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"x","type":"bytes32"},{"internalType":"bytes32","name":"y","type":"bytes32"}],"name":"setPubkey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"},{"internalType":"string","name":"value","type":"string"}],"name":"setText","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"string","name":"key","type":"string"}],"name":"text","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}]`
    exchange.IO("abi", resolverAddress, abiENSPublicResolver)
    let vitalikAddress = exchange.IO("api", resolverAddress, "addr", ensNode)
    Log("vitalikAddress:", vitalikAddress)
}

Envío de ETH

En los capítulos anteriores del curso, hemos aprendido cómo configurar claves privadas. ¿Cómo sabemos la dirección de la billetera correspondiente a esta clave privada para el objeto de intercambio configurado?exchange.IO("address")función para obtener la dirección de la billetera correspondiente a la clave privada configurada.

El siguiente contenido en este capítulo utiliza el entorno de Goerli testnet, por lo que el nodo que estoy utilizando es:https://goerli.infura.io/v3/*******, y Infura asigna diferentes direcciones de nodos para cada usuario registrado.*******Esconde contenido específico.

function main() {
    let walletAddress = exchange.IO("address")
    Log("Testnet goerli wallet address:", walletAddress)
}

Después de conocer la dirección de tu billetera, puedes usar el método RPC de Ethereumeth_getTransactionCountEn Ethereum, este recuento es muy común, y en realidad es el número de transacciones de la dirección de la billetera.nonceEn Ethereum, nonce es un número único utilizado para asegurar que cada transacción sea única. Es un número creciente, y aumentará automáticamente cada vez que se envíe una nueva transacción. Por lo tanto, cuando envías una transacción a un contrato inteligente, necesitas proporcionar un nonce para asegurar que la transacción sea única y en el orden correcto. Podemos encontrar esta información en algunos materiales y documentos:

https://goethereumbook.org/en/

img

Aquí, elPendingNonceAtLa función en la biblioteca de Ethereum del lenguaje Go es en realidad llamar a laeth_getTransactionCountEn los cursos anteriores, también hemos aprendido a llamar a los métodos RPC.exchange.IO("api", "eth", ...)funcionan de nuevo.

function toAmount(s, decimals) {
    return Number((BigDecimal(BigInt(s)) / BigDecimal(Math.pow(10, decimals))).toString())
}

function main() {
    let walletAddress = exchange.IO("address")
    Log("Testnet goerli wallet address:", walletAddress)

    /**
    * eth_getTransactionCount
    * @param address - string - The address from which the transaction count to be checked.
    * @param blockNumber - string - The block number as a string in hexadecimal format or tags.
    * @returns The integer of the number of transactions sent from an address encoded as hexadecimal.
    */
    let nonce: string = exchange.IO("api", "eth", "eth_getTransactionCount", walletAddress, "pending")
    Log("wallet address:", walletAddress, "current nonce:", nonce, ", convert to decimal:", toAmount(nonce, 0))
}

Antes de explicar la operación de transferencia, entendamos brevemente algunos conceptos. Al transferir en Ethereum, se consumirá una cierta cantidad de tokens ETH (como tarifas de gas).

  • Gas precio

    Sin embargo, las tarifas de gas en la red Ethereum siempre fluctúan de acuerdo con la demanda del mercado y las tarifas que los usuarios están dispuestos a pagar, por lo que escribir una tarifa de gas fija en el código a veces no es una opción ideal.eth_gasPricemétodo que aprendimos antes, que puede obtener el precio promedio de la gasolina.

  • GasLimit

    Una transferencia estándar de Ether tiene un límite de gas de 21.000 unidades.

Después de comprender los conceptos denonce, gasPrice, ygasLimitFMZ proporciona una función de transferencia muy simple y fácil de usar.

exchange.IO("api", "eth", "send", toAddress, toAmount)

Cuando se utiliza para transferencias, el tercer parámetro deexchange.IOse fija como enviar, eltoAddressel parámetro es la dirección que recibe ETH durante la transferencia, ytoAmountes la cantidad de ETH transferida.

Los parámetrosnonce, gasPrice, ygasLimitpueden utilizar todos los valores predeterminados del sistema obtenidos automáticamente en FMZ. También se pueden especificar:

exchange.IO("api", "eth", "send", toAddress, toAmount, {gasPrice: 5000000000, gasLimit: 21000, nonce: 100})

A continuación, transferiremos una cierta cantidad de ETH a una dirección específica en la red de prueba de Goerli:

function toInnerAmount(s, decimals) {
    return (BigDecimal(s)*BigDecimal(Math.pow(10, decimals))).toFixed(0)
}

function main() {
    let walletAddress = exchange.IO("address")
    Log("Testnet goerli wallet address:", walletAddress)

    let ret = exchange.IO("api", "eth", "send", "0x4D75a08E870674E68cAE611f329A27f446A66813", toInnerAmount(0.01, 18))
    return ret // return Transaction Hash : 0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e
}

Porque la unidad de la cantidad de transferencia de Ethereum eswei, una función personalizadatoInnerAmountSe necesita utilizar para procesar el valor enwei units.

Hash de transacción de consulta:0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734eEn elhttps://etherscan.io/.

img

También se puede escribir código para la consulta transferencia hash0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e, utilizando eleth_getTransactionReceiptmétodo para las consultas.

function main() {
    let transHash = "0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e"
    let info = exchange.IO("api", "eth", "eth_getTransactionReceipt", transHash)
    return info
}

Resultado de la consulta:

{
	"cumulativeGasUsed": "0x200850",
	"effectiveGasPrice": "0x1748774421",
	"transactionHash": "0xa6f9f51b00d8ae850b0f204380b59da98f4bbce34b813577d3d948f61de4734e",
	"type": "0x0",
	"blockHash": "0x6bdde8b0f0453ecd24eecf7c634d65306f05511e0e8f09f9ed3f59eee2d06ac7",
	"contractAddress": null,
	"blockNumber": "0x868a50",
	"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
	"gasUsed": "0x5208",
	"to": "0x4d75a08e870674e68cae611f329a27f446a66813",
	"status": "0x1",
	"transactionIndex": "0x23",
	"from": "0x6b3f11d807809b0b1e5e3243df04a280d9f94bf4",
	"logs": []
}

Descripción correspondiente a cada campo:

blockHash - The hash value of the block where the transaction is located.
blockNumber - The block number of the block where the transaction is located, encoded in hexadecimal.
contractAddress - If it's a contract creation, the address of the contract; otherwise null.
cumulativeGasUsed - The total gas used when executing this transaction in the block.
effectiveGasPrice - Total base fee plus tip per unit of gas.
from - Sender's address.
gasUsed - Gas used by this specific transaction.
logs - Array of log objects generated by this transaction.
  address - Address that generated this log.
  topics - Data array with 0 to 4 indexed log parameters, each with 32 bytes. In Solidity, first topic is event signature hash (e.g., Deposit(address,bytes32,uint256)), unless you declare an event using anonymous specifier.
  data - Non-indexed parameters for logs with length of 32 bytes.
  blockNumber - The block number of the block where this log is located.
  transactionHash - Transaction hash at time when log was created. Null if pending state.
  transactionIndex - Index position during creation. Null if pending state.
  blockHash - The hash value for containing block.
  logIndex - Hexadecimal-encoded integer index position within containing block. Null if pending state.
  removed - True if deleted due to chain reorganization; false for valid logs.
logsBloom - Bloom filter for retrieving related logs.
status - Hexadecimal-encoded value either being '1' (success) or '0' (failure).
to - Receiving party's address; null for contract creation transactions.
transactionHash - The hash value associated with given transaction.
transactionIndex - Hexadecimal-encoded index position within its respective containing-block.
type - Type value.

Llame al contrato inteligente de Ethereum

En el capítulo sobre Reading Contract Information, usamos un ejemplo completo para llamar al método de contrato ENS desplegado en Ethereum para obtener la dirección de la billetera de Vitalik Buterin.Readmétodos, y llamar a estos métodos no requieregas(recuerdan lo que hablamos de gas antes?).Writemétodos de contratos inteligentes en Ethereum y pagar porgasEstas operaciones serán verificadas por cada nodo y minero en toda la red y cambiar el estado de la cadena de bloques.

En el caso de las entidades financieras:

Para el contrato ERC20 (contrato de tokens ERC20), la plataforma FMZ enumera el ABI del contrato ERC20 ABI como un ABI común integrado directamente en el sistema, eliminando el paso de registrar el ABI.

Para comprender mejor ABI, puede comprobarlo antes de usarlo.

[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"tran

Relacionados

Más.