3

What I am trying to achieve is like , i should be able to call a set of solidity functions dynamically based on some criteria. i'm using call() method to achieve the same.

(bool success, bytes memory result) =APContract.call(abi.encodeWithSignature(string(data), "hello"));

data variable contain the function call string "testCall(string)". instead of encoding from the contract I should be able to encode the same with javascript (because of some argument generation logic). so that i can call the function like APContract.call(data). Is there any method that help to achieve the same?

1
  • 2
    Just clarification: What i wanted is javascript snipet equivalent to abi.encodeWithSignature("testCall(string)", "hello") Feb 2, 2021 at 11:03

2 Answers 2

0

Here's what I used to crack the Ethernaut Puzzle Wallet level. I believe encodeFunctionCall is exactly what you're looking for:

let deposit   = web3.eth.abi.encodeFunctionCall(contract.abi[2], [])
let multicall = web3.eth.abi.encodeFunctionCall(contract.abi[6], [[deposit]])
let calldata  = web3.eth.abi.encodeFunctionCall(contract.abi[6], [[deposit, multicall]])

await sendTransaction({
  from:  player, 
  to:    instance,
  value: web3.utils.toWei('0.001', "ether"),
  data:  calldata
})
0

Not sure if I totally understood your question but you can take a look at the Solidity Documentation Contract ABI Specification: https://docs.soliditylang.org/en/latest/abi-spec.html#examples

To see how to encode the parameters on your own. It is basically a big concatenated strings set of function name hash and function arguments.

You can also take a look at this lib which performs "custom contract calls" (so not relying on any ABI): https://github.com/ERC725Alliance/erc725.js/blob/main/src/lib/utils.ts

Manual way

import Web3 from 'web3';

const web3 = new Web3();

const methodId = web3.utils.keccak256('testCall(string)').substr(0, 10); //0xc7cee1b7

// In this function call, the first and only parameter uses a dynamic type: string
// https://docs.soliditylang.org/en/latest/abi-spec.html#use-of-dynamic-types

// we use the offset in bytes to the start of their data area, measured from the start of the value encoding
// offset to start of data part of second parameter, 1*32 bytes, exactly the size of the head part

const stringArgument = web3.utils.padLeft(web3.utils.toHex(1*32), 64).replace('0x', '');
// 0000000000000000000000000000000000000000000000000000000000000020


const stringValue = 'TODO' // This one is a bit tricky, the docs explain it well: https://docs.soliditylang.org/en/latest/abi-spec.html#use-of-dynamic-types

const call = methodId + stringArgument + stringValue;

ABI way

You can always construct your own ABI dict, then web3 will handle the above conversion for you:

const contract = new web3.eth.Contract(
        [
            {
                name: 'testCall',
                inputs: [
                    { type: 'bytes32', name: '_hash', internalType: 'bytes32' },
                ],
            },
        ],
        contractAddress,
    );

const answer = await contract.methods
            .testCall(messageHash)
            .call();

ABI utils way

Use the helpers fonctions from: https://web3js.readthedocs.io/en/v1.3.0/web3-eth-abi.html to build what you need.

web3.eth.abi.encodeParameter('string', 'Hello')

Edit: you can also check web3 source code

1
  • Thanks for putting effort on answering.what i wanted to do is encode the method from javascript using a method equivalent toabi.encodeWithSignature("testCall(string)", "hello"). and the encoded bytes will be passed a parameter of a solidity function (will be web3 call). that particular function will call like aPContract.call(data). data is the encoded bytes came as argument of the called function. It'll be help full if you guide in that way Feb 3, 2021 at 4:47

Your Answer

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

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