Solidez más de uno si la evaluación de declaraciones falló

Estoy tratando de evaluar más de una declaración if , pero después de un cierto número de declaraciones if, la remezcla arroja un error: error: no se pudo decodificar la salida: TypeError: no se puede leer la propiedad 'longitud' de undefined . Por el error, parece que la longitud no está definida, pero el mismo código funciona bien si reduzco el número si las declaraciones . Para el caso actual, si pruebo 3 if s, está bien, pero tan pronto como agrego uno más , la remezcla arroja un error.

Tengo dos contratos: uno es padre y otro es hijo . El contrato principal se instancia en el contrato secundario y sus funciones se heredan.

pragma solidity ^0.4.20;

contract Parent {

    struct Info{
        string fName;
        string lName;
    }

    uint256[] values;

    mapping(address => Info) names;
    mapping (address => uint256[])transactions;
    mapping (address => uint) accountBalance;


    function setName(address addr,string _fName, string _lName){
        names[addr] = Info(_fName, _lName);
    }

    function getFName(address addr) constant returns (string){
        return names[addr].fName;
    }

    function getLName(address addr) constant returns (string){
        return names[addr].lName;
    }

    function storeValue(address addr, uint256 _value) {
        transactions[addr].push(_value);
        accountBalance[addr] += _value;
    }

    function accountTx(address addr) constant returns(uint256[]) {
        return (transactions[addr]);
    }

    function totalBalance(address addr) constant returns(uint){
        return accountBalance[addr];
    }

}

y este es el contrato de niño:

pragma solidity ^0.4.20;

import './Parent1.sol';

contract Child {

  /* instantiating parent contract*/
  Parent p = Parent(0x692a70d2e424a56d2c6c27aa97d1a86395877b3a);

  uint256 public totalSupply;
  mapping (address => uint256) balances;

  function getName(address addr)constant returns(string, string){
      return (p.getFName(addr), p.getLName(addr));
  }

  function addBalance(address addr){
      if (uint(keccak256(p.getFName(addr))) == uint(keccak256("a")) && uint(keccak256(p.getLName(addr))) == uint(keccak256("b"))){
          balances[addr] += (p.accountTx(addr)[p.accountTx(addr).length - 1]) * 2;
          totalSupply += (p.accountTx(addr)[p.accountTx(addr).length - 1]) * 2;

      }

      if (uint(keccak256(p.getFName(addr))) == uint(keccak256("a")) && uint(keccak256(p.getLName(addr))) == uint(keccak256("c"))){
          balances[addr] += (p.accountTx(addr)[p.accountTx(addr).length - 1]) * 3;
          totalSupply += (p.accountTx(addr)[p.accountTx(addr).length - 1]) * 3;

      }

      if (uint(keccak256(p.getFName(addr))) == uint(keccak256("a")) && uint(keccak256(p.getLName(addr))) == uint(keccak256("d"))){
          balances[addr] += (p.accountTx(addr)[p.accountTx(addr).length - 1]) * 4;
          totalSupply += (p.accountTx(addr)[p.accountTx(addr).length - 1]) * 4;

      }

      if (uint(keccak256(p.getFName(addr))) == uint(keccak256("a")) && uint(keccak256(p.getLName(addr))) == uint(keccak256("e"))){
          balances[addr] += (p.accountTx(addr)[p.accountTx(addr).length - 1]) * 5;
          totalSupply += (p.accountTx(addr)[p.accountTx(addr).length - 1]) * 5;

      }

      else {
          balances[addr] += (p.accountTx(addr)[p.accountTx(addr).length - 1]) * 6;
          totalSupply += (p.accountTx(addr)[p.accountTx(addr).length - 1]) * 6;

      }

  }

  function checkBalance(address addr) constant returns(uint){
      return balances[addr];
  }

}

Si solo crea dos contratos en remix copiando y pegando los códigos tal como están, y luego implementa el contrato principal, establezca algunos nombres y valores, copie la dirección del contrato implementado y reemplace la dirección aquí:

Parent p = Parent(0x692a70d2e424a56d2c6c27aa97d1a86395877b3a);

obtendrá el error, pero si simplemente elimina la condición , funcionará bien.

Los contratos son una versión simplificada de mis contratos originales y probé algunas alternativas pero no tuve suerte.

¿Alguien puede ayudarme a explicar por qué es este comportamiento extraño y cómo puedo continuar con más de uno si ?

con gracias,

Respuestas (1)

Por lo que ha dicho, es cuando está probando con ciertos valores que una de sus declaraciones if arroja un error. ¿Verificó que el mapeo de transacciones no esté vacío para los valores con los que está probando? Le ha pedido a la gente que le haga pruebas aleatorias. Sin información más específica sobre los valores que usó para producir el error y en qué instrucción if ocurrió el error, es difícil entender cómo produjo el error en primer lugar.

Podría intentar reducir algo de complejidad en el código para hacerlo más eficiente y ayudar a que los errores sean más fáciles de rastrear.

Dividiría su función addBalance() en dos partes creando una función getMultiplier() porque las declaraciones if solo intentan identificar qué valor multiplicador usar.

function addBalance(dirección dirección){
    multiplicador de puntos;
    multiplicador = obtenerMultiplicador(dirección);

    // Debe verificar que tiene un valor multiplicador antes de actualizar su saldo y los valores de suministro total.
    saldos[dirección] += (p.cuentaTx(dirección)[p.cuentaTx(dirección).longitud - 1]) * multiplicador ;
    totalSupply += (p.cuentaTx(dirección)[p.cuentaTx(dirección).longitud - 1]) * multiplicador ;  
}

función getMultiplier(dirección dirección) devuelve (uint){

  if (uint(keccak256(p.getFName(dirección))) == uint(keccak256("a")) ) {

    if ( uint(keccak256(p.getLName(dirección))) == uint(keccak256("b")) ){
        devolver 2;
    }

    if ( uint(keccak256(p.getLName(dirección))) == uint(keccak256("c")) ){
        devolver 3;
    }

    if (uint(keccak256(p.getLName(dirección))) == uint(keccak256("d")) ){
        devolver 4;
    }

    if (uint(keccak256(p.getLName(dirección))) == uint(keccak256("e")) ){
         devolver 5;
    } demás {
        devolver 6;
    }
  }
}


Cada una de sus declaraciones if comenzó con la misma condición.

if( uint(keccak256(p.getFName(dirección))) == uint(keccak256("a")) && ....

Si esta condición falla la primera vez, no debe continuar comprobando todas las demás declaraciones if porque ya sabe que también fallarán. Entonces mueve esto a una condición previa antes de comenzar a verificar cada una de las condiciones del apellido.

El uso de la función getMultiplier() también hace que su código sea más fácil de mantener. En lugar de que el cálculo para actualizar los saldos y el suministro total se repita en cada instrucción if, es mucho mejor tener esto en una sola ubicación para que pueda ver claramente cuándo se modifican los valores. getMultiplier() también saldrá de la función (usando return) cuando se encuentre el valor correcto, mientras que su método continúa leyendo cada instrucción if hasta que llega al final de la función, lo que requiere mucho tiempo.

En lugar de llamar a las funciones getFName() y getLName() para cada declaración if, puede mantener estos valores en variables al comienzo de la función y luego simplemente leer desde la variable en lugar de múltiples llamadas a funciones para obtener el mismo resultado.

@ machine-uprising, muchas gracias por una solución muy inteligente. Tengo la idea y funciona.
@ machine-uprising, ¿puede echar un vistazo a mi otra pregunta aquí: ethereum.stackexchange.com/q/50507/38516