A function without a pure
modifier, a view
modifier or a constant
modifier (which is equivalent to a view
modifier) is assumed to be changing the contents of the block-chain.
This "change" is refereed to as transaction, and the value returned to the off-chain caller (e.g., web3
) is a hash which encrypts the transaction.
The actual value that you return from the function can be used only inside the block-chain (i.e., by any other function which calls your function).
If you want this value to be accessible on the off-chain side, then you need to generate an event
(inside the Solidity function) which contains it.
Then, on the off-chain side, you will need to decode the returned value (i.e., the transaction hash) in order to retrieve that value.
On-Chain Example:
contract MyContract {
event MyEvent(address indexed sender, uint256 amount);
function myFunction(uint256 a, uint256 b, uint256 c) external returns (uint256) {
uint256 x = a * b + c;
MyEvent(msg.sender, x);
return x;
}
}
Off-Chain Example:
let PARAMS = [ // This should reflect MyEvent
{name: "sender", size: 160, indexed: true },
{name: "amount", size: 256, indexed: false},
];
function decode(data) {
let transaction = {};
let index = "0x".length;
for (let i = 0; i < PARAMS.length; i++) {
if (!PARAMS[i].indexed) {
let name = PARAMS[i].name;
let size = Math.floor(PARAMS[i].size / 4);
transaction[name] = web3.toBigNumber("0x" + data.substr(index, size));
index += size;
}
}
return transaction;
}
async function myFunction(myContract) {
let hash = await myContract.myFunction(5, 6, 7);
let transaction = decode(hash.receipt.logs[0].data);
return transaction.amount; // should be 5 * 6 + 7
}
Please note that by hash.receipt.logs[0]
, we are accessing the first event which occurred as a result of invoking myContract.myFunction
. In other words, the index (in this case, 0
) indicates the number of the desired event by chronological order.