Skip to main content
const Web3 = require('web3');

async function encodeFunction() {

  // generate function signature
  const hashedFunction = web3.utils.keccak256("transfer(address,uint256)")  // Function name and parameters
  const functionSignature = hashedFunction.substr(0, 10); // Extract the first 8 digits (4bytes) + 0x

  // Encode function parameters
  const firstParameter = '0xdfd5293d8e347dfe59e90efd55b2956a1343963d'
  const paddedFirstParameter = web3.utils.padLeft(firstParameter, 64); // Pad to 32 bytes (64 hex characters)
  const encodedParam1= paddedFirstParameter.slice(2) // Slice(2) remove 0x

  const secondParameter = '1000000000000000000'
  const hexParameter = web3.utils.toHex(secondParameter); // Convert the input from decimal to hex
  const paddedSecondParameter = web3.utils.padLeft(hexParameter, 64); // Pad to 32 bytes (64 hex characters)
  const encodedParam2= paddedSecondParameter.slice(2) // Slice(2) remove 0x

  // Generate calldata
  const functionCallData = functionSignature + encodedParam1 + encodedParam2

  console.log(`Encoded function signature: ${functionSignature}\n`); // Log the encoded function signature
  console.log(`Encoded parameter 1: ${encodedParam1}\n`); // Log the encoded first parameter
  console.log(`Encoded parameter 2: ${encodedParam2}\n`); // Log the encoded second parameter
  console.log(`Function calldata: ${functionCallData}`) // Log the complete calldata
}

encodeFunction()
$ node theory
Encoded function signature: 0xa9059cbb

Encoded parameter 1: 000000000000000000000000dfd5293d8e347dfe59e90efd55b2956a1343963d

Encoded parameter 2: 0000000000000000000000000000000000000000000000000de0b6b3a7640000

Function calldata: 0xa9059cbb000000000000000000000000dfd5293d8e347dfe59e90efd55b2956a1343963d0000000000000000000000000000000000000000000000000de0b6b3a7640000

$ node index
Function name: transfer
Function signature: 0xa9059cbb
Encoded parameters: 000000000000000000000000dfd5293d8e347dfe59e90efd55b2956a1343963d0000000000000000000000000000000000000000000000000de0b6b3a7640000

Function calldata: 0xa9059cbb000000000000000000000000dfd5293d8e347dfe59e90efd55b2956a1343963d0000000000000000000000000000000000000000000000000de0b6b3a7640000
When interacting with a smart contract on the Ethereum blockchain, developers use a data field named callData, which is an encoded string that specifies the function to be called and its parameters.To encode the callData parameters, developers use the Ethereum ABI specification, which defines how to encode data structures for communication between different components of an Ethereum application.Here you will find two scripts:
  • theory.js shows you the intermediate steps and the logic. This is a more hardcoded approach, but it shows you the inner workings.
  • index.js shows you an efficient way to leverage the web3.js library tools to generate universals callData. This method abstracts the logic under web3.js’ hood.
Install node.js in case it is not installed.Create a new directory for your project, then Install the web3.js library.npm install web3
The first step is to create a Web3 instance to be able to access the web3.js tools.
const Web3 = require('web3');
This function generates the encoded callData.
async function encodeFunction() {
The first step is to generate the signature of the smart contract function you intend to call.The signature is generated by taking the first 8 characters (4 bytes) of the Keccak-256 hash of the function’s name and the type of its parameters.See the comments in theory.js to learn more.If you see the logic in index.js, you will notice that the signature is encoded directly using the function’s name and parameters, and it is much more efficient.
// generate function signature
  const hashedFunction = web3.utils.keccak256("transfer(address,uint256)")  // Function name and parameters
  const functionSignature = hashedFunction.substr(0, 10); // Extract the first 8 digits (4bytes) + 0x
Then we can encode the parameters. The principle is the same as for the logs topics: the parameters are encoded in a 32-bytes hexadecimal string.You can see each step in theory.js, while, in index.js, everything is abstracted away and done in one line of code using the encodeParameters function.
  // Encode function parameters
  const firstParameter = '0xdfd5293d8e347dfe59e90efd55b2956a1343963d'
  const paddedFirstParameter = web3.utils.padLeft(firstParameter, 64); // Pad to 32 bytes (64 hex characters)
  const encodedParam1= paddedFirstParameter.slice(2) // Slice(2) remove 0x

  const secondParameter = '1000000000000000000'
  const hexParameter = web3.utils.toHex(secondParameter); // Convert the input from decimal to hex
  const paddedSecondParameter = web3.utils.padLeft(hexParameter, 64); // Pad to 32 bytes (64 hex characters)
  const encodedParam2= paddedSecondParameter.slice(2) // Slice(2) remove 0x

The last portion simply puts together the outputs. As you can see, both scripts produce the same callData outcome.Note that in index.js, we can pass more dynamic functions and parameters.
  console.log(`Encoded function signature: ${functionSignature}\n`); // Log the encoded function signature
  console.log(`Encoded parameter 1: ${encodedParam1}\n`); // Log the encoded first parameter
  console.log(`Encoded parameter 2: ${encodedParam2}\n`); // Log the encoded second parameter
  console.log(`Function calldata: ${functionCallData}`) // Log the complete calldata
}
const Web3 = require('web3');

async function encodeFunction() {

  // generate function signature
  const hashedFunction = web3.utils.keccak256("transfer(address,uint256)")  // Function name and parameters
  const functionSignature = hashedFunction.substr(0, 10); // Extract the first 8 digits (4bytes) + 0x

  // Encode function parameters
  const firstParameter = '0xdfd5293d8e347dfe59e90efd55b2956a1343963d'
  const paddedFirstParameter = web3.utils.padLeft(firstParameter, 64); // Pad to 32 bytes (64 hex characters)
  const encodedParam1= paddedFirstParameter.slice(2) // Slice(2) remove 0x

  const secondParameter = '1000000000000000000'
  const hexParameter = web3.utils.toHex(secondParameter); // Convert the input from decimal to hex
  const paddedSecondParameter = web3.utils.padLeft(hexParameter, 64); // Pad to 32 bytes (64 hex characters)
  const encodedParam2= paddedSecondParameter.slice(2) // Slice(2) remove 0x

  // Generate calldata
  const functionCallData = functionSignature + encodedParam1 + encodedParam2

  console.log(`Encoded function signature: ${functionSignature}\n`); // Log the encoded function signature
  console.log(`Encoded parameter 1: ${encodedParam1}\n`); // Log the encoded first parameter
  console.log(`Encoded parameter 2: ${encodedParam2}\n`); // Log the encoded second parameter
  console.log(`Function calldata: ${functionCallData}`) // Log the complete calldata
}

encodeFunction()
$ node theory
Encoded function signature: 0xa9059cbb

Encoded parameter 1: 000000000000000000000000dfd5293d8e347dfe59e90efd55b2956a1343963d

Encoded parameter 2: 0000000000000000000000000000000000000000000000000de0b6b3a7640000

Function calldata: 0xa9059cbb000000000000000000000000dfd5293d8e347dfe59e90efd55b2956a1343963d0000000000000000000000000000000000000000000000000de0b6b3a7640000

$ node index
Function name: transfer
Function signature: 0xa9059cbb
Encoded parameters: 000000000000000000000000dfd5293d8e347dfe59e90efd55b2956a1343963d0000000000000000000000000000000000000000000000000de0b6b3a7640000

Function calldata: 0xa9059cbb000000000000000000000000dfd5293d8e347dfe59e90efd55b2956a1343963d0000000000000000000000000000000000000000000000000de0b6b3a7640000
I