[Ethereum] Simple deposit and withdrawal contract, withdrawal not returning error but executing

contract-designcontract-developmentsolidity

I am attempting to write a contract that takes a two Ether deposit, has a function to check the balance of the contract, and also a function to remove the Ether from the contract and send it to the owner.

For example 0x17F deploys the contract and is the owner, 0xCA3 initialized the accept() function and two ETH is taken out of that address and appears as in the contract address 0xE2D. Now I would like to pay out the contract holdings to the owner by way of the collect() function.

When I try to run the collect() function, it seems to execute but no ether is removed from the contract and none is sent to the owner.

My code:

pragma solidity >=0.7.0 <0.9.0;


contract  AcceptEth {

    address public owner;
    uint public price = 2 ether;
    mapping (address => uint) balance;
    //uint256 contractBalance = address(this).balance;
    uint256 public val = 1;

    constructor() {
        owner = msg.sender;
    }


    function accept() payable public {
        // Error out if anything other than 2 ether is sent
        require(msg.value == price);

        //Remove the 2 ether from the initiator of the accept function, and add it to the contract address balance
        balance[address(this)] += msg.value;
    
    
    }

    function check() public returns(uint256) {
        //Error out if anyone other than owner tries to check the balance
        require(msg.sender == owner);
    
        //Show the balance on the contract address
        return address(this).balance;
    
    }

    function collect() payable public {
        //Error out if anyone other than the owner tries to collect
        require(msg.sender == owner);
    
        //Send the ether in the contract address, to the owner of the contract address
        balance[owner] += balance[address(this)];
    
    
    }


}

The last function appears to execute in remix, and renders a green check in the console. Besides that, nothing seems to happen. There may be something fundamental I am missing, so would appreciate if it appears I am doing something wrong in general with my contract if you could let me know.

So my question is, how can I retrieve the ETH from the contract and send it to the owner?

***Note that I am very new to Solidity and there may be lots of problems/misunderstandings I present here, so any commentary would be great.

Best Answer

I'm not sure if this is the block, but many new developers struggle with separating "balance" into protocol ETH balances, which every address has, and internal accounting concerns. A variable called balance is just a variable with no actual impact on the coins in the contract or any other user's account.

This does internal accounting that isn't necessary and then does not transfer any ether.

balance[owner] += balance[address(this)];

A balances mapping such as that is usually used to track liabilities to users. Consider a contract with many user deposits. The contract balance would correctly report the funds in the treasury but the contract would be responsible for knowing how much belongs to slice and how much belongs to bob.

balance alice: 100 balance bob: 50 balance contract: 150 <= ethereum knows that

Many cases require the contract to keep an eye on user balances (like an ATM) because knowledge of the total funds inside is insufficient for the internal logic, i.e. how much is alive allowed to withdraw?

You have no internal accounting requirement because you want all money to go to the owner. Here's a simple implementation based on your description of the goal.

pragma solidity 0.7.6;

contract Collect {
    
    address public owner;
    
    constructor() {
        owner = msg.sender;
    }
    
    function deposit() external payable {
        require(msg.value == 2 ether, "please send two ether");
    }
    
    function withdraw() external {
        require(msg.sender == owner, "No");
        msg.sender.transfer(address(this).balance);
    }
    
    // this is observable without help from the contract, could be left out or included as a courtesy
    
    function balance() external view returns(uint balanceEth) {
        balanceEth = address(this).balance;
    }
}

Hope it helps.

Related Topic