I have below smart contract and a test program to test transfer ETH out of contract address, but contract’s ETH balance not changed. I tested withdrawAmount(uint256 amount) but the assertion error occurred. I also use msg.sender.transfer(getBalance()); this work will transfer all balance out of contract, but I want to transfer with my amount with withdrawAmount(uint256 amount) function. How does msg.sender.transfer(amount) work in solidity0.6.10? How can I transfer the ETH’s amount from contract’s address?

$ truffle version
Truffle v5.1.26 (core: 5.1.26)
Solidity - 0.6.10 (solc-js)
Node v10.20.0
Web3.js v1.2.1


 // SPDX-License-Identifier: MIT
 pragma solidity >=0.4.21 <0.7.0;
 contract ContractBalanceTest {
     address public owner;
     constructor() public payable {
         owner = msg.sender;
     modifier onlyOwner () {
       require(msg.sender == owner, "This can only be called by the contract owner!");
     function deposit() payable public {
     function depositAmount(uint256 amount) payable public {
         require(msg.value == amount);
     function withdraw() payable onlyOwner public {
     function withdrawAmount(uint256 amount) onlyOwner payable public {
         require(msg.value == amount);
         require(amount <= getBalance());
         msg.sender.transfer(amount); //this not work
         //msg.sender.transfer(getBalance()); // this ok
     function getBalance() public view returns (uint256) {
         return address(this).balance;

#test code

 var ContractBalance  = artifacts.require('ContractBalanceTest');
 contract('test contract balance with eth', function (accounts) {
   let contract, balance;
   before(async function () {
     contract  = await ContractBalance.new({from: accounts[0]});
     balance   = await contract.getBalance();
     console.log('ContractBalanceTest ', contract.address, balance.toString());
   describe('#deposit', function () {
     it('test deposit', async function () {
       let one_eth = web3.utils.toWei("1", "ether");
       let tx = await contract.depositAmount(one_eth, { from: accounts[1], value : one_eth});
       let b = await contract.getBalance();
       console.log('ContractBalanceTest ', contract.address, b.toString());
       assert.equal( b.toString(), "1000000000000000000", "the contract's balance should be 1 ether");
   describe('#withdraw', function () {
     it('test withdraw', async function () {
       let half_eth = web3.utils.toWei("0.5", "ether");
       let tx = await contract.withdrawAmount(half_eth, { from: accounts[3], value : half_eth});
       //let tx = await contract.withdraw({ from: accounts[0], value : half_eth});
       let b = await contract.getBalance();
       console.log('ContractBalanceTest ', contract.address, b.toString());
       assert.equal( b.toString(), "500000000000000000", "the contract's balance should be 0.5 ether" );

#test result

  Contract: test contract balance with eth
ContractBalanceTest  0xb7Ff5FB586177E7F489B956e7b218CdeB731B319 0

ContractBalanceTest  0xb7Ff5FB586177E7F489B956e7b218CdeB731B319 1000000000000000000
      ✓ test deposit (131ms)
ContractBalanceTest  0xb7Ff5FB586177E7F489B956e7b218CdeB731B319 1000000000000000000
      1) test withdraw

    Events emitted during test:

      amount: <indexed> 500000000000000000 (type: uint256)


  1 passing (508ms)
  1 failing

  1) Contract: test contract balance with eth
         test withdraw:

      the contract's balance should be 0.5 ether
      + expected - actual

      at Context.<anonymous> (test/test_contract_balance.js:34:14)
      at process._tickCallback (internal/process/next_tick.js:68:7)
  • The comments in function withdrawAmount depict an impossible scenario! Please check again and make sure what the function really reverts on. – goodvibration Jul 2 at 4:13
  • @goodvibration I checked whether the transaction is reverted, the transaction is ok and the hash created, no error catched in assertion test.I use msg.sender.transfer(getBalance()) the balance transfered out. – kinjia Jul 2 at 5:26
  • You have 4 lines in this function. The comments there suggest that the function completes successfully when executing only lines [1,2,4], and that the function reverts when executing only lines [1,2,3]. This depicts an impossible scenario! – goodvibration Jul 2 at 5:58
  • And BTW, if amount is equal to msg.value, then it is definitely going to be <= address(this).balance, because msg.value is always <= address(this).balance. So line 2 in that function is obviously redundant. – goodvibration Jul 2 at 6:02
  • @goodvibration If I understand correctly . require(msg.value == amount); // check the the transaction ETH value whether equal the function(code)'s parameter require(amount <= getBalance()); // this is check the contract's balance so no redundant problem. – kinjia Jul 2 at 6:15

remove payable keyword, and remove value from test code

    //remove payable and msg.value
    function withdrawAmount(uint256 amount) public {
         require(amount <= getBalance());
         emit Transfer(amount);
     //remove value field
     let tx = await contract.withdrawAmount(half_eth, { from: accounts[1] });

| improve this answer | |

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.