¿Cuáles son los pasos para compilar e implementar una biblioteca en Solidity?

Tengo varias piezas de documentación sobre bibliotecas, pero aún no puedo inferir qué pasos se necesitan para compilar e implementar una biblioteca y luego un contrato que la use. El comportamiento de la biblioteca dentro de la solidez es bastante claro, pero la compilación y la vinculación no son obvias para mí.

Recursos que he consultado:

Aquí hay un ejemplo de contrato y biblioteca que me gustaría que funcione:

MetaCoin.sol:

import "TestLib.sol";

contract MetaCoin {
  TestLib.Data data;
  address public owner;

  function MetaCoin() {
    owner = msg.sender;
    TestLib.Set(data, 2);
  }

  function GetData() constant returns(uint) {
    return TestLib.Get(data);
  }
}

TestLib.sol:

library TestLib {
  struct Data {
    uint n;
  }

  function Set(Data storage self, uint a) {
    self.n = a;
  }

  function Get(Data storage self) returns(uint) {
    return self.n;
  }
}

¡Gracias por tu ayuda!

Respuestas (2)

Primero, guardemos ambos archivos en el mismo directorio y ejecutemos solc --optimize --bin MetaCoin.sol. La salida es:

======= MetaCoin =======
Binary: 
606060405260018054600160a060020a031916331790557f9447fa1700000000000000000000000000000000000000000000000000000000606090815260006064819052600260845273__TestLib_______________________________91639447fa179160a4916044818660325a03f41560025750505060c0806100846000396000f3606060405260e060020a600035046376b8e528811460245780638da5cb5b14608f575b005b60ad7ffc22471a000000000000000000000000000000000000000000000000000000006060908152600060648190529073__TestLib_______________________________9063fc22471a906084906020906024818660325a03f41560025750506040515191505090565b60b660015473ffffffffffffffffffffffffffffffffffffffff1681565b50604051602090f35b6060908152602090f3

======= TestLib =======
Binary: 
606060405260458060106000396000f3650302e3c5418550606060405260e060020a60003504639447fa178114602e578063fc22471a146037575b6007565b60243560043555005b600435546060908152602090f3

Si observa detenidamente (desplácese hacia la derecha) el código de bytes de MetaCoin (también conocido como binario), encontrará un par de instancias de __TestLib_______________________________. Estos son marcadores de posición donde se vinculará la dirección eventual de TestLib. Esto significa que para implementar MetaCoin, primero necesitaremos implementar TestLib y luego usar solc para vincular la dirección de TestLib con el código de bytes de MetaCoin.

Podemos implementar TestLib como lo haríamos con cualquier otro contrato. Consulte ¿Cómo implementar un contrato en un nodo en ejecución local usando el navegador solidity? para un ejemplo. Una vez que se implemente, deberá copiar la dirección de la biblioteca TestLib implementada, que se requiere para vincular TestLib al binario MetaCoin. Para hacer la vinculación, use el TestLib desplegado <address>y ejecute:

solc --optimize --bin MetaCoin.sol | solc --link --libraries TestLib:<address>

La salida se verá casi igual que antes, pero ahora los __TestLib_______________________________marcadores de posición se habrán reemplazado con el <address>valor. Este código de bytes ahora se puede usar para implementar MetaCoin en la misma red Ethereum en la que implementó TestLib.

Uso 3 bibliotecas diferentes en mi contrato, pero nunca obtengo el ___libraryName____________resultado, no importa si las uso --optimizeo no. Mi versión de solc es: 0.4.24+commit.e67f0147.Linux.g++

Para agregar, es posible vincular manualmente los contratos (si desea implementar la biblioteca y el contrato juntos). La forma más sencilla es reemplazar todas las apariciones de los marcadores de posición con la dirección.

Un ejemplo, tomado de mi propio código (modificado):

var linkedMetaCoinCode = metaCoinBytecode.replace(
  /_+TestLib_+/g,
  testLib.address.replace("0x", "")
);

testLib sería un contrato web3 normal, implementado anteriormente, mientras que metaCoinBytecode sería el código de bytes de MetaCoin producido por solc. (En mi propio código, uso --combined-json de solc para obtener una forma agradable para JS). Tenga en cuenta que tendrá que eliminar el prefijo '0x' o el código vinculado no será válido.

método interesante, esto se ve bien