Solidity, Member "transfer" not found or not visible after argument-dependent
Asked Answered
B

4

6

Using Solidity ^0.5.0, I'm actually trying to implement an old code working in ^0.4.17, but it throws an error on Remix. I checked syntax and everything but just can't catch what's wrong. Any help highly appreciated.

pragma solidity ^0.5.0;

contract Lottery{
  address public manager;
  address[] public players;

  constructor() public {
      manager = msg.sender;
  }

   function participate() public payable {
       require(msg.value > .01 ether);
       players.push(msg.sender);
  }

   function pseudoRandom() private view returns(uint){
    return uint(keccak256(abi.encodePacked(block.difficulty, now, players)));
  }

  function pickWinner() public {
    uint index = pseudoRandom() % players.length;
    players[index].transfer(address(this).balance);
  }
}

Here is the error message:

browser/Lottery.sol:22:8: TypeError: Member "transfer" not found or not visible after argument-dependent lookup in address.

players[index].transfer(address(msg.sender).balance);

^---------------------^

Blatherskite answered 27/11, 2018 at 12:42 Comment(0)
D
7

Please see Solidity v0.5.0 Breaking Changes.

As pointed out here:

The address type was split into address and address payable, where only address payable provides the transfer function.

See my answer here for more details.

Change this line:

address[] public players;

To this:

address payable[] public players;

EDIT

Thanks smarx! 😄

Dannettedanni answered 27/11, 2018 at 13:19 Comment(1)
This answer was accepted, but I don't think it's the actual issue in the above code. players[index] was already an address, so casting it doesn't do anything. I believe the actual issue is that the type is address rather than address payable. The fix would be to use address payable[] public players.Stratiform
C
3

You are missing the payable modifier on the initial declaration. Change

address[] public players;

to

address payable[] public players;

Chaechaeronea answered 28/11, 2018 at 2:13 Comment(0)
P
0

As far as I understood from your contract's business logic, all addresses enter the lottery wouldn't win a price, so you don't need to make all addresses payable. Better way is making only the winner address payable by casting address type to a payable address as below.

    address payable winnerAddress = payable(players[index]);
    winnerAddress.transfer(address(this).balance);
Pifer answered 7/1, 2022 at 15:8 Comment(0)
N
0

This is how overall contract code looks like

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.9;

contract Lottery {
    address public manager;
    address payable[] public players;
    
    constructor() { }

    function lottery() public {
        manager = msg.sender;
    }

    function enter() public payable {
        require(msg.value > .01 ether);
        players.push(payable(msg.sender));
    }

    function random() public view returns (uint8) {
        return uint8(uint256(keccak256(abi.encodePacked(block.timestamp, block.difficulty, players)))%251);
    }

    function pickWinner() public {
        uint index = random() % players.length;
        players[index].transfer(address(this).balance);
    }
}
Naquin answered 6/2, 2022 at 10:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.