Implementation is stored as value in
IMPLEMENTATION_SLOT (see the source code), so you can get the underlined Contract with:
let proxyContract = "0x4fabb145d64652a948d72533023f6e7a623c7c53";
let storagePosition = "0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3";
let result = await web3Client.eth.getStorageAt(proxyContract, storagePosition);
// > 0x0000000000000000000000005864c777697bf9881220328bf2f16908c9afcd7e
implementation method you are calling is allowed only with admin rights. I think, this method is there for testing or a quick check only.
Etherscan also shows
0x5864c777697bf9881220328bf2f16908c9afcd7e as a target implementation contract.
But, what I'm wondering is, why when reading
totalSupply in proxy
0x4fabb145d64652a948d72533023f6e7a623c7c53 it returns
9023954154960000000000000000, but directly inside the implementation
0x5864c777697bf9881220328bf2f16908c9afcd7e it returns
0. May be smbd. here will have a clue.
Ok, found it - storage belongs to the proxy, means the proxy is like a storage container, and when it calls implementation methods, they are called in the proxy storage context.
* @title BUSDImplementation
* NOTE: The storage defined here will actually be held in the Proxy
* contract and all calls to this contract should be made through
* the proxy, including admin actions done as owner or supplyController.
* Any call to transfer against this contract should fail
* with insufficient funds since no tokens will be issued there.
Implementation Storage Slot
Usually, the unstructed pattern is used to persist the Implementation Contract Address, as otherwise it could conflict with the implementation.
There is also a standard for this https://eips.ethereum.org/EIPS/eip-1967 , but before
openzeppelin had its own approach https://blog.openzeppelin.com/proxy-patterns/
In both cases the slots are hardcoded:
bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)) resolves to
keccak256("org.zeppelinos.proxy.implementation") resolves to
I don't know, if from ABI you can distinguish both this standard implementations, please check the differences, but anyway you can try to read both storage slots.
If the contract uses not standard proxy patterns, then you have to know the implementation.