[SOLVED] Is this a bug in Sophia remote call ? I think i found one!


`contract A =
record state = {value : int,
balances : map(address, int)}

function init() = {
value = 0,
balances = {[Call.caller] = 0}}

function main() =
state.balances[Call.caller] // bug ?

function set(who : address) =
put(state{balances[who] = 0})

contract A =
function main : () => bool

contract B =
record state = {a : A}

function init(_a : A) = {
a = _a }

function main() =

Above has two contract, when from contract B call contract A, it will got a error “Error: Invocation failed: _b3V0X29mX2dhc0caXYY=”

It seems this function can’t work in remote call.
function main() =

But, when call the A.set(B) function first, then call B.main, it will work well .:slightly_smiling_face:


TL;DR; - No it is not a bug it is the documented behavior.

First, to avoid confusion, there is no such thing as contract A and contract B on chain. There will be instances (can be zero, one, or many) of a given contract. For the sake of this discussion/example suppose we have one instance A' of contract A, and one instance B' of contract B, where A' is passed to the init function of B'. Also we have an account making the calls (in fact contract call transactions), lets name this account X.

This means that the init function of A' will set the balance of account X to 0 in it state.balances map.

So now what happens when you’re calling B'.main()? You will make a remote call to A' with Call.caller = B' it will look for B' in the state.balances map and since it is not there it will fail with an out_of_gas error. (BTW _b3V0X29mX2dhc0caXYY= is the Base64 encoding of “out of gas”). If you first set the account balance to 0 by calling A'.set(B') the result is different.

From the Sophia documentation: Looking up a non-existing key in a map results in contract execution failing. A default value to return for non-existing keys can be provided using the syntax m[k = default] .

I.e. if you want to return a 0 balance for non-existing accounts you could change state.balances[Call.caller] into state.balances[Call.caller = 0].

ProTip: using code formatting will make the post more readable.


Aha, Thank you very much! :+1: