Search code examples
ethereumsmartcontractscryptocurrencyerc20openzeppelin

Figuring out addresses in an ERC20 contract


I'm writing an ERC20 contract that would allow another ERC20 to be able to work with my contract, and am unsure how to get a specific address in the scenario given below.

Say my contract is CoinA, and someone else's contract is PartnerCoin. I'm proxied, and they may or may not be (in the scenario, I am already aware of if they are or aren't proxied, however). And say I'm using OpenZeppelin as my proxy. My coin's proxy contract address is 0x123 and their coin's contract (or proxy) address is 0x456. We can say that, if PartnerCoin is proxied, then their implementation address is 0x192.

Person, Bob, comes along and wants to transfer 10 of his PartnerCoin over to his friend, John. Bob's wallet address is 0x987 and John's wallet address is 0x654. PartnerCoin has a require on its transfer function that it must receive a specific response from a public function it can call from CoinA, otherwise it won't transfer. It calls the function, we'll call it SuperFunction, on CoinA and awaits a response.

I only want PartnerCoin to be able to call SuperFunction, at least for now, and I know what PartnerCoin's address is.

Within my implementation contract, say, 0x384, I believe it's the case that:

msg.sender would return 0x123, my own proxy, because my proxy is calling my implementation, correct?

_msgSender() would return 0x987, because they're the actual end user.

What would return 0x456, PartnerCoin's contract address, so that CoinA could check that it's indeed PartnerCoin that is calling SuperFunction, and not some other coin?

Thank you for the help!


Solution

  • The OpenZeppelin _msgSender() (source) currently (OZ 4.x, Solc 0.8.x) returns the same value as the global variable msg.sender. The function exists for easier upgradability, if the msg.sender ever becomes deprecated (as already happened with its predecessor, tx.origin).

    When the PartnerCoin calls your SuperFunction, it doesn't make a difference if they're calling your contract directly or through a proxy (that delegatecalls your contract). The msg.sender is always going to be the PartnerCoin

    If the proxy only called (and not delegatecalled) your contract, then yes, the msg.sender would be the proxy. But that's not the case of the OpenZeppelin Proxy contract (source).