Я следую этому примеру , чтобы поэкспериментировать с контрактом внутри контракта (используя 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();
}
}
Мое имя файла — Product.sol, а файл deloy в трюфеле — это:
var Product = artifacts.require("./Product.sol");
var ProductFactory = artifacts.require('ProductFactory');
module.exports = function(deployer) {
// deployer.deploy(supplyChain);
deployer.deploy(Product);
deployer.deploy(ProductFactory);
};
При развертывании и ProductFactory, и Product работают хорошо, о чем свидетельствует создание нового продукта с помощью addProduct. Однако при выполнении getName возвращается ошибка: исключение VM.
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: когда я пытаюсь сделать следующее,
truffle(development)> PF.productAddresses(0)
'0x4b01bd4691c306c59e8985bb6bd5bcc88abf1e81'
truffle(development)> Product.at('0x4b01bd4691c306c59e8985bb6bd5bcc88abf1e81').Name()
'0x6162686900000000000000000000000000000000000000000000000000000000'
понятно что работает. PF.productAddresses(0)
- это объект , как я понял, и когда я его использую, Product.at(PF.productAddresses(0))
он терпит неудачу так же, как getName
. Однако при прямом использовании адресной строки , как только что показано, это работает. Как справиться с этой проблемой?
РЕДАКТИРОВАТЬ1 над:
Я новичок. Если бы кто-то мог сообщить мне, что я могу делать неправильно. Я думаю, что это связано с асинхронным вызовом, но я не уверен. Я пробовал несколько вариантов, а также Remix, но это просто не работает.
Я не думаю, что речь идет о наличии нескольких контрактов, у вас есть проблема в функции getName()
с этим оператором:
productNames[i] = prod.Name();
Вам не разрешено назначать индекс за пределами конца массива с динамическим размером. В частности, при первом вызове getName()
массив productNames
имеет нулевой размер, поэтому вы не можете присвоить значение одному из его элементов: их нет.
Вам лучше использовать productNames.push(_productName)
в своей addProduct()
функции и getName()
полностью удалить.
В качестве альтернативы вы можете использовать сопоставление вместо массива в i
качестве ключа. То есть измените объявление productNames
следующим образом: остальной код не меняется:
mapping (uint => bytes32) productNames;
Это работает, но это странный способ кодирования (имхо).
См. также эти вопросы и ответы.
Марганец