¿Puedo definir variables globales en el contrato de la biblioteca?

Quiero usar algunas variables en múltiples funciones en mi contrato de biblioteca. ¿Hay alguna forma de hacer eso? Recibí el siguiente código de error para mi código de biblioteca.

library myArithmetic {
    bytes1[10] mData;

    function doSomeMath(bytes1[10] _input) public returns (bytes1[10]) {
        for(uint8 i=0 ; i<10 ; i++){
            mData[i] = _input[i];
        }
        //do some my math..here..
    }
}

Tengo un error, como que TypeError: Library cannot have non-constant state variablesno quiero hacer cada una de mis funciones con varios parámetros de entrada y retorno, ya otras funciones... etc. ¿¿Es posible hacer eso??

Sé que en el contrato normal, los mData serán variables de almacenamiento. Pero la biblioteca no permite tener variables de estado. Entonces, ¿no puedo definirlo de esta manera?

Piense en una biblioteca física, puede registrar y retirar libros, pero no puede editar libros. Lo mismo se aplica a la mayoría de las implementaciones programáticas de una "Biblioteca".

Respuestas (2)

Un enfoque para resolver esto es definir una estructura dentro de su biblioteca y pasar esa estructura como el primer parámetro. Las funciones en su biblioteca podrán modificar la estructura.

pragma solidity ^0.4.0;

library Arithmetic {
    struct Data {
        bytes1[10] mData;
    }

    function doSomeMath(Data s, bytes1 _input, uint8 _idx) internal pure returns (bytes1) {
        s.mData[_idx] = _input;
        return _input;
    }
}

En su contrato, crea una instancia de esa estructura y la pasa a las funciones de la biblioteca. Puede usar el azúcar de sintaxis "usando" para tener un código de mejor apariencia.

contract Ballot {
    // Reserver storage for library data
    Arithmetic.Data d;

    // When referencing Data allow shortcut to Arithmetic functions
    using Arithmetic for Arithmetic.Data;

    function bar(bytes1 a) public view returns (uint8) {
        // The following is equivalente to 
        // bytes1 b = Arithmetic.doSomeMath(d, a, 3);
        bytes1 b = d.doSomeMath(a, 3);
        return uint8(b);
    }
}

Las bibliotecas no tienen almacenamiento. Sus métodos se invocan con el delegatecallcódigo de operación, lo que significa que se ejecutan en el contexto de la persona que llama. En una biblioteca, thisapunta al contrato de llamada.

Si desea solucionar esto, cree un contrato de almacenamiento con los globales y páselo a cada método de biblioteca en el que desee usar los globales.