Guía de desarrollo no autorizado de Solidity (2): resumen de sintaxis

Contacto

Similar a la clase, puede ser: abstracta, heredada y convocada por otros contratos.

Uso típico:

  • Crear un nuevo contrato:new MyContract(...)
  • Utilice el contrato desplegado:MyContract($address)

visibilidad

visibilidad similar aplicar para accesible desde el exterior Los subcontratos son accesibles
externo función
público público función + variable de estado
interno protegido función + variable de estado
privado privado función + variable de estado

Nota: Para las variables públicas, el captador correspondiente se generará automáticamente (consulte: Guía de desarrollo no autorizada de Ethers.js (continuación) para obtener más detalles ).

Elementos clave

elemento ilustrar ejemplo
Variables de estado Almacenado permanentemente en la cadena, toma gas uint data;
función Hay dos tipos de lectura/escritura, y el método de escritura necesita consumir gas; puede existir dentro y fuera del contrato function func() public {...}
retroceder() No se puede llamar directamente desde el exterior, se ejecutará cuando no haya ninguna función en el contrato de solicitud fallback() external { ... }
recibir() No se puede llamar directamente externamente, se ejecuta al recibir eth receive() external payable {...}
modificador Restricciones declarativas reutilizables, ejecutadas antes de las llamadas a funciones. Declaración: modifier onlyOwner(){...}Uso:function func() public onlyOwner {...}
evento El registro de ejecución en la cadena se puede consultar en el futuro. emit Event1(data);
estructura tipo personalizado struct MyType { uint item1; bool item2; }
error excepción personalizada Declaración: error MyError(unit reason);Uso:revert MyError(200);
enumerar La mejor opción para valores constantes finitos enum State { Created, Locked, Inactive }

Nota:

  • pagadero, la función que recibe eth debe agregar

  • view o pure, lo que indica que la función no cambiará el estado de Ethereum

  • funciones de respaldo y recepción

    • Ninguno puede tener un nombre de función, por lo que no hay  function palabras clave.
    • debe usar external
    • La función alternativa también se puede pagar, pero se recomienda utilizar primero la función de recepción.
    • Las funciones de respaldo y recepción pagables pueden consumir hasta 2300 de gas, lo que debe probarse aquí.
    • El respaldo ordinario no tiene esta limitación, siempre que el gas sea suficiente, se puede realizar cualquier operación compleja.

Para obtener detalles sobre cómo usar registros de eventos y consultas en dapps, consulte: Guía de desarrollo no autorizado de Ethers.js (Parte 2)

Interfaz

De forma similar a las interfaces en otros idiomas, puede:

  • Heredar otras interfaces
  • Solo declaraciones de métodos, nada más.
  • Todos los métodos son externos.

Biblioteca

Similar al contrato, pero:

  • no puede usar variables de estado
  • no puede heredar o ser heredado
  • no puedo recibir eth
  • No puede ser ejecutado de forma independiente y debe ser referenciado por otros contratos.

La relación entre ambos es similar: contrato, archivo ejecutable; biblioteca, biblioteca de enlaces dinámicos

tipo de datos

Tipos de valor y tipos de referencia

similar
tipo de valor bool, uint / int, dirección, byte, enumeración
tipo de referencia Matriz (como bytes / cadena), estructura, mapeo

Nota:

  • matrices de bytes y cadenas

    • keccak256(abi.encodePacked(s1)) == keccak256(abi.encodePacked(s2))
    • bytes bs = 'bytes';
    • string str = 'string';
    • byte1 b1 = 'a';
    • byte2 b2 = 256;, 256 supera el tamaño de un solo byte
    • Matriz de bytes de longitud fija: byte1 ~ byte32
    • Datos de bytes dinámicos: bytes y cadena, donde la cadena se codifica en utf-8.
    • Solidity no proporciona un método para la comparación de cadenas, pero se puede hacer con la ayuda de una función hash.
  • formación

  • int[] age = [10, 20, 30, 40, 50];

  • int[] age = new int[](5);

  • int[5] age = [10, 20, 30, 40, 50];

  • Las matrices de longitud fija no se pueden inicializar con nuevas

  • Las matrices dinámicas pueden usar una asignación nueva o inicial al mismo tiempo

  • Hay dos tipos de dirección: address y  address payable, frente a la primera, la segunda tiene más funciones de transferencia.

ubicación de almacenamiento

similar ejemplo
almacenamiento Persistencia, memoria global en el contrato Variables de estado
memoria Memoria local de la función, no persistente entrada de función
datos de llamada Parámetros de entrada de funciones, no persistentes entrada de función
pila Pila de llamadas de EVM

Reglas relevantes:

  • Priorice los datos de llamadas porque pueden evitar la copia y no se pueden modificar

  • Función variables locales:

    • mapping (uint => address) storage localNames = names;
    • Cuando es almacenamiento, debe apuntar a la variable de estado externa
    • tipo de valor, memoria
    • Tipo de referencia, el valor predeterminado es almacenamiento, pero se puede especificar como memoria.
    • mapeo, almacenamiento, siempre apuntan a variables de estado externas. El siguiente ejemplo  names es una variable de estado definida en un contrato, y su tipo también es mapeo.
  • Reglas de asignación

  • tipo de valor, haciendo una copia independiente

  • tipo de referencia, copia de referencia

  • La asignación entre almacenamiento y memoria/calldata siempre produce una copia independiente.

  • Asignación entre variables de memoria

  • almacenamiento Asigna un valor a una variable de almacenamiento local, copiando la referencia.

  • Otras asignaciones de almacenamiento siempre generan copias independientes.

variables globales y métodos

ilustrar ejemplo
unidad ética wei, wei, éter 1 gwei
unidad de tiempo segundos, minutos, horas, días, semanas 1 minutes
bloquear objeto de bloque
bloquehash() Si el parámetro de entrada es uno de los últimos 256 bloques, será su hash. De lo contrario, 0.
mensaje objeto de mensaje
tx objeto de transmisión
izquierda gas() gas restante
abi objeto abi
DIRECCIÓN objeto de dirección
este El objeto del contrato actual, que se puede convertir explícitamente en dirección address(this).balance
tipo() clasificar información
añadir mod (a + b) %k
mulmod (a * b) %k
función hash keccak256,sha256,ripemd160
ecrecover Recuperar la dirección de la firma

详见:Unidades y variables disponibles globalmente — documentación de Solidity - 0.8.18

Nota:

  • La diferencia entre tx.orgin y msg.sender

    • tx.orgin es la primera cuenta que inicia tx y su valor siempre es eoa.
    • msg.sender es la cuenta de llamada directa de la función actual, que puede ser eoa o dirección de contrato.
  • Asegúrese de que el primer parámetro de ecrecover sea un hash de firma de mensaje eth válido, lo que se puede hacer con la ayuda de la clase de herramientas ecdsa de openzepplin.

  • Se usa primero  address.transfer, y cuando falla, transfer lanza una excepción y  sender regresa  false.

  • Los métodos de bajo nivel (llamada, llamada delegada, llamada estática, envío, transferencia) en la dirección tienen dos lados:

  • Son baratos de ejecutar debido a la falta de controles de tiempo de ejecución como tipo, existencia, etc.

  • Por lo tanto, no es seguro.

  • El uso de llamada, llamada delegada y llamada estática en la dirección es similar, pero los escenarios de aplicación son diferentes:

  • llamada, aplicada al contrato

  • llamada delegada, aplicada a la biblioteca

  • staticcall, aplicado a métodos de contrato de solo lectura, a saber, métodos de vista o puros, de lo contrario, se lanzará una excepción.

  • Una típica llamada address.call:

bytes memory payload = abi.encodeWithSignature("register(string)", "MyName");
(bool success, bytes memory returnData) = address(nameReg).call(payload);
require(success);
  • Si necesita ajustar el gas y enviar eth, entonces:
address(nameReg).call{gas: 1000000, value: 1 ether}(abi.encodeWithSignature("register(string)", "MyName"));

manejo de excepciones

Tipo de excepción:

  • Pánico, error interno, como división por cero.
  • Error, excepción general.

Después de que el contrato arroja una excepción, el estado se revierte. Actualmente hay 3 formas:

  • require (expresión), si la expresión es falsa, se lanza una excepción y se devuelve el gas no utilizado

    • Es adecuado para el parámetro de entrada de la función de verificación y arroja Error.
    • La versión actual de require no se puede usar con tipos de error personalizados. Si es necesario, use la combinación de "declaración condicional + revertir".
  • afirmar (expresión), igual que arriba, pero el gas no utilizado no se reembolsará y se consumirá en su totalidad

  • Adecuado para verificar el estado interno y lanzar Panic.

  • revert(), lanzar Error directamente o personalizar Error, similar a lanzar en otros idiomas.

Ejemplo de una sentencia try...catch:

try feed.getData(token) returns (uint v) {
    return (v, true);
} catch Error(string memory /*reason*/) {
    // require 导致
    errorCount++;
    return (0, false);
} catch Panic(uint /*errorCode*/) {
    // assert 导致
    errorCount++;
    return (0, false);
} catch (bytes memory /*lowLevelData*/) {
    // revert 导致
    errorCount++;
    return (0, false);
}

Supongo que te gusta

Origin blog.csdn.net/smartContractXH/article/details/128202072
Recomendado
Clasificación