solidity: error when call function from another contract

solidity: error when call function from another contract



Faced a very not clear problem for me. There are two simple contracts:


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();




The value of field Test1.val you can change as calling function setVal in Test1 contract and calling same function in Test2 (Of course after setting the address of the first contract in the second Test2.setTest1)).



In the Remix and tests (ganache) – everything works as expected. But on a Private Network (implemented via Geth) I have trouble: when I call Test2.setVal – the value is changed; when I call Test2.getVal – does not work. I make calls via web3j


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



In the point (1) there is an exception:


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



I have no idea what wrong with this. The mechanism of calling function from another contract is quite simple. But I can’t understand what I’m doing wrong.



And I tried to call contract’s functions throw geth-console. In this case there is no error, but simply Test2.getVal () returns 0.



I will be grateful for any ideas!



UPDATE. This is test (I used @Ferit's test)


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);
)
)





The problem doesn’t appear to be in your contract. Do you get a valid TransactionReceipt returned from setVal().send()? Are you using the generated contract proxy?
– Adam Kipnis
Aug 28 at 5:01


TransactionReceipt


setVal().send()





Thanks for your reply. Yes, setVal().send() returned a valid TransactionReceipt. TransactionReceipt r = test2.setVal( BigInteger.valueOf(30)).send(); System.out.println( r.getBlockHash() ); result = test1.getVal().send(); System.out.println( "1) " + result ); result = test2.getVal().send(); // ERROR! System.out.println( "2) " + result ); Do you mean a proxy-java-class? Yes, I use web3j to generate it. For compilation I use truffle.
– vasiliy
Aug 28 at 7:42



setVal().send()


TransactionReceipt


TransactionReceipt r = test2.setVal( BigInteger.valueOf(30)).send();


System.out.println( r.getBlockHash() );


result = test1.getVal().send();


System.out.println( "1) " + result );


result = test2.getVal().send(); // ERROR!


System.out.println( "2) " + result );


web3j


truffle





Please add your genesis.json to the post and I’ll try deploying it when I have some time later tonight.
– Adam Kipnis
Aug 28 at 13:42





Thanks for your attention. Here is the genesis file: genesis_test.json
– vasiliy
Aug 29 at 13:25




2 Answers
2



Problem 1: .send(). should be removed.


.send()



Problem 2: Are you sure that you passed the address of Test 1 instance to Test 2?



Problem 3: You need to call them asynchronously. In your test file, I don't see any async/await or any promise clauses.



Changes I made:


.send()



Fixed test file as follows:


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);
)
)



Welcome to Stack Overflow!





Thanks for your replay. Problem 1: .send() this is java-code. I mean I use java library web3j. And this construction is used for asynchronous call. Problem 2: Yes, I checked that I passed the address of Test1 instance to Test2. This code I wrote into the deploy part. Problem 3: Your test works correctly in ganache-cli. And I took your code for making js-test. I changed it to replace new by particular addresses. And unfortunately this is the same error.
– vasiliy
Aug 29 at 13:55


.send()


ganache-cli


new





Did you migrate your contacts to your private network? @vasiliy
– ferit
Aug 29 at 14:00






Yes. I try it on my private network (after deployed contracts). truffle test --network priv4 where priv4 is name of my private network.
– vasiliy
Aug 29 at 15:01


truffle test --network priv4





Problem is about your migration/network almost certainly. Triple check your configurations.
– ferit
Aug 29 at 15:10






Did you fund your account? Ganache does it automatically for you. I think that's why on Ganache it works. @vasiliy
– ferit
Aug 30 at 5:35



I thing I found the cause for the problem.



The request from @Adam-Kipnis’s about the file genesis gave me the idea to try to start another private network with different parameters.
I took them from here.
And the test has worked!



Unfortunately I don’t remember where I took that genesis file for my private network.
There may be a problem with the values in homesteadBlock, eip155Block, eip158Block, byzantiumBlock.
I will try to deploy my remaining contracts and test them. And I will write about results.



Great thanks you all for your participation! Your offers were very useful for finding a solution!





Sorry for the delay. I was only now able to look at the genesis file you added. The version you posted is definitely a problem. I believe those initial address fields you were attempting to use in alloc are reserved for precompiled contracts (see ethereum.stackexchange.com/questions/440/… or the Ethereum white paper). Also, take a look at this answer for an explanation of the genesis.json fields: ethereum.stackexchange.com/questions/2376/…
– Adam Kipnis
Aug 30 at 23:59


alloc



Required, but never shown



Required, but never shown






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)