Skip to content
This repository has been archived by the owner on Dec 15, 2023. It is now read-only.

Return Value Strangenesses #127

Closed
antazoey opened this issue Jun 14, 2022 · 11 comments
Closed

Return Value Strangenesses #127

antazoey opened this issue Jun 14, 2022 · 11 comments

Comments

@antazoey
Copy link

antazoey commented Jun 14, 2022

I am noticing some odd behaviors with return values as of recently where the length of return arguments is included. Here are the scenarios I have tried:

@external
func get_array{
        syscall_ptr : felt*, pedersen_ptr : HashBuiltin*,
        range_check_ptr}() -> (arr_len: felt, arr: felt*):
    const ARRAY_SIZE = 3
    let (ptr) = alloc()
    assert [ptr] = 1
    assert [ptr + 1] = 2
    assert [ptr + 2] = 3
    let (current_count) = array_get_counter.read()
    array_get_counter.write(current_count + 1)
    return (ARRAY_SIZE, ptr)
end

@view
func view_array{
        syscall_ptr : felt*, pedersen_ptr : HashBuiltin*,
        range_check_ptr}() -> (arr_len: felt, arr: felt*):
    const ARRAY_SIZE = 3
    let (ptr) = alloc()
    assert [ptr] = 1
    assert [ptr + 1] = 2
    assert [ptr + 2] = 3
    return (ARRAY_SIZE, ptr)
end
method client result
@external normal [3, 1, 2, 3]
@external account [4, 3, 1, 2, 3]
@view normal [3, 1, 2, 3]
@badurinantun
Copy link
Contributor

Isn't this because account can have multiple calls?

@0xSidius
Copy link

For further reference:

unknown (1)

@FabijanC
Copy link
Collaborator

@unparalleled-js How does this differ from responses you get from alpha-goerli?

@ca11ab1e

This comment was marked as outdated.

@FabijanC
Copy link
Collaborator

@unparalleled-js have you been able to compare with output from alpha-goerli?

@ca11ab1e
Copy link
Contributor

ca11ab1e commented Jun 18, 2022

I finally got a comparison with alpha-goerli. Returned data are identical to the devnet (tx):

$ starknet get_transaction_receipt --hash '0x552334e3dfb31d87d62eb9c1483551c30f03c91e5aa7af376df030646c21123' --network 'alpha-goerli' | jq '.events[0].data'
[
  "0x552334e3dfb31d87d62eb9c1483551c30f03c91e5aa7af376df030646c21123",
  "0x4",
  "0x3",
  "0x1",
  "0x2",
  "0x3"
]

@ca11ab1e
Copy link
Contributor

I adapted the test contract to generate an array with 10 elements.
Result: [11 10 1 2 3 4 5 6 7 8 9 0]

tx details:

$ starknet get_transaction_receipt --hash 0x67411b96d1b4cca009c7ae16cad46be17aa21000de8c4431b6f5c227f6e7aae --network alpha-goerli | jq '.events[0].data'
[
  "0x67411b96d1b4cca009c7ae16cad46be17aa21000de8c4431b6f5c227f6e7aae",
  "0xb",
  "0xa",
  "0x1",
  "0x2",
  "0x3",
  "0x4",
  "0x5",
  "0x6",
  "0x7",
  "0x8",
  "0x9",
  "0x0"
]

@ca11ab1e
Copy link
Contributor

In a diff of the same contract compiled with Cairo 0.8.2.1, and 0.9.0, I can see such changes:

             "__wrappers__.get_array.Return": {
-                "full_name": "__wrappers__.get_array.Return",
-                "members": {
-                    "pedersen_ptr": {
-                        "cairo_type": "starkware.cairo.common.cairo_builtins.HashBuiltin*",
-                        "offset": 1
-                    },
-                    "range_check_ptr": {
-                        "cairo_type": "felt",
-                        "offset": 2
-                    },
-                    "retdata": {
-                        "cairo_type": "felt*",
-                        "offset": 4
-                    },
-                    "size": {
-                        "cairo_type": "felt",
-                        "offset": 3
-                    },
-                    "syscall_ptr": {
-                        "cairo_type": "felt*",
-                        "offset": 0
-                    }
-                },
-                "size": 5,
-                "type": "struct"
+                "cairo_type": "(syscall_ptr : felt*, pedersen_ptr : starkware.cairo.common.cairo_builtins.HashBuiltin*, range_check_ptr : felt, size : felt, retdata : felt*)",
+                "type": "type_definition"
             },
-                    "ret_struct": {
-                        "cairo_type": "__main__.get_array.Return",
+                    "ret_value": {
+                        "cairo_type": "(arr_len : felt, arr : felt*)",
             "__wrappers__.get_array_encode_return.Return": {
-                "full_name": "__wrappers__.get_array_encode_return.Return",
-                "members": {
-                    "data": {
-                        "cairo_type": "felt*",
-                        "offset": 2
-                    },
-                    "data_len": {
-                        "cairo_type": "felt",
-                        "offset": 1
-                    },
-                    "range_check_ptr": {
-                        "cairo_type": "felt",
-                        "offset": 0
-                    }
-                },
-                "size": 3,
-                "type": "struct"
+                "cairo_type": "(range_check_ptr : felt, data_len : felt, data : felt*)",
+                "type": "type_definition"
             },

The return type changes from struct to type_definition. Not sure it is the actual problem though, just taking notes for everyone.

@ca11ab1e
Copy link
Contributor

ca11ab1e commented Jun 18, 2022

FTR I tested a modified version of the contract that does not touch to the storage var, just to isolate more the behavior. It changes nothing, results are the same.

Here is the epured contract:

%lang starknet

from starkware.cairo.common.alloc import alloc


@external
func get_array() -> (arr_len : felt, arr : felt*):
    alloc_locals

    let (local arr : felt*) = alloc()
    assert arr[0] = 1
    assert arr[1] = 2
    assert arr[2] = 3

    return (arr_len=3, arr=arr)
end

@ca11ab1e
Copy link
Contributor

I was wondering if the return type changes when returning a simple integer: it still return an additional value: [1 42] (tx)

Contract (you can play with it here):

%lang starknet

from starkware.cairo.common.alloc import alloc


@external
func get_array() -> (arr_len : felt, arr : felt*):
    alloc_locals

    let (local arr : felt*) = alloc()
    assert arr[0] = 1
    assert arr[1] = 2
    assert arr[2] = 3

    return (arr_len=3, arr=arr)
end

@external
func get_int() -> (res : felt):
    return (res=42)
end

@FabijanC
Copy link
Collaborator

If calling through an account, it is expected behavior to have the first returned value be the length of the return sequence (might depend on account implementation, but I believe they all work that way). Doesn't look like unwanted behavior, I'll be closing this. Tell me if you think it should be reopened.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants