[Ethereum] Solidity Smart Contract withdrawal ETH with amount from contract address does not work

soliditysolidity-0.6.xtruffle-contract

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

#ContractBalanceTest.sol

 // 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 {
         msg.sender.transfer(address(this).balance);
     }
 
     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) {
   //console.log(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());
     console.log('');
   });
 
   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});
       //console.log(tx);
       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});
       //console.log(tx.logs);
       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

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

    Events emitted during test:
    ---------------------------

    ContractBalanceTest.Transfer(
      amount: <indexed> 500000000000000000 (type: uint256)
    )


    ---------------------------


  1 passing (508ms)
  1 failing

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

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

      -1000000000000000000
      +500000000000000000
      
      at Context.<anonymous> (test/test_contract_balance.js:34:14)
      at process._tickCallback (internal/process/next_tick.js:68:7)

Best Answer

remove payable keyword, and remove value from test code

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

Related Topic