5

This is a contract I made when the latest version of solidity was 0.4.0, it was working then, but now it shows error in Remix, so I updated it to 0.5.0. Now it shows errors in the transfer function and keccak256 function.

The errors are:

Typeerror: member balance not found or not visible argument-dependent lookup in contractLottery. Use "address(this).balance" to access this address member.players[index].transfer(this.balance);

TypeError: Wrong argument count for function call: 3 arguments given but 
expected 1. This function requires a single bytes argument. Use 
abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) 
to use ABI encoding.
return uint(keccak256(block.difficulty,now,players));

CONTRACT

pragma solidity ^0.5.0;

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

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

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

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

    function winner() public restricted {
        uint index = random() % players.length;
        players[index].transfer(this.balance);
        players = new address[](0);
    }

    function allplayers() public {
        return players;
    }

    modifier restricted() {
        require(msg.sender == manager);
        _;
    }
}
2
  • Be careful with your random() it's highly predictable, you could generate a function that calculates random() % players.length and call winner() only when he is the winner Commented Nov 27, 2018 at 13:05
  • Better to use Oracle for random number. More safe and accurate. Commented Nov 27, 2018 at 14:33

5 Answers 5

9

Please see Solidity v0.5.0 Breaking Changes.

As pointed out here:

The functions .call(), .delegatecall(), staticcall(), keccak256(), sha256() and ripemd160() now accept only a single bytes argument.

This:

uint(keccak256(block.difficulty,now,players))

...must become this:

uint(keccak256(abi.encodePacked(block.difficulty,now,players)))

In addition, as pointed out here:

Contract types do not include address members anymore in order to separate the namespaces. Therefore, it is now necessary to explicitly convert values of contract type to addresses before using an address member. Example: if c is a contract, change c.transfer(...) to address(c).transfer(...), and c.balance to address(c).balance.

So this:

players[index].transfer(this.balance);

...must become this:

players[index].transfer(address(this).balance);

Finally you need to go and mark address [] public players to payable like so:

// here
address payable[] public players;
...
// here
players=new address payable [](0);
...
// and here
function allplayers() public view returns(address payable[] memory) {

Note: added memory to the return parameter as it says in docs here:

Explicit data location for all variables of struct, array or mapping types is now mandatory. This is also applied to function parameters and return variables.

Let me know if that was helpful! 😊

1

return uint(keccak256(abi.encodePacked(block.difficulty, block.timestamp, players)));try this way as keccak256 now require only one arg of encodePacked

0

As you can see in the change log of new solidity version 0.5.0, many things changed. https://solidity.readthedocs.io/en/v0.5.0/050-breaking-changes.html

So, From your error, it seems the address type is not explicitly converted.

Which means rather than using a contract variable directly in your function, you need to convert this.balance to:

address(this).balance
0

The error messages are pretty clear.

ERROR 1 - Transfer

The problem with transfer is that the new version of solidity require that the addresses are marked as payable otherwise you cannot send money to "unpayable" addresses. So you have to change the declaration:

address payable[] public players;

Moreover in function winner you have to change the constructor:

players=new address payable[](0);

Since you marked players as input you don't need the function allplayers.

As already pointed out by Yogesh you have to change this.balance to address(this).balance

ERROR 2 - KECCAK256

Apparently the signature of function change, it require a single bytes input. So you have to transform the input of the function into a byte array.

0

Errors are quite self explanatory.

Typeerror: member balance not found or not visible argument-dependent lookup in contractLottery. Use "address(this).balance" to access this address member.players[index].transfer(this.balance);

As per the new 0.5.0 version: it is now necessary to explicitly convert values of contract type to addresses before using an address member. Example: if c is a contract, change c.transfer(...) to address(c).transfer(...), and c.balance to address(c).balance.

TypeError: Wrong argument count for function call: 3 arguments given but expected 1. This function requires a single bytes argument. Use abi.encodePacked(...) to obtain the pre-0.5.0 behaviour or abi.encode(...) to use ABI encoding. return uint(keccak256(block.difficulty,now,players));

New version suggests : Change every keccak256(a, b, c) to keccak256(abi.encodePacked(a, b, c)).

I hope it answers your question. You see the complete changelog explained here.

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.