Webjs and the ABI Array
Youāre maybe wondering, whatās this ABI array? And why do I need it for interacting with smart contracts.
Those are really good questions which I am trying to answer now in this lecture.
ABI stands for Application Binary Interface.
When you compile a smart contract then you get bytecode which gets deployed. Inside there are assembly opcodes telling the EVM during execution of a smart contract where to jump to. Those jump destinations are the first 4 bytes of the keccak hash of the function signature.
Best is, weāre looking through the lens of the debugger into the execution of a smart contract and run through that.
Enable the Debugger Plugin
In Remix, go to the Plugins and enable the Debugger plugin.
For a short-cut, click this linkā
Add the following sample code:
//SPDX-License-Identifier: MIT
pragma solidity 0.8.14;
contract MyContract {
uint public myUint = 123;
function setMyUint(uint newUint) public {
myUint = newUint;
}
}
- Deploy the Smart Contract
- update the
myUint
throughsetMyUint
- Then hit the ādebugā button in the console window
Using the Remix Debugger
The debugger will open up. On the left side, you see a horizontal scrollbar. Scroll it all the way to the beginning:
If you scroll (or step into) until instruction 041, you should see something like PUSH4 e492fd84
, which means, its now pushing the 4 bytes e492fd84 onto the stack and then in 046 its comparing it to the first 4 bytes of the calldata, which, incidentally also contains e492fd84 as the first 4 bytes.
Where are they coming from?
Itās the first 4 bytes of the function signature bytes4(keccak256(setMyUint(uint256)))
.
As you know with hashes, once you hashed a value its hard to go back, unless you have a rainbow table or do brute forcing of some sorts.
And web3js tries to offer nice functions to interact with a smart contract. So, in web3js, you can do things like contractInstance.methods.setMyUint(123)
, all with auto-completion. Thatās only possible, if we provide the information what functions exist on a smart contract to web3js.
This is what the ABI array does. You can stop the debugger nowā¦
The ABI Array
The ABI Array contains all functions, inputs and outputs, as well as all variables and their types from a smart contract.
If you open up the artifacts/MyContract.json file in the file-explorer, you can scroll all the way to the bottom. There you find the ABI array:
If you want to interact with a smart contract from web3js, you need two things:
- the ABI array
- the contract address (or you deploy the contract through web3js)
Add the following script and add the address of your contract from the Deploy & Send Transactions plugin
(async() => {
const address = "ENTER_ADDRESS_HERE_FROM_RUN_TX_PLUGIN";
const abi = [
{
"inputs": [],
"name": "myUint",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "newUint",
"type": "uint256"
}
],
"name": "setMyUint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
];
let contractInstance = new web3.eth.Contract(abi, address);
console.log(await contractInstance.methods.myUint().call());
let accounts = await web3.eth.getAccounts();
await contractInstance.methods.setMyUint(345).send({from: accounts[0]});
console.log(await contractInstance.methods.myUint().call());
})()
Then right-click on the file and run the script.
It should output 345 at the end:
Now youāre ready for some more advanced contract interaction. Letās have a look at events next!