- How smart contract storage works in general.
- Common scenarios where you need to retrieve data from contract storage.
- Step-by-step instructions on how to fetch data, using Solidity and a client library (e.g.,
web3.js
orethers.js
). - Best practices and potential pitfalls.
Prerequisites
- Understanding of Solidity
- You have a working development environment set up with:
- A Solidity compiler (e.g., via Hardhat, Truffle, or Remix).
- Access to the peaq network’s EVM endpoint (or a local test EVM).
- Using a library like
web3.js
orethers.js
to interact with your deployed contracts. Alternatively, any other JSON-RPC client can be used if you are comfortable with lower-level interactions. - Already have a deployed contract on the peaq network, or you have the means to deploy one during testing.
- Access to contract’s its Application Binary Interface (ABI). This is generally generated automatically when compiling your Solidity smart contract.
Instructions
1. Understanding EVM Contract Storage
In EVM-based networks like peaq, each contract has its own allocated storage. Storage is typically broken down into slots of 256 bits each:- State Variables store data in these storage slots.
- Mappings are hashed to find their storage slots.
- Arrays and other data structures have their own packing and storage rules.
2. Declaring and Storing Data in Solidity
Let’s look at a simple example contract that stores some data:storedValue
is a publicuint256
. By making it public, Solidity automatically creates a getter functionstoredValue()
that returns the value.balances
is a public mapping fromaddress
touint256
. Likewise,balances(address)
becomes a getter function to read the balance for any given address.
3. Interacting With the Contract to Fetch Data
Using a Script (JavaScript + ethers.js/web3.js)
Below is an example of how to fetch data fromstoredValue
and balances
using ethers.js
.
Ethers.js Example:
- We use the
view
functions (storedValue()
andbalances(address)
) to retrieve data without sending a transaction. - This means there is no cost in terms of gas for these read operations; only the provider’s request/response overhead applies.
Using the Remix IDE
If you prefer a browser-based approach:- Open Remix IDE.
- Select the “Solidity” environment and load your contract code.
- Compile and Deploy to a peaq network-compatible endpoint (via “Deploy & run transactions” panel).
- After deployment, you will see the contract’s interface in Remix.
- Clicking on
storedValue
will fetch and display the currentstoredValue
. - Providing an address to
balances
will fetch and display the mapping value for that address.
- Clicking on
4. Fetching Custom or Complex Data Types
If you have custom data structures like structs or nested mappings, you can expose them through custom getter functions. For example:User
is stored in a private mapping. We expose a getUser
function that returns the data in a single call. You can fetch it from your JavaScript code similarly with a function call:
Summary
Fetching data from smart contract storage on the peaq network (or any EVM-compatible network) follows the same paradigm as Ethereum:- You define state variables in Solidity.
- You expose those variables either with the
public
keyword or dedicated getter functions. - You interact with them through a client library (e.g.,
ethers.js
,web3.js
) or Remix IDE.
- Public Variables: Automatically generate getter functions, convenient for straightforward retrieval.
- View/Pure Functions: Cost no gas when called off-chain, making them ideal for reading data.
- Custom Getter Functions: Useful for complex data structures or additional data processing.
- Security: Ensure that any data you do not want freely accessible remains in private variables, and only expose it through controlled view functions as needed.