Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

length and offset is 0 ? #471

Closed
oznfc opened this issue Aug 21, 2021 · 20 comments
Closed

length and offset is 0 ? #471

oznfc opened this issue Aug 21, 2021 · 20 comments

Comments

@oznfc
Copy link

oznfc commented Aug 21, 2021

I'm using flipper examle for solana. if ı call flip and get function together my codes is working. but ı tried different way.
first step ı call only Flip function.
second step ı call only get function . When ı called only get fuction after the first step my ofset and length is "0" .
I have to use the flip and get functions together. Why ?

@seanyoung
Copy link
Contributor

The flip function has no return values, so the length will be zero. It might make sense for the flip function to return the current state. Does that explain what is happening?

@oznfc
Copy link
Author

oznfc commented Aug 22, 2021

I know flip has no return values.already ı tried for get function. error :

UnhandledPromiseRejectionWarning: Error: Returned values aren't valid, did it run Out of Gas? You might also see this error if you are not using the correct ABI for the contract you are retrieving data from, requesting data from a block number that does not exist, or querying a node which is not fully synced.

I tried at new contract , simple name get- set functions . same error.

@seanyoung
Copy link
Contributor

Would you mind sharing your code so I can reproduce this issue? I don't know how this can happen without seeing your code. Thanks

@oznfc
Copy link
Author

oznfc commented Aug 22, 2021

yes sure.

contract Events {
    string public name;
    string public surname;

    event NameChanced(string message, string newName);
    event SurnameChanced(string message, string newSurname);

    constructor() public {
        name = 'myName';
        surname = 'mySurname';
    }

    function setName(string memory _name) public {
        name = _name;
        emit NameChanced('Name Chanced', _name);
    }

    function setSurname(string memory _surname) public {
        surname = _surname;
        emit SurnameChanced('Surname Chanced', _surname);
    }

    function getNames() public view returns (string memory _name , string memory _surname ) {
        return (name ,surname);
    }


    function getName() public view returns (string memory _name ) {
        return name ;
    }

     function getSurname() public view returns (string memory _surname ) {
        return surname ;
    }

}

@seanyoung
Copy link
Contributor

Would you mind sharing the client-side code too? Thanks

@oznfc
Copy link
Author

oznfc commented Aug 22, 2021

I already using solang library. if ı using this style (2 function together. ) ı can see account data.

        let res = await prog.call_function(conn, "setName", ["ozan"]);
        let res2 = await prog.call_function(conn, "getName", []);

but if I use only await prog.call_function(conn, "setName", ["ozan"]); than ı call await prog.call_function(conn, "getName", []); function than ı cant see account data.

            const accountInfo = await test.connection.getAccountInfo(this.contractStorageAccount.publicKey);
            let length = Number(accountInfo!.data.readUInt32LE(4));
            let offset = Number(accountInfo!.data.readUInt32LE(8));

length and offset are zero.

@seanyoung
Copy link
Contributor

I think I can reproduce an issue. Let me get back to you..

@oksanassss
Copy link

oksanassss commented Aug 23, 2021

Ok. I am waiting.

@seanyoung
Copy link
Contributor

Would you mind testing this again with the latest solang? Also note that I have turned your example into a test case.

@oksanassss
Copy link

did you test it? length and offset are 0 after the setName() function. so ı can't read data.

@seanyoung
Copy link
Contributor

Yes, the tes runs and the tests get run by github actions at every pull request as well.

Note that setName will clear the offset/length because the function has no return values.

Would you mind sharing your entire test case so I can reproduce the problem?

@oksanassss
Copy link

oksanassss commented Aug 24, 2021

hmm , understood. now running . I misunderstood some things. another question. :
if ı want not use getName() .
Because

    string public name;
    string public surname;

is public data. Do I have to use the call_function function again? can ı read public datas in accounData ?

@seanyoung
Copy link
Contributor

A public variable will have an accessor function generated. This means you do call_funtion('name', []) and there is no need for the getName() function.

@oksanassss
Copy link

I know but call_function wants gas fee. I should not pay gass fee to read public data.

@seanyoung
Copy link
Contributor

Yes, you're absolutely right. So this should be done via an RPC call, which does not charge any gas at all. However, since this function writes to account data, it cannot be an RPC call.

The way to fix this is to provide an alternate way of returning data in Solana. This is why solana-labs/solana#19318 exists. Hopefully this will be approved soon and then it can be implemented.

@oksanassss
Copy link

oksanassss commented Aug 24, 2021

Hopefully. Actually what I'm looking for is something like this:

contractStorageAccount = new PublicKey("24QoA3yefopzVxNuGFGKdcmbSebheZaFt9XBKJKarFur");
    const accountInfo = await connection.getAccountInfo(contractStorageAccount);
    const data = Buffer.from(accountInfo.data);
    const DataInfoLayout = BufferLayout.struct([
        BufferLayout.u8("data1"),
        BufferLayout.u8("data2"),
    ]);
    const tokenInfo = DataInfoLayout.decode(data);
    console.log(tokenInfo)
   // output { data1: 0, data2: 1 }

When I try with this method, I can read data from a normal solana program. I don't know if I can read from Solang this way. I tried, it didn't work.

@seanyoung
Copy link
Contributor

For the first string, you need to read the u32 at offset 16 (let's call this V). If V is 0, the string is empty; if is not zero, then it is the offset at which the string is stored. The length can be fetched the u32 at V - 8.

Ideally we need a node library that can do this. There is a plan for a npm package here solana-labs/solana-solidity.js#1, I will add an entry for reading the storage.

@oksanassss
Copy link

I'm looking forward.

@seanyoung
Copy link
Contributor

That solana-solidity.js project has just received funding from Solana (25k USD). Hopefully it will move quickly.

@seanyoung
Copy link
Contributor

@oznfc @oksanassss anything else I can help with or can I close this issue?

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

No branches or pull requests

3 participants