Why an old value of an smart-contract property is retrieved instead of the most current one?

Viewed 192

I've deployed a simple ERC721-compatible contract to the Polygon network:

contract MyContract is ERC721 {
    uint256 public counter;
    constructor(string memory name, string memory symbol) ERC721(name, symbol) {
        // ...
        counter = 0;
    }
    function myMethod(string memory _arg) public {
        // ...
        counter++;
    }
}

My only interaction with the contract is to simply fetch the value of counter and then call the myMethod(), all in a loop:

for (let i = 0; i < N; ++i) {
  const counter = (await contract.counter()).toNumber();
  console.log(`counter: ${counter}`);
  // ..
  const tx = await contract.connect(myAccount).myMethod(str);
  await tx.wait();
}

It's all fine; but sometimes an old value of the "counter" is retrieved, for example:

counter: 11                     counter: 96
counter: 12                     counter: 97
counter: 13                     counter: 98
counter: 14                     counter: 60  <---- ??!!
counter: 15                     counter: 100 ** corrected in the next iteration
counter: 12  <---- ??!!
counter: 17  ** corrected in the next iteration

Why is that? How should I avoid it?!

It worth noting: in the subsequent iterations, as per the example above, the counter is retrieved correctly and holds the most up-to-date value.

1 Answers

defining state variable public and calling it is not the right method. Since it is public it can be overwritten by mistake easily somewhere in your code. Instead:

uint256 private counter; 

then write a getter:

function getCounter() external view returns(uint256){
   return counter
}

also a setter and call this setter inside myMethod

function setCounter() external {
  counter++
}
Related