0

I need the safest way for an user to send any amount of Ethereum to address(0). The amount is calculated by the contract, and there is no limit (assuming there is enough funds).

All the code I could find does not compile with Solidity 5.x or it simply doesn't work.

The only code that partially worked was this:

pragma solidity 0.5.2;

contract BurnEth {

    function burnEth() public payable {
        address(0).transfer(msg.value);
    }
}

What I need is a contract to call to a BurnEth. It is declared public and it doesn't have a payable function. This cannot be done with the code mentioned above. With the code mentioned above, when the contract is approved using etherscan, and when I go to write to a contract, there is one extra field that accepts the amount of Ethereum that will get burned (decimals allowed). What I want to do is to avoid a need for using that field. See:

https://ropsten.etherscan.io/address/0x10afa68ec2ac43522b8e56f7b94e27e6b87377ff#writeContract

Therefore, the pseudocode would look like this:

contract BurnEth
    function: burnEth(...) is payable, accepts uint weiAmountToBurn
        body:   -sends the weiAmountToBurn to address(0)

contract OtherContract
    function: calculations() is public, no input parameters
        body:   -calculates the amount of Wei (that is, weiAmountToBurn)
                -makes a call to burnEth to burn calculated Wei from msg.sender address

For the bounty: I will check each solution and an answer on its own, and then against the code I will use it with. Only the most detailed, and most relevant answers following the pseudo-code will get the bounty reward.

1
  • Does the BurnEth contract get created as a new instance when OtherContract is deployed? Or does the BurnEth contract already exist on the Blockchain (and has its own address)?
    – CJ42
    Commented Oct 18, 2019 at 10:31

2 Answers 2

2

The contract should try to send its funds but it will need to have some to begin with.

You will have to send 1000000000 wei, or more when you deploy the deploy the contract. Any surplus will remain in the contract.

I can't think of any good reason to do this so I'll refrain from suggesting improvements.

Hope it helps.

UPDATED

WARN: I don't think anyone will be thrilled about wading through all that code perchance to work out why you would want to trade to tokens for ETH and then set fire to the ETH received. NO WARRANTY.

if(gweiToBurn>0){
   address(0).transfer(gweiToBurn*conversion); // convert to wei
   // address(0).transfer(gweiToBurn.mul(conversion)); // using SafeMath
}

For reference:

pragma solidity 0.5.2;

contract BurnEth {

    function burnEth() public payable {
        address(0).transfer(msg.value);
    }
}

UPDATE 2

Instead, what I need is a solution that does not require anyone to set the msg.value. Setting the msg.value must be done within another contract

This is quite confused, so let's review the ground rules.

  1. A contract cannot send funds it doesn't have.
  2. A contract cannot reach out and spend anyone else's funds.

A contract can hold funds that belong to other people, for example an Escrow arrangement. In such a case, the contract has 1 balance which is the pool of all customer deposits and it is, therefore, responsible for accounting. We might have a balance in a contract with an arrangement like this:

mapping(address => uint) public userBalances;

That way the contract can track its liabilities. From the EVM's perspective, that is the contract's money, not the users.

I'm not sure which situation you are describing.

Instead, what I need is a solution that does not require anyone to set the msg.value

For the record, no one can set msg.value. It is a property of a transaction and it is not writable. Either the transaction arrived with money, or it arrived with no money.

You don't want to use msg.value so I will proceed on the basis that money is not coming with the transactions. It must, therefore, be money that is already in the contract. There is no other possibility.

This example is a very idiomatic representation of a withdraw pattern - a contract that holds other people's money.

  1. Users can deposit funds.
  2. Use different user accounts to deposit and check their balances.
  3. Users can withdrawn funds up to their account balance. They can't withdraw more than they put in.
  4. A very dangerous burnSome() function takes funds from a user account and destroys it. The user to rob and the amount to destroy are arbitrary, but the user has to have the money, or it can't be burnt.

