0

First, this is not a duplicate question of these ones:

I would like to know if it's possible to call a payable function in contract B from a non-payable function in contract A and paying from contract A's balance and not from the caller.

This way, the call would be "free" for the caller and the contract will assume the costs of paying the second payable function.

I've tried using the {value: amount} in the call request, but this seems to get the funds from the caller, not from the contract balance.

Thank you!!

3 Answers 3

0

This is just pure conjecture, but I know it's possible to call a payable function with a value of 0. Therefore it should be possible to do what you're describing. You should try it out on remix.ethereum.org

0

Yes, it is possible, here is an example: I have deployed my first contract TestPayable that contains a payableFunction that requires 1 ether.

contract TestPayable {

    uint public count;

    function payableFunction() payable external {
        require(msg.value == 1 ether);
        count++;
    }

    function getBalance() external view returns(uint) {
        return address(this).balance;
    }
}   

Then I have my second contract CallPayable, I have a receive function, I'm sending a few ethers before calling callPayableFunction.

   interface ITestPayable {
        function payableFunction() payable external;
    }
    
    contract CallPayable {

    receive() payable external {
        
    }

    function callPayableFunction(address contractAddress) external {
        IPayable(contractAddress).payableFunction{value: 1 ether}();
    }

    function getBalance() external view returns(uint) {
           return address(this).balance;
    }
}

By calling callPayableFunction, it calls payableFunction() from TestPayable, increases the balance of the TestPayable, and decreases the CallPayable balance.

hope it helps

0

wow, thank you very much for your answer, it worked. I don't know what I was doing before, because I think I was doing the same thing :S

I have extended your example, is this correct?

interface ITestPayable {
    function payableFunction() payable external;
}

contract CallPayable {

receive() payable external {
    
}

// This function pays from the caller: msg.value
function callPayableFunction(address contractAddress) external payable {
    require(msg.value >= 1 ether);
    
    ITestPayable (contractAddress).payableFunction{value: 1 ether}();
}

// This function pays from this contract balance
function callPayableFunction(address contractAddress) external {
    ITestPayable (contractAddress).payableFunction{value: 1 ether}();
}

function getBalance() external view returns(uint) {
       return address(this).balance;
}

}

In the code above, there are two functions that call the second contract payable function:

  • One of them is also payable, thus it will pay from the msg.value.
  • The other one is not payable, therefore it will pay form the contract balance

Is this understanding correct?

1
  • No, it's not correct ;) ethers always go to the SC balance and after that, SC can send out ethers from its balance. Both methods you wrote sends ethers from the contract's balance, the only difference is that with the first method you can "refill" with ethers the contract balance at the same time you send ethers to the other contract. With the second method you need to have sent value before in other ways (i.e. with calling the receive method) May 25, 2022 at 22:38

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.