Made a little example to show different elementary modes.
There is a caller contract, a "constant" contract and a "writer" contract. You can invoke the caller contract from externally owned account with either sendTransaction()
or .call()
and this will change things (create a transaction or just interrogate results).
There's a callConstant()
function that talks to a contract function is marked constant and can't alter the chain, but it does return a result.
There's also a callWriter()
function that calls a function that can update the chain, and also returns a value. This inter-contract communication is a "message". It doesn't create a new transaction and it's resolved more or less immediately.
I say can update the chain because the client has the option of "calling" either function with the passive call()
option which does not send a state-changing transaction to the chain. Therefore, the "dry-run" mode can have no lasting impact.
pragma solidity ^0.4.6;
contract Caller {
Constant public c;
Writer public w;
event LogReturnedValue(uint valueReceived);
function Caller() {
c = new Constant();
w = new Writer();
}
// can send transactions to these two functions to call function in another contract with read-only/read-write
function callConstant()
public
returns(uint x)
{
uint gotVal = c.returnValue();
LogReturnedValue(gotVal);
return gotVal;
}
function callWriter()
public
returns(uint y)
{
uint gotVal = w.returnValue();
LogReturnedValue(gotVal);
return gotVal;
}
}
contract Constant {
function returnValue()
public
constant // <-- indicates read-only function cannot change the chain
returns(uint X)
{
return 1;
}
uint public counter;
function returnValue()
public
returns(uint Y)
{
counter++;
return 2;
}
}
Main take-away: There is a matrix of function design and invocation methods that takes some getting used to.
Hope it helps.