солидность: ошибка при вызове функции из другого контракта - PullRequest
0 голосов
/ 27 августа 2018

Столкнулся с очень непонятной для меня проблемой. Есть два простых контракта:

contract Test1 {
    int128 public val;    
    function getVal() view public returns(int128) {
        return val;
    }    
    function setVal( int128 _val ) public {
        val = _val;
    }
}

contract Test2 {
    address public the1;    
    function setTest1( address _adr ) public {
        the1 = _adr;
    }    
    function setVal( int128 _val ) public {
        Test1( the1 ).setVal( _val );
    }    
    function getVal() view public returns(int128) {
        return Test1( the1 ).getVal();
    }    
}

Значение поля Test1.val, которое вы можете изменить, вызывая функцию setVal в контракте Test1 и вызывая ту же функцию в Test2 (конечно, после установки адреса первого контракта во втором Test2.setTest1)).

В Remix и тестах (ganache) - все работает как положено. Но в частной сети (реализованной через Geth) у меня возникают проблемы: когда я вызываю Test2.setVal - значение изменяется; когда я вызываю Test2.getVal - не работает . Я звоню через web3j

test2.setVal( BigInteger.valueOf(30)).send();
result = test2.getVal().send(); // (1)

В точке (1) есть исключение:

ContractCallException: Emtpy value (0x) returned from contract.

Понятия не имею, что с этим не так. Механизм вызова функции из другого договора довольно прост. Но я не могу понять, что я делаю неправильно.

И я попытался вызвать функции контракта через geth-console. В этом случае ошибки нет, а просто Test2.getVal () возвращает 0.

Буду благодарен за любые идеи!

UPDATE. Это тест (я использовал тест Ферита)

const TEST_1 = artifacts.require('Test1.sol');
const TEST_2 = artifacts.require('Test2.sol'); 

contract('Ferit Test1', function (accounts) {

  let test1;
  let test2;

  beforeEach('setup contract for each test case', async () => {
    test1 = await TEST_1.at("…");
    test2 = await TEST_2.at("…");   
    })

  it('test1', async () => {
      await test1.setVal(333);
      let result = await test1.getVal();
      console.log( "-> test1.getVal=" + result );   
      assert(result.toNumber(), 333 );
  })

  it('test2', async () => {
      await test2.setVal(444);
      let result = await test2.getVal(); // (!!!) return 0
      console.log( "-> test2.getVal=" + result );   
      assert(result.toNumber(), 444);
  })
})

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

Я понял, что нашел причину проблемы.

Запрос @ Adam-Kipnis о происхождении файла дал мне идею попробовать запустить другую частную сеть с другими параметрами. Я взял их от здесь . И тест сработал!

К сожалению, я не помню, где я взял этот генезис для моей частной сети. Может быть проблема со значениями в homesteadBlock, eip155Block, eip158Block, byzantiumBlock . Я постараюсь развернуть мои оставшиеся контракты и протестировать их. А о результатах напишу.

Большое спасибо всем за участие! Ваши предложения были очень полезны для поиска решения!

0 голосов
/ 28 августа 2018

Задача 1 : .send(). должны быть удалены.

Проблема 2 : Вы уверены, что передали адрес экземпляра Теста 1 в Тест 2?

Проблема 3 : Вы должны вызывать их асинхронно. В вашем тестовом файле я не вижу ни async / await, ни каких-либо положений об обещании.

Изменения, которые я сделал:

  • Перенес контракты в соответствующие файлы (Test1.sol и Test2.sol).
  • Исправлена ​​проблема 1 в тестовом файле путем удаления .send()
  • Исправлена ​​проблема 2 в тестовом файле путем передачи адреса экземпляра Test1 в Test2
  • Исправлена ​​проблема 3 в тестовом файле с использованием синтаксиса async / await.

Исправлен файл теста следующим образом:

const TEST_1 = artifacts.require('Test1.sol');
const TEST_2 = artifacts.require('Test2.sol');


contract('Test1', function (accounts) {

  let test1;
  let test2;

  beforeEach('setup contract for each test case', async () => {
    test1 = await TEST_1.new({from: accounts[0]});
    test2 = await TEST_2.new({from: accounts[0]});
    await test2.setTest1(test1.address); // Problem 2
  })

  it('should let owner to send funds', async () => {
      await test2.setVal(30); // Problem 1 and 3
      result = await test2.getVal(); // Problem 1 and 3
      assert(result.toNumber(), 30);
  })
})

Добро пожаловать в переполнение стека!

...