Cuando uso remix, hay un problema "Error en la estimación de gas, excepción de VM al procesar la transacción: código de operación no válido"

Cuando uso la función setDailyAssessmentInfo, aparece el error:

Error de estimación de gas con el siguiente mensaje (ver más abajo). Es probable que la ejecución de la transacción falle. ¿Quieres forzar el envío? Excepción de máquina virtual al procesar la transacción: código de operación no válido

Aquí está mi código:

pragma solidity ^0.4.21;

contract DailyAssessmentScoreContract {

   struct dailyAssessment{
        string dailyAssessmentId;
        string[] period;
        uint[] score;
    }
    dailyAssessment[] daily_assessment;


   function stringsEqual(string storage _a, string memory _b) internal returns (bool) {
        bytes storage a = bytes(_a);
        bytes memory b = bytes(_b);
        if (a.length != b.length)
            return false;
        // @todo unroll this loop
        for (uint i = 0; i < a.length; i ++)
            if (a[i] != b[i])
                return false;
        return true;
    }
    function stringToUint(string s) constant returns (uint result) {
        bytes memory b = bytes(s);
        uint i;
        result = 0;
        for (i = 0; i < b.length; i++) {
            uint c = uint(b[i]);
            if (c >= 48 && c <= 57) {
                result = result * 10 + (c - 48);
            }
        }
    }

   function setDailyAssessmentInfo(string _dailyAssessmentId, string _period, string _score) public {
       bool write = false;
       uint score = stringToUint(_score);
       for(uint i=0; i<=daily_assessment.length; i++)
       {                                                                                                                                                                                                                                                            
           if(stringsEqual(daily_assessment[i].dailyAssessmentId, _dailyAssessmentId))
           {
               daily_assessment[i].period.push(_period);
               daily_assessment[i].score.push(score);
               write = true;
           }
       }
       if(write==false)
        {
            daily_assessment[i].dailyAssessmentId=_dailyAssessmentId;
            daily_assessment[i].period.push(_period);
            daily_assessment[i].score.push(score);
        }
   }

   function getDailyAssessmentInfo(string _dailyAssessmentId) public constant returns (uint) {
       uint score;
       for(uint i=0;i<=daily_assessment.length;i++)
       {
           if(stringsEqual(daily_assessment[i].dailyAssessmentId, _dailyAssessmentId))
           {
               uint sum = 0;
               uint scoreLength = daily_assessment[i].score.length;
               for(uint j=0;j<=scoreLength;j++)
               {
                    sum = sum + daily_assessment[i].score[j];
               }
                score = sum / scoreLength;
           }
       }

       return (score);
   }   
}

Respuestas (1)

El problema radica en

for(uint i=0; i<=daily_assessment.length; i++)

Al iterar sobre la matriz, si crece demasiado, podría causar un error de falta de gas y, dado que es una matriz de longitud variable, está causando un error de estimación de gas.

Puede cambiar su diseño para usar mappingen lugar de matriz.

mapping(string => dailyAssessment) daily_assessment;

Utilice un mapen el que keyserá el daily assessment idy valueserá la estructura dailyAssessment.

function setDailyAssessmentInfo(string _dailyAssessmentId, string _period, string _score) public {
   bool write = false;
   uint score = stringToUint(_score);

   dailyAssessment storage assessment = daily_assesment[_dailyAssesmentId];
   if(assesment.dailyAssesmentId == _dailyAssesmentId)
       {
           assessment.period.push(_period);
           assessment.score.push(score);
           write = true;
       }

Con respecto a su comentario: "aquí hay otro problema que quiero usar" getDailyAssessmentInfo "para obtener la suma de la matriz de puntuación, un aumento de error me gusta por encima de la estimación de gas con error con el siguiente mensaje", el problema es exactamente el mismo. Parece que está calculando el promedio de las puntuaciones en esta getDailyAssessmentInfofunción. Se trata de utilizar un bucle sobre toda la puntuación y calcular el promedio. Entonces, la solución ideal sería calcular el promedio sin usar bucles.

Le sugiero que calcule el promedio al insertar los datos (en setDailyAssessmentInfo), guárdelo y simplemente obtenga ese puntaje promedio usando una función de obtención. Pero recuerde que el cálculo no debe usar loop. He usado una idea simple en el siguiente código para hacerlo.

struct dailyAssessment{
    string dailyAssessmentId;
    string[] period;
    uint[] score;
    uint averageScore;
}

function getDailyAssessmentInfo(string _id) returns (uint){
   return daily_assessment[_id].averageScore;
}

function setDailyAssessmentInfo(string _dailyAssessmentId, string _period, uint _score) public {
   uint average = daily_assessment[_dailyAssessmentId].averageScore;
   uint N = daily_assessment[_dailyAssessmentId].score.length;

   uint newAverage = (average * N + _score) / (N + 1);
   daily_assessment[_dailyAssessmentId].averageScore = newAverage;

Espero haber ayudado.

Gracias, funciona. Aquí hay otro problema que quiero usar "getDailyAssessmentInfo" para obtener la suma de la matriz de puntuación, un aumento de error me gusta arriba "Error en la estimación de gas con el siguiente mensaje"
función getDailyAssessmentInfo(string _dailyAssessmentId) public return (uint) { uint score; uint suma = 0; uint scoreLength = daily_assessment[_dailyAssessmentId].score.length; for(uint j=0;j<=longitudpuntuación;j++) { suma = suma + evaluación_diaria[_id_evaluacióndiaria].puntuación[j]; } puntaje = suma / scoreLength; retorno (puntuación); }
@Kyrie He actualizado la respuesta para reflejar su segundo problema. Si eso resolvió su problema, vote a favor y acepte la respuesta.