VM-Ausnahme: Vertrag innerhalb eines Vertrages

Ich folge diesem Beispiel , um mit dem Vertrag innerhalb eines Vertrags zu experimentieren (unter Verwendung von testrpc).

contract Product {
    bytes32 public Name;

    function Product (bytes32 _Name) {
        Name = _Name;
    }
}

contract ProductFactory {

    bytes32[] public productNames;
    address[] public productAddresses;

    function addProduct (bytes32 _productName) {
        address newProduct = new Product(_productName);
        productAddresses.push(newProduct);
    }

    function getName (uint i) {
    Product prod = Product(productAddresses[i]);

    productNames[i] = prod.Name();
  }
}

Mein Dateiname ist Product.sol und die Deloy-Datei in Truffle ist:

var Product = artifacts.require("./Product.sol");
var ProductFactory = artifacts.require('ProductFactory');


module.exports = function(deployer) {
  // deployer.deploy(supplyChain);
  deployer.deploy(Product);
  deployer.deploy(ProductFactory);
};

Bei der Bereitstellung funktionieren sowohl ProductFactory als auch Product gut, wie die Erstellung eines neuen Produkts mit addProduct zeigt. Bei getName wird jedoch der Fehler: VM Exception zurückgegeben.

truffle(development)> ProductFactory.deployed().then(function(instance){PF=ProductFactory.at(instance.address)})

truffle(development)> PF.addProduct('abcd')
{ tx: '0xe304f9194fb9b06ae5f0a3664f64255e74d88de099cce0cd38092030b5d48d7f',
  receipt:
   { transactionHash: '0xe304f9194fb9b06ae5f0a3664f64255e74d88de099cce0cd38092030b5d48d7f',
     transactionIndex: 0,
     blockHash: '0x09d3e5547b1d4cd9ef40d05b5b15561a45b9f62f55410d03c175886dd1c591eb',
     blockNumber: 122,
     gasUsed: 122275,
     cumulativeGasUsed: 122275,
     contractAddress: null,
     logs: [] },
  logs: [] }

truffle(development)> PF.getName(0)
Error: VM Exception while processing transaction: invalid opcode
    at Object.InvalidResponse (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:37047:16)
...

EDIT1: Wenn ich Folgendes versuche,

truffle(development)> PF.productAddresses(0)
'0x4b01bd4691c306c59e8985bb6bd5bcc88abf1e81'
truffle(development)> Product.at('0x4b01bd4691c306c59e8985bb6bd5bcc88abf1e81').Name()
'0x6162686900000000000000000000000000000000000000000000000000000000'

verständlicherweise funktioniert es. PF.productAddresses(0)ist ein Objekt , wie ich gesammelt habe, und wenn ich Product.at(PF.productAddresses(0))es verwende, schlägt es genauso fehl wie getName. Wenn Sie jedoch wie gerade gezeigt direkt die Adresszeichenfolge verwenden , funktioniert es. Wie geht man mit diesem Problem um?

EDIT1 über:

Ich bin ein Neuling. Wenn mir jemand sagen könnte, was ich falsch mache. Ich denke, es hat mit asynchronem Anruf zu tun, aber ich bin mir nicht sicher. Ich habe mehrere Varianten und auch Remix ausprobiert, aber es funktioniert einfach nicht.

Antworten (1)

Ich glaube nicht, dass es darum geht, mehrere Verträge zu haben, Sie haben ein Problem in der getName()Funktion mit dieser Anweisung:

    productNames[i] = prod.Name();

Sie dürfen keinen Index über das Ende eines Arrays mit dynamischer Größe hinaus zuweisen. Genauer gesagt, wenn Sie zum ersten Mal aufrufen getName(), hat das productNamesArray eine Größe von Null, sodass Sie es keinem seiner Elemente zuweisen können: Es gibt keine.

Sie sollten besser productNames.push(_productName)innerhalb Ihrer addProduct()Funktion verwenden und getName()vollständig entfernen.

Alternativ können Sie anstelle eines Arrays eine Zuordnung mit ials Schlüssel verwenden. Das heißt, ändern Sie Ihre Deklaration productNameswie folgt; der Rest des Codes ist unverändert:

mapping (uint => bytes32) productNames;

Das funktioniert, aber es ist eine seltsame Art, es zu codieren (imho).

Siehe auch diese Fragen und Antworten.

Perfekt, anstatt getName ganz zu entfernen, habe ich versucht, die Array-Größe um 1 (in addName) zu erhöhen und zu prüfen, ob es funktioniert - wie Sie die Referenz dafür angegeben haben, gibt es zwei Möglichkeiten, die Array-Größe zu erhöhen, zu pushen oder die Länge zu erhöhen. Beide Ansätze funktionieren! Die Mapping-Idee ist interessant, muss ich sagen, obwohl ich mit konventionellen weitermachen werde. Danke noch einmal!