2

In the case of solidity language -

In smart contracts, state variables can be made public to allow for easy access and visibility of the data stored in the contract. When a state variable is declared as public, a getter function is automatically generated by the compiler, which allows any external entity to access the current value of that variable.

so, is it also possible to ink smart contracts?

// SPDX-License-identifier:MIT

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";

contract NFT is ERC721URIStorage{ uint public tokenCount;

...... ...... ...... ...... ......

}

2 Answers 2

2

You can also calculate the storage keys and use the getStorage method to avoid implementing getters.

If you have a contract with storage as follows:

    // Contract storage
    #[ink(storage)]
    pub struct Dapp {
        accounts: Lazy<Vec<AccountId>>,
    }

And storage in your JSON ABI as follows:

            {
              "layout": {
                "root": {
                  "layout": {
                    "leaf": {
                      "key": "0x87c1e648",
                      "ty": "8"
                    }
                  },
                  "root_key": "0x87c1e648"
                }
              },
              "name": "accounts"
            },

Then you can get the relevant storage key from the ABI using the following functions, although there is probably a better way in polkadot-js to do this.

class YourClass extends ContractPromise {
    async getStorageKey(storageName: string): Promise<`0x${string}`> {

        // Get the storage entry from the JSON which is the abi in ContractPromise
        // Assuming here that you're in a class that extends ContractPromise
        const json = this.abi.json

        // Returns the JSON object above
        let storage = json.storage.root.layout.struct.fields.filter(
            (obj: { name: string }) => obj.name === storageName
        )[0]

        if (storage) {
            while ('root' in storage.layout) {
                storage = storage.layout.root
            }
            const rootKey = storage.root_key
            const rootKeyReversed = reverseHexString(rootKey.slice(2))
            return `0x${rootKeyReversed}`
        }
        throw new Error('Storage entry not found')
    }
}
// used to reverse the hex key 0x87c1e648 above, swapping the Endianness
function reverseHexString(str: string): string {
    return (
        str
            .match(/.{1,2}/g)
            ?.reverse()
            .join('') || ''
    )
}

Now get your storage with this code, again assuming you're in YourClass extending ContractPromise.

import { firstValueFrom } from 'rxjs'

const storageKey = getStorageKey('accounts')
const type = 'Vec<AccountId>'
const promiseResult = api.rx.call.contractsApi.getStorage(contractAddress, storageKey)
const result = await firstValueFrom(promiseResult)
if (result) {
    const optionBytes = this.abi.registry.createType('Option<Bytes>', result)
    const accounts = this.abi.registry.createType(type, [optionBytes.unwrap().toU8a(true)])
    console.log(accounts)
}

Obviously, this process gets more complicated as your storage types get more complicated e.g. Vec<Struct>. Then you should be able to use typegen to generate your contract types, import them to the API, and construct them from the results of getStorage.

2

No, ink! does not generate the getter. You've to manually implement the getters.

#[ink::contract]
mod contracts {
    #[ink(storage)]
    pub struct Contracts {
        value: bool,
    }

    impl Contracts {
        /// Getter for self.value
        #[ink(message)]
        pub fn get(&self) -> bool {
            self.value
        }
    }
}

1
  • For simple values you can use getStorage and avoid bloating contract size by creating unnecessary getters.
    – forgetso
    Commented May 2, 2023 at 18:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.