¿Cómo puede la biblioteca cambiar de estado?

Tengo casos muy Interesantes sobre Bibliotecas.

CASO 1:

Leí lo siguiente en los documentos oficiales de solidez:

Las funciones de biblioteca solo se pueden llamar directamente (es decir, sin el uso de DELEGATECALL) si no modifican el estado (es decir, si son funciones de vista o puras), porque se supone que las bibliotecas no tienen estado

Estoy seguro de que quieren llamar a las bibliotecas con el uso de .callen la dirección y dicen que esto solo sería posible si la función de las bibliotecas fuera pure/view. Permítanme repetir lo a), b), c)que no entiendo.

a) En la oración copiada, Dice: if they do not modify the state. No estoy seguro de cómo la biblioteca cambia de estado en absoluto. no tiene uno propio y todo lo que puede hacer es cambiar el valor de la variable pasada.

b) Intenté usarlo con addr.call, pero no especifiqué funciones como pure/viewy todavía me deja hacer esto. Es interesante por qué me dejó, ya que en los documentos dice que debería revertirse.

c) ¿ Por qué querría llamar a las bibliotecas con el .call? Esto simplemente anula todo el propósito de las bibliotecas.

**D) ** Parece que si uso internalfunciones en bibliotecas, el código de la biblioteca termina en la versión compilada del contrato. ¿Alguna razón por la que esto es bueno? si es así, habría usado otro contrato en lugar de la biblioteca.

Caso 2:

En los documentos, es realmente un mal ejemplo cómo pasa el tipo de referencia. Digamos que tengo una biblioteca:

// Let's say this was written by third-party and it's put on github.

library libraryContract {
   
   function libraryTest(){

   }

}

// I can import the above here.

// import "libraryContract.sol";

contract myContract {
   
   function contractTest(){
      // I call it. This will work. Now, let's say in this contract, I
      // have a variable called `uint x = 0;`. and what libraryContract 
      // should be doing is change the value of the passed argument. 
      // If I pass `x` here directly, and change the argument in 
      //`libraryTest`, It still doesn't work since it's not passed by 
      //reference or something. Another case is What If I want my library 
      //to be changing the struct's properties, but library doesn't see 
      //the definiton of struct. 
      libraryContract.test(); 
   }

}

Una vez implementadas, las bibliotecas son como cualquier otro contrato. AFAIK no hay nada que impida que cualquier usuario llame a las funciones. Las funciones internas están destinadas a ser llamadas desde dentro del mismo contrato, lo que hace que se puedan llamar desde otro contrato anulando el propósito de ser internas. Las bibliotecas son buenas para organizar el código, pero tienen algunas limitaciones. Si los documentos de solidez no están claros, sugeriría preguntar a los desarrolladores de solidez.

Respuestas (3)

a) En la oración copiada, Dice: si no modifican el estado. No estoy seguro de cómo la biblioteca cambia de estado en absoluto. no tiene uno propio y todo lo que puede hacer es cambiar el valor de la variable pasada.

Una biblioteca puede cambiar el estado de un contrato de llamada a través de una llamada delegada. En este caso, la función se ejecuta como si estuviera escrita directamente en el contrato de llamada. Esto significa que, en teoría, puede modificar cualquier parte del estado del contrato de llamada, siempre que las variables correspondientes hayan sido declaradas en la biblioteca (pero no inicializadas, ya que la biblioteca no tiene estado propio). Lo que dicen los documentos es que si intenta llamar a dicha función directamente, fallará, ya que no tiene la intención de cambiar/modificar su propio almacenamiento (porque no existe tal almacenamiento), sino el almacenamiento correspondiente en un contrato de llamada .

b) I tried using it with addr.call, but I didn't specify functions as pure/view and it still let me do this. It's interesting why it let me since in the docs, it says it should revert.

Marcar una función como pure/ viewno es obligatorio, por lo que mientras la función no intente modificar el estado, la transacción no se revertirá.

c) Why would I ever want to call libraries with the .call ? This just defeats the whole purpose of libraries.

Se puede usar una biblioteca para modificar el estado de un contrato de llamada (a través de delegatecall), pero también se puede comportar como una clase con métodos estáticos. Por ejemplo, supongamos que siempre necesita algunas constantes o métodos familiares en sus contratos ( uint pi, uint days_in_year function n_squared(uint n), etc.). Puede factorizarlos en una biblioteca para evitar tener que incluirlos en cada contrato que escriba. Luego, solo se almacenan una vez en la cadena de bloques, y los demás calllos contratan solo cuando los necesitan.

Gracias Simón. Tengo un par de puntos aquí también.
1). Tu dices: not initialised. Significa que lo único que puedo poner en la biblioteca es struct, porque si pongo ints o array o cualquier otra cosa, significa que se inicializan de manera predeterminada. 3). Parece ser que el ejemplo que trajo n_squaredtambién se puede hacer simplemente cargando un contrato en lugar de una biblioteca y luego usando sus funciones. Además, podría llamar al método del contrato con el mío propio delegatecall. Entonces, todavía no veo el panorama general, tal vez

Parece que si uso funciones internas en las bibliotecas, el código de la biblioteca termina en la versión compilada del contrato.

Una aplicación para esto es el código reutilizable. Por ejemplo, SafeMath utiliza funciones internas. De esta manera, cuando haces a.add(b), hace el cálculo sin usar un delegatecall. Si delegatecallse usara a, los cálculos terminarían siendo bastante costosos.

Sin embargo, en el futuro, este uso de bibliotecas probablemente será menos frecuente debido a las funciones gratuitas.


Un ejemplo simple de la "cuestión estatal" sería:

library L {
    function f() external {
        assembly {
            sstore(0, 1)
        }
    }
}

Entonces, si no hubiera protección de llamadas, estaría escribiendo en el estado de la biblioteca.

Las bibliotecas no tienen estado, solo pueden almacenar valores 'constantes'. Entonces, incluso si se usa la llamada delegada en la biblioteca, no podrá cambiar el estado del contrato de la persona que llama.

Por ejemplo, cuando traté de crear la biblioteca a continuación, da este error:

de solidity: TypeError: la biblioteca no puede tener variables de estado no constantes

library LibraryContract {

  uint storedTime;  

  function setTime(uint _time) public {
    storedTime = _time;
  }
}

Actualización: resulta que esta restricción se elimina cuando se usa de la forma en que se menciona en este artículo: https://dev.to/mudgen/solidity-libraries-can-t-have-state-variables-oh-yes-they-can-3ke9