Normally we use owner-only restrictions for the withdrawal functions but still, I'm curious why it didn't work.
I created a sender and receiver contract. After deploying the contract I kept some amount in the contract. Then I tried to withdraw that balance amount from another contract. I wrote two functions to try two different ways. One is using the interface and one is without it.
I'm not sure what I'm doing is the right way. Please help me to learn.
I got an error when I try to withdraw it from the contract WithrawAmtFromAnotherContract
Like this:
transact to WithrawAmtFromAnotherContract.stealAmntFromContract1
errored: VM error: revert.revert The transaction has been reverted to the initial state. Note:
The called function should be payable if you send value and the value
you send should be less than your current balance. Debug the
transaction to get more information.
This is the code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract ReceiveEther {
receive() external payable {}
fallback() external payable {}
function getBalance() public view returns (uint) {
return address(this).balance;
}
function withdraw() public payable{
payable(address(msg.sender)).transfer(address(this).balance);
}
}
contract SendEther {
function sendViaCall(address payable _to) public payable {
// Call returns a boolean value indicating success or failure.
// This is the current recommended method to use.
(bool sent, bytes memory data) = _to.call{value: msg.value}("");
require(sent, "Failed to send Ether");
}
}
interface With{
function getBalance() external view returns(uint);
function withdraw() external payable;
}
contract WithrawAmtFromAnotherContract{
function getBalance(address _address) public view returns(uint){
return With(_address).getBalance();
}
function stealAmntFromContract_method1(address payable _address) public payable{
With(_address).withdraw();
}
function stealAmntFromContract_method2(address payable _address) public payable{
payable(msg.sender).transfer(_address.balance);
}
}
Best Answer
In your case, when you call
stealAmntFromContract_method1()
method insideWithrawAmtFromAnotherContract
themsg.sender
value passed towithdraw()
function inside ReceiveEther is the WithrawAmtFromAnotherContract smart contract address and for this reason you see this error. That's because, WithrawAmtFromAnotherContract call withdraw() function on your behalf and passed it its address like msg.sender. You must to change your smart contract in this way:In this smart contract, I added a new input parameter call
_to
(datatype: address) that allows you to keep the user address that callstealAmntFromContract_method1
and pass it towidthdraw()
function. At this point, this last function'll have inside_to
input parameter the user address and it can transfer your balance to him.NOTE: I also changed withdraw() signature in
With
interface.