I'm developing two contracts:

Tokens : ERC20Burnable Transparent Upgradeable Proxy - contract minting a token 1:1 for each ethers sent.

Machine : Transparent Upgradeable Proxy - contract accepting Tokens as payment. When Tokens are received, Machine instantly burn them and redeem the associated ethers.

So far, so good... Except that I keep getting reverted transaction when trying to burn and redeem.

Here is the buy function from Machine contract :

function buy(uint _amount) public {

    emit MachineBuy(_amount, _msgSender());

Here is the burnAndRedeemFrom function from Tokens contract :

function burnAndRedeemFrom(address _from, uint _amount) public {
    burnFrom(_from, _amount);


    emit TokensBurn(_amount);

I'm sure that Tokens contract has funds. I'm sure that allowance from the address to Machine contract is correct.

Still I keep getting execution reverted?

How are transactions working here? Should the buy function be payable so the Tokens contract can send ethers?

What am I missing?

Thanks in advance!

  • buy doesn't need to be payable. Who will receive the Redeemed ether ? the Machine contract or the user who calls buy function from Machine contract?
    – minhhn2910
    Commented Dec 29, 2022 at 12:37

2 Answers 2


I have a guess here, will update if I get more info. I assume you have carefully checked others condition (e.g. approval & ether balance). The revert may come from this :


Here _msgSender() is the Machine contract. If that contract doesn't implement receive payable or fallback payable it will reject ether and revert the whole tx. This could be what you want to implement, the redeemed Ether will be sent directly to the user who triggers the transaction (who has the token).

  • You are right, it works perfectly when an user owned address calls burnAndRedeemFrom, but a contract calling this function would need a receive() external payable fallback function. Thanks!
    – Saucy
    Commented Dec 29, 2022 at 13:25

Thanks to @minhhn2910 I understood that my Machine contract was missing a fallback payable function!

So I added this to my Machine contract and now it works perfectly :

receive() external payable {}

More informations about fallback and receive functions here :


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.