Cómo salir de (disminuir la longitud de) una matriz de memoria en Solidity

Tengo una función que obtiene una matriz de direcciones de otro contrato, elimina condicionalmente el msg.sender de la matriz y luego guarda la nueva matriz en ese contrato.

Debido a que la matriz backerList está en la memoria, no puedo hacerbackerList.length--;

Pero no puedo declarar backerList como una matriz de almacenamiento porque la matriz de memoria no se puede convertir en una de almacenamiento.

Estoy atascado aquí, ¿qué debo hacer?

 address[] memory backerList = syndicate.getBackerList();

 if(syndicate.individualTotalBacking(msg.sender) == 0){

        uint index;

        for(uint i=0; i<backerList.length; i++){
            if (backerList[i] == msg.sender){
                index = i;
            }

        //shifting array

            for(uint k=index; k<backerList.length-1; k++){
                backerList[k]=backerList[k+1];
            }

        }

        backerList.length--;
        syndicate.setBackerList(backerList);
    } else {}
¿Cuál es la firma de función de setBackerList?
setBackerList básicamente pasa backerList[ ] a otro contrato llamado sindicato. No creo que este sea el problema para ser honesto.
Lo que estoy tratando de preguntar es, ¿el tipo de parámetro es setBackerListun address[] memory?
buen punto, simplemente se declaró como esta función setBackerList (dirección [] newBackerList) public { ... }

Respuestas (2)

Aquí hay una manera de hacerlo usando backerList.length--;un ensamblado en línea:address[] memory backerList

assembly { mstore(backerList, sub(mload(backerList), 1)) }

Algunos puntos importantes para recordar:

  • Asegúrese de que este código de ensamblaje nunca se ejecute cuando backerList.length == 0(no permita que la longitud de la matriz se desborde)

  • No intente usar esto para aumentar el tamaño de una matriz (reemplazando subcon add)

  • Úselo solo en variables con un tipo como ...[] memory(por ejemplo, no lo use en a address[10] memoryo address)

Descargo de responsabilidad: por lo general, no se recomienda el uso de ensamblaje en línea. Úselo con precaución y bajo su propio riesgo :)

increíble y aterrador, ¿qué tan arriesgado es para mí usarlo? eso sería una buena solución para mí.
@RickChen Ciertamente recomiendo probarlo a fondo. Las principales preocupaciones son: No lo use en matrices vacías. Úselo solo en variables con un tipo como ...[] memory.
¿Hay alguna actualización en 2022 o sigue siendo la única forma de hacerlo?
¿Por qué no usar add para aumentar el tamaño de la matriz? Parece que lo he usado con éxito para 'empujar' a una matriz de memoria. Ha funcionado en las pruebas al menos. Gracias por este comentario, por cierto, esa línea de Yul para 'hacer estallar' (y aparentemente empujar) a las matrices de memoria ha sido de gran ayuda.
@RyanSea Puedes imaginar que la memoria EVM es un archivo uint8[2**64-1]. Cuando ejecuta, uint[] memory a = new uint()[10];el compilador asigna parte de esa matriz para almacenar a. El compilador puede decidir usar la memoria directamente después apara algún otro propósito ( b) porque asume legítimamente que ninguna característica del lenguaje puede crecer a. Si usa el ensamblaje en línea para ampliar a, sobrescribirá b. Si algún otro código escribe en b, sobrescribirá la parte extendida de a. Malos tiempos. Puede 'funcionar' porque no hay b, pero no funciona porque ha perdido todas las garantías de seguridad.

Sí, tiene razón, no puede reducir el tamaño de la matriz de memoria explícitamente, solo se aplica a la matriz de almacenamiento. Pero puede usar el operador de eliminación para borrar la memoria, lo que ahorrará gasolina.

Sin embargo, el tamaño de la matriz no cambiará, seguirá siendo el mismo. Debe crear una variable adicional para rastrear el tamaño de la matriz.