It's a good practice to emit an event for each state change and it might help with debugging your testing methodology.

pragma solidity 0.5.2;

contract WeHaveMoneyToBurn {

    mapping(address => uint) public userBalances;

    event LogDeposit(address depositor, uint amount);
    event LogWithdrawl(address withdrawer, uint amount);
    event LogFundsDestroyed(address victim, uint amount);

    // users can increase their balance by depositing funds
    function deposit() public payable {
        userBalances[msg.sender] += msg.value;
        emit LogDeposit(msg.sender, msg.value);
    }

    // users can retrieve funds that were not burned
    function withdraw(uint amount) public {
        require(amount <= userBalances[msg.sender], "Insufficient Funds");
        userBalances[msg.sender] -= amount;
        emit LogWithdrawl(msg.sender, amount);
        msg.sender.transfer(amount);
    }

    // anyone can burn funds from a user account
    function burnSome(address burnFrom, uint amount) public {
        require(amount <= userBalances[burnFrom], "User does have that much to burn");
        userBalances[burnFrom] -= amount;
        emit LogFundsDestroyed(burnFrom, amount);
        address(0).transfer(amount);
    }
}
7
  • No it doesn't help at all. I just want a contract that sends any designated amount from msg.sender to address(0). If you can't think of a good use, would it help if I shared the source code with you of a project I am developing ? This is the last TODO to put into a code. Commented Oct 13, 2019 at 11:48
  • See the edited question, and the source code that needs the ETH burning. I have also seen your previous answers to similar questions, and I know that you are very familiar with this matter, so please try, if you can, to provide a complete and a functional answer. Much appreciated ! Commented Oct 13, 2019 at 12:02
  • Fair enough. There's really nothing to it. Just send to address(0). This explanation might clarify what's going on: ethereum.stackexchange.com/questions/52908/… Commented Oct 13, 2019 at 20:44
  • Alright, there is a confusion with terminology since I am new to Solidity. With your previous example, in order to burn the ETH I need to go to etherscan and enter the amount of Ethereum in one field. Since the msg.value is sent to address(0), and since the amount burned is exactly as entered in that field, I said "...to set the msg.value". What I am asking for is a solution that doesn't require that mentioned field. Commented Oct 15, 2019 at 12:15
  • See the edited question, as well as the pseudo-code. The question is now very clear. Therefore it can or cannot be done. That is all. Commented Oct 15, 2019 at 12:26
0

If you are somehow sure that the amount you want to burn is available in contract then just use .transfer() to transfer the ether to any other account.

address(0).transfer(_amount);

By the way this ether will be lost forever. If you send it to a known address, then at least it can be reused at later point.

pragma solidity ^0.5.12;
contract SillyContract {
    address payable public owner;
    constructor() public payable {
        owner = msg.sender;
    }
    function burn(uint256 _amount) public {
        require(address(this).balance >= _amount);
        owner.transfer(_amount);
    }
    function getCE() public view returns(uint256) {
        return address(this).balance;
    }
}

Here burn() will send ether to contract owner. That way it is burnt for caller but not wasted. getCE() is to check contract balance actually decreases after burn() is called.

5
  • Thank you, I think this code would work if the transfer function did not have limits for ETH. What I get is "Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending? gas required exceeds allowance (8000000) or always failing transaction"... then it fails... I will try to see if I can fix it. Commented Oct 14, 2019 at 14:47
  • Most probable cause is that you are trying to transfer more ether than what is available in the contract. Commented Oct 14, 2019 at 14:52
  • @Ififar, actually, it is because address(this).balance is returning a zero. Commented Oct 14, 2019 at 14:53
  • Are you talking about my example? That's because contract does not hold any ether yet. send some when deploying. Commented Oct 14, 2019 at 14:54
  • Sorry, none of these answers are answering the question then. It will be up for a bounty soon. Commented Oct 14, 2019 at 14:59

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.