Revert on unmatched function with upgradeable contract?

:computer: Environment
@openzeppelin/cli: 2.8.0
@openzeppelin/contracts-ethereum-package: 2.5.0
@openzeppelin/upgrades: 2.8.0


I’m using the OpenZeppelin Proxy Upgradeability pattern faciliated through the OpenZeppelin CLI.

Everything is working well - my one question is wondering if it’s possible to revert() a transaction when the underlying “logic” contract (the one the developer writes when using this pattern) doesn’t have a function matching the transaction encoded data.

Example: My contract has a payable function signature of buyStamp(). However, Bob calls buyStamp(5) on my contract - and sends 5 ETH. The signature buyStamp(uint256) doesn’t exist so the proxy forwards it to my contract, and nothing happens - Bob doesn’t buy a stamp. However:

  1. To Bob it originally appears the transaction was successful (it didn’t fail).
  2. Bob just gave away 5 ETH for nothing in return.

I’m wondering if it’s possible the transaction fails instead of the current behavior.

I think generally the best practice is something like below, where you’d check the is empty (ie. they weren’t trying to call a function). I believe this would be added to the “logic” contract (not OpenZeppelin’s Proxy contract).

function() payable { require( == 0); }

However, I’m not sure if that will mess with the OpenZeppelin proxy pattern functionality.

Thanks for any help!

1 Like

Hi @Dyno,

My understanding is that if the function signature doesn’t exist then calling the non-existant function via the proxy will revert unless there is a fall back function in the logic contract. So I am not sure if I can see how we would get to your scenario.

Are you able to put together an example?

Hi @abcoathup

Thanks for the response.

Ah, ok that’s good news - yes, in the contract in question there is a fallback function. Currently it is defined as:

function() external payable {}

I’m guessing that I need to either remove it, or require the == 0. I need the fallback definition so I can receive Ether transfers - therefore I’m guessing the solution is to do the latter.

From what you’ve said, the proxy will still forward the logic contract the non-existent function - but now it will revert as the > 0. Also, my understanding is that the proxy contract doesn’t forward all function calls to the logic contract’s fallback function - only ones where a matching function signature is missing.

Is this correct?

Yes exactly.

This is not exactly correct. You can read more about this in Transparent Proxies and Function Clashes in the docs.


Awesome, thanks for the clarification @frangio

1 Like