1

I have 3 interconnected questions.

  1. Could you please explain me the difference between two methods of interaction with contract mentioned below:
 `async function main () {
    const targetAddress = '0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512';
    const accountAddress ='0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199';
    const signer = ethers.provider.getSigner(accountAddress);
    const targetContract = new ethers.Contract(targetAddress, Artifact.abi, signer);
    const contractCall = await targetContract.caller()
    console.log(contractCall);
    }`

and the second:

const sender = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266';
const receiver ='0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512';
const signer = provider.getSigner(sender);

let tx = {
    to: receiver,
    value: amountInEther,
    data:
}
   
result = await signer.sendTransaction(tx)

First is using abi, second using call method with raw data, right?

Second question: what is new ethers.Contract? I read docs but still don't undertand what is Contract instance? Does it like temporary copy of contract?

Third question: how can i send call function, assume balanceOf() using await signer.sendTransaction(tx) ,method? Should I encode it at bytecode and input in "data:" ?

Thank you very much!

2 Answers 2

0

The first is instantiating a contract js instance and calling its methods through it. Doing it this way is helpful because we don't have to encode the data manually, but the contract instance will do it for us.

The second is making a raw transaction, which could be sent to the smart contract or a regular account. If you want to send a transaction this way to a smart contract, then the to needs to be the contract address, and we need to add the data manually. In the data field, we need to indicate what smart contract method we want to call and pass the parameters, all encoded.

For example, if the smart contract has a method caller() that does not receive any parameter, then the data we need to send is the first 4 bytes of the keccak256 hash of "caller()". It's fc9c8d39. This is the way of indicating which function from the smart contract to call. Check the hash yourself here: https://emn178.github.io/online-tools/keccak_256.html

enter image description here

So, our payload would look like this:

let tx = {
    to: contractAddress,
    value: amountInEther, // Optional when calling a contract, unless the function we are calling is `payable`
    data: "0xfc9c8d39" // The `caller()` method in the smart contract will be executed
}

As you can see, it's a bit cumbersome to do it this way. That's why we better create a contract instance that will abstract and take care of all that for us. And that takes me to your second question.

new ethers.Contract(contractAddress, abi, signer) is used to create a 'wrapper', a instance of the smart contract in Javascript, so you don't need to think about encoding and decoding data manually. Obviously, this instance is not the contract itself, but just an abstraction that allows us to seamlessly use the smart contract from Javascript. It makes the calls to the real contract located at contractAddress, encoding the data, which function to call, the parameters, etc. It's really convenient.

And your third question, yes, you can do it manually, calculation the keccak256 hash of the balanceOf(address), encoding the first 4 bytes of that hash with the address param value, using something like:

const data = ethers.utils.defaultAbiCoder.encode(
  ["bytes4", "address"],
  ["0x70a08231", "0x6827b8f6cc60497d9bf5210d602C0EcaFDF7C405"]
);

The encoded data given the above values to encode will look like this:

0x70a08231000000000000000000000000000000000000000000000000000000000000000000000000000000006827b8f6cc60497d9bf5210d602c0ecafdf7c405

And adding it to our payload looks like this:

let tx = {
    to: contractAddress,
    data: "0x70a08231000000000000000000000000000000000000000000000000000000000000000000000000000000006827b8f6cc60497d9bf5210d602c0ecafdf7c405" // The `balanceOf(address)` method in the smart contract will be executed
}

But as you can see, it's cumbersome. Better get the ABI of the contract you need and instantiate a Javascript instance of it and use it, so it handles all the encoding/decoding details for you.

0

Q1

Well,In first one we are getting the contract through abi and target address and calling the contract function caller() and console log it. But in the second one we are sending eth from the sender to receiver using .sendTransaction().

Q2

And you asked what is ethers.Contract here is it,

enter image description here Basically it used to connect contract using a provider, so we will only have read only access to the contract.

Q3

And if we want to call and function it depends that the function is an view or not means if the function is view(which reads data from blockchain) it does not require any gas so we call it by using eth.call() or if the function changes the state then use eth.sendTransaction(). eg:

so the first 4 bytes of

web3.sha3('get()');
"0x6d4ce63caa65600744ac797760560da39ebd16e8240936b51f53368ef9e0e01f"

So the first 4 bytes is : 0x6d4ce63c

// for function without parameters
eth.call({
   to: Contractaddress, // need to define address first
   data: "0x6d4ce63c"   
})

// for function with parameters
var para="000....00FF" // para is the encoded argument
eth.call({
    to: ContractAddress,
    data: "0x6d4ce63c"+ para  
})

Well as you said you want to read the balanceof() of address first then you can use this .call().

So if you want to call an function which make changes in blockchain we have to use .sendTransaction as it uses gas. first getting the same first 4 bytes of the function hash

web3.sha3("set(uint256)");
"0x60fe47b16ed402aae66ca03d2bfc51478ee897c26a1158669c7058d5f24898f4"

so the first 4 bytes is: 0x60fe47b1

eth.sendTransaction({
    from: eth.accounts[0],
    to: ContractAddress,
    data: "0x60fe47b1" + arg  // as said it is the encoded argument
})

parameters are as follows

enter image description here

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.