¿Cuáles son las dificultades o limitaciones comunes al codificar en Solidity?

¿Qué estaría en su lista para advertir a otros desarrolladores?

¿Qué funciona en la mayoría de los otros idiomas que no funciona o no se comporta como se esperaba en Solidity?

Solo por ejemplo: ¿qué parámetros se pueden pasar a las funciones, qué se puede devolver de las funciones?

Respuestas (6)

Declarar una matriz local (u otro tipo de referencia ) y asumir que se creará en la memoria pero que en realidad sobrescribirá el almacenamiento :

/// THIS CONTRACT CONTAINS AN ERROR
contract C {
    uint someVariable;
    uint[] data;

    function f() {
        uint[] x;
        x.push(2);
        data = x;
    }
}

El tipo de la variable local x es almacenamiento uint[], pero dado que el almacenamiento no se asigna dinámicamente, debe asignarse desde una variable de estado antes de poder usarse. Por lo tanto, no se asignará espacio en el almacenamiento para x, sino que funcionará solo como un alias para una variable preexistente en el almacenamiento.

Lo que sucederá es que el compilador interpreta x como un puntero de almacenamiento y hará que apunte a la ranura de almacenamiento 0 de forma predeterminada. Esto tiene el efecto de que someVariable (que reside en la ranura de almacenamiento 0) es modificada por x.push(2).

La forma correcta de hacerlo es la siguiente:

contract C {
    uint someVariable;
    uint[] data;

    function f() {
        uint[] x = data;
        x.push(2);
    }
}

OR

contract C {
    uint someVariable;
    uint[] data;

    function f() {
        uint[] memory x = new uint[](1);
        x[0] = 2;
        data = x;
    }
}
¿Puede POR FAVOR proporcionar un ejemplo de código?
@JossieCalderon Buena llamada, gracias, espero que sea mucho más clara.

de los documentos

En for (var i = 0; i < arrayName.length; i++) { ... }, el tipo de i será uint8, porque este es el tipo más pequeño que se requiere para contener el valor 0. Si la matriz tiene más de 255 elementos, el ciclo no terminará.

además

Todavía no es posible utilizar matrices de matrices en funciones externas. ... Solo puede usar un nivel de matrices dinámicas [en cualquier lugar].

y

Debido a las limitaciones de EVM, no es posible devolver contenido dinámico desde llamadas a funciones externas. La función f en contrato C { función f() devuelve (uint[]) { ... } } devolverá algo si se llama desde web3.js, pero no si se llama desde Solidity. La única solución por ahora es usar arreglos grandes de tamaño estático.

  • Proporcione siempre suficiente gasolina para una transacción (el 90% de los errores de novatos se deben a que no hay suficiente gasolina)
  • Las excepciones consumirán todo el gas de la transacción (usar con precaución)
  • No se puede verificar fácilmente si su contrato lanza una excepción
  • No es fácil verificar si su transacción se quedó sin gasolina
  • Las cosas pueden funcionar con testnet, pero pueden fallar en una testnet privada (marque para que funcione en ambos)
  • Hay soporte limitado para cadenas sin bibliotecas externas
  • Algunas funciones pueden fallar (como enviar), verifique el valor de retorno
  • Esté atento a los problemas de reingreso (especialmente al enviar dinero u otro tipo de token)

string[] no están permitidos en parámetros de función o retornos.

consulte la discusión aquí:
¿Es imposible usar una matriz de cadenas como argumento para la función de solidez?

returnscon parámetros de salida con nombre introduce una nueva variable local.

Por ejemplo, de esta pregunta :

contract Test {
    address owner;

    function Test(){
        owner = msg.sender;
    }

    function getOwner() returns (address owner) {
        return owner;
    }
}

Aquí en getOwnernew variable ownerse introduce y se inicializa a cero. Coincidentemente, anula la variable de estado, ownerlo que conduce a un resultado inesperado.


Las asignaciones solo se permiten para variables de estado (o como tipos de referencia de almacenamiento en funciones internas).

Por ejemplo, de esta pregunta :

function getBalance(address addr) returns (uint, uint) {
    mapping(address => uint)  balancers;
    balancers[msg.sender] = 500;

    return (balancesA[addr], balancesB[addr]);
}

Aquí mapping(address => uint) balancesno asigna una nueva asignación, sino que introduce una variable no inicializada. Por lo tanto, el acceso balancers[msg.sender]no es válido.

  • El uso deleteen una matriz deja un espacio, por lo que debe cambiar los elementos manualmente y actualizar la propiedad de longitud.

  • stringes lo mismo que bytespero no permite el acceso a la longitud ni al índice.

  • byteses lo mismo byte[]pero empaquetado herméticamente (más caro).

  • Los sufijos de fecha no se pueden aplicar a las variables.

  • Solidity hereda las reglas de alcance de JavaScript; no hay alcance de bloque.

Para obtener más trucos de solidez, consulte https://github.com/miguelmota/solidity-idiosyncrasies