How to do a contract call in RSK network
Unlike sending a transaction, where one must pay a fee and wait for it to be mined (because it modifies the blockchain’s state), calling directly a view or pure function in a contract is a free procedure where the node responds immediately.
This will be useful for oracles or any process that needs to check information frequently or dynamically that is stored or calculated in a smart contract.
Here will be explained two ways to do it:
- Using the cURL command line, which will be already present in most of bash terminals.
- Using ethers.js library for NodeJS which requires installing some dependencies and a small script.
Both will require:
- The data that will be sent in the contract call, which is basically the encoded signature of the smart contract’s function you want to call.
- The contract address that is being called.
- The node url to send the call. For this example it will be used the RSK testnet public node: https://public-node.testnet.rsk.co
Get the encoded signature
If there’s a method declared as function multiply(uint256 x, uint256 y), the signature will be multiply(uint256, uint256), which is the name of the function and the type of the parameters between parentheses. If it doesn’t have any parameter, the parentheses will be empty.
Now it needs to be hashed with keccak256 in order to indicate the contract which method you are calling. This webapp will do it. Entering the function signature in the input will output the hashed one. Now taking the first 4 bytes (the 8 first characters from the left), and adding 0x at the beginning will result in the data to send in the contract call.
Let’s use a real example of a contract in RSK testnet; the Rif On Chain (RoC) stablecoin price feeder. It has the method getPrice(), so:
Method signature: getPrice()
Hashed signature: 98d5fdcadea1306147ea4341c5601cc83106db3090e2da99fbba25961fd05868
Call data: 0x98d5fdca
Call the contract using cURL
This is the fastest and easiest method since it only requires to enter a command in a terminal; but since it won’t be integrated into any program it may be more useful for occasional calls.
Open a terminal and run:
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0x159980A48aBb56b190C2Ea8593515ee8fE7B197b","data":"0x98d5fdca"}, "latest"],"id":1}' \
https://public-node.testnet.rsk.co
As it’s shown, the method used is eth_call. The first parameter has the to property, which is the contract being called (the testnet RoC stablecoin price feeder in this case), the data property that is the encoded signature getPrice(), and the second parameter is a string asking for the more recent block to read the blockchain’s state from. If the block was other than the latest one, and the method depended on any permanent state, it would reflect the state of that block.
At the end of the command there’s the public node url for testnet.
It will output something like this:
{"jsonrpc":"2.0","id":1,"result":"0x0000000000000000000000000000000000000000000000000de0b6b3a763ffff"}
The hexadecimal result converted to decimal will be the RoC stablecoin price.
Call the contract using Ethers.js
- NodeJS and NPM need to be installed.
- Open a terminal, create a folder and move into it: mkdir test-call && cd test-call
- Install Ethers.js library and create an empty .js file: npm install ethers && touch script.js
- Edit the script with your preferred code editor and add the following code:
const { ethers } = require('ethers')
const nodeURL = 'https://public-node.testnet.rsk.co'
const provider = new ethers.JsonRpcProvider(nodeURL)
const GET_PRICE_METHOD = '0x98d5fdca'
const PRICE_FEEDER_ADDRESS = '0x159980A48aBb56b190C2Ea8593515ee8fE7B197b'
const getPriceTx = {
to: PRICE_FEEDER_ADDRESS,
data: GET_PRICE_METHOD
}
async function main() {
const price = await provider.call(getPriceTx)
console.log(price)
return
}
main()
- Save the script and run it: node script.js
It will output the price directly in the console, in hexadecimal as the cURL approach as well.
And that’s how a smart contract can be called from outside the blockchain, without spending any money and getting an immediate response.
Remember this will only work with view and pure functions, which don’t modify the EVM state.