I am trying to get my smart contract to transfer all its balance to another address. The transfer line doesn’t throw any errors but the balance of contract does not change afterwards.
I am using web3js with ganache to test this function:
My contract:
// SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.12; contract Lottery { address payable public manager; address payable[] public players; constructor() { manager = payable(msg.sender); } function enterLottery() public payable { require(msg.value >= .01 ether); players.push(payable(msg.sender)); } function getPlayers() public view returns (address payable[] memory) { return players; } function random() public view returns (uint256) { return uint256( keccak256( abi.encodePacked(block.difficulty, block.timestamp, players) ) ); } function pickWinner() public { // this transfer contract balance to the account uint256 index = random() % players.length; players[index].transfer(address(this).balance); } }
My test case:
beforeEach(async () => { accounts = await web3.eth.getAccounts(); contract = await new web3.eth.Contract(abi) .deploy({ data: evm.bytecode.object }) .send({ from: accounts[0], gas: "1000000" }) }) describe("Lottery", () => { it("Contract has an address? ", () => { assert.ok(contract.options.address) }) it("Prize pool can receive ether", async () => { await contract.methods.enterLottery().send({ from: accounts[1], gas: "1000000", value: "10000000000000000" }); const contractBalance = await web3.eth.getBalance(contract.options.address) const hasContractReceivedEntry = contractBalance === "10000000000000000"; assert.equal(hasContractReceivedEntry, true) }) it("Winner can receive the prize pool", async () => { await contract.methods.enterLottery().send({ from: accounts[1], gas: "1000000", value: "10000000000000000" }); await contract.methods.pickWinner().call(); const contractBalance = await web3.eth.getBalance(contract.options.address) console.log(contractBalance) // the contract balance should be 0 after the pickWinner call, but it is still 10000000000000000 wei the enterLottery function gave }) })
Edit: It is confirmed that the smart contract can run enterLottery and random() as intended
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
await contract.methods.pickWinner().call();
On this line, you’re invoking a read-only call that doesn’t update the contract state. You need to send a transaction using the .send()
function – just like on the previous line.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0