0

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.

0

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.

6
  • Thank you Rob, you are correct. I made some incorrect assumptions about the Solidity material I was consuming. In Python, the function structure is just a matter of organization and doesn't execute anything in and of itself. It appears with Solidity, some of these functions external parameters like "payable"? actually executes some functionality. I will continue to study.
    – Argon
    Apr 21 at 22:33
  • payable is a function modifier that makes it acceptable to send ether to the function, along with data (input arguments). The default is to reject the transaction if msg.value > 0. This is to prevent money from arriving at a function that isn't expecting it because that could result in funds that are not accounted for, which could be impossible to withdraw, for example: require(amount <= balance[msg.sender] looks okay, but it implies that funds were added to balance when they arrived. Unexpected funds would be trapped. Apr 21 at 22:40
  • So what part of the deposit() function actually executes a transfer from msg.sender to the contract address?
    – Argon
    Apr 22 at 4:27
  • Nothing. The signed transaction has two similar parts, data and value. The data would be unpacked and mapped to input arguments. The attached funds, if any are not data. It's money. Consider sendTransaction({from: me, to: contract, data: args, value: ether}) where those values are addresses, a bytes array, and ether to send from the sender's account. The payable modifier allows it receive funds (otherwise it would revert when msg.value > 0. The money is already there, and if it's exactly 2 ether per your spec, then there is nothing else to do. Apr 22 at 4:41
  • I see. I presume there is some particular reason for that, which I haven't yet encountered. It seems to me more straightforward to have all transactions behave in the same way that you scripted with msg.sender.transfer(address(this).balance); <- That line is very coherent, straightforward, and in alignment with typical coding structure. Thanks again.
    – Argon
    Apr 22 at 5:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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