简体   繁体   中英

Returned error: VM Exception while processing transaction: revert only owner can call this function

I'm trying to test this contract using "truffle test" but it show the following error: Error: Returned error: VM Exception while processing transaction: revert only owner can call this function - - Reason given: Only owner can call this function.

Question Open the TestGaming.sol contract in the test folder. Write a test for the function withdrawFunds. Your test should check the balance of the owner who called the withdrawFunds function. Your test should also verify if the owner's balance has increased by 10 ether.

Gaming.sol

pragma solidity ^0.5.0;

contract Gaming {
    /* Our Online gaming contract */
    address public owner;
    bool public online;

    struct Player {
        uint wins;
        uint losses;
    }

    mapping (address => Player) public players;

    constructor() public payable {
        owner = msg.sender;
        online = true;
    }

    modifier isOwner() {
        require(msg.sender == owner, "Only owner can call this function");
        _;
    }

event GameFunded(address funder, uint amount);
    event PlayerWon(address player, uint amount, uint mysteryNumber, uint displayedNumber);
    event PlayerLost(address player, uint amount, uint mysteryNumber, uint displayedNumber);

    function mysteryNumber() internal view returns (uint) {
        uint randomNumber = uint(blockhash(block.number-1))%10 + 1;
        return randomNumber;
    }

    function determineWinner(uint number, uint display, bool guess) public pure returns (bool) {
        if (guess == true && number > display) {
            return true;
        } else if (guess == true && number < display) {
            return false;
        } else if (guess == false && number > display) {
            return false;
        } else if (guess == false && number < display) {
            return true;
        }
    }

    function winOrLose(uint display, bool guess) external payable returns (bool, uint) {
        /* Use true for a higher guess, false for a lower guess */
        require(online == true, "The game is online");
        require(msg.sender.balance > msg.value, "Insufficient funds");
        uint mysteryNumber_ = mysteryNumber();
        bool isWinner = determineWinner(mysteryNumber_, display, guess);
        Player storage player = players[msg.sender];
        /* Player Won */
        if (isWinner == true) {
            player.wins += 1;
            msg.sender.transfer(msg.value * 2);
            emit PlayerWon(msg.sender, msg.value, mysteryNumber_, display);
            return (true, mysteryNumber_);
          /* Player Lost */
        } else if (isWinner == false) {
            player.losses += 1;
            emit PlayerLost(msg.sender, msg.value, mysteryNumber_, display);
            return (false, mysteryNumber_);
        }
    }
}

TestGaming.sol

pragma solidity ^0.5.0;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/Gaming.sol";

contract TestGaming {
    uint public initialBalance = 10 ether;
    Gaming gaming;
    address owner;

    function beforeAll() public {
        gaming = Gaming(DeployedAddresses.Gaming());
        owner = gaming.owner();

    }

    function testWithdrawFunds() public {
        uint ownerBalanceBefore = owner.balance;
        gaming.withdrawFunds();
        uint ownerBalanceAfter = owner.balance;

        Assert.equal (initialBalance, ownerBalanceAfter - ownerBalanceBefore, "The owner's balance should have increased by 10 ether");
}
function testPlayerWonGuessHigher() public {
        bool expected = true;
        bool result = gaming.determineWinner(5, 4, true);

        Assert.equal(expected, result, "The player should have won by guessing the mystery number was higher than their number");
    }

    function testPlayerWonGuessLower() public {
        bool expected = true;
        bool result = gaming.determineWinner(5, 6, false);

        Assert.equal(expected, result, "The player should have won by guessing the mystery number was lower than their number");
    }

    function testPlayerLostGuessLower() public {
        bool expected = false;
        bool result = gaming.determineWinner(5, 4, false);

        Assert.equal(expected, result, "The player should have lost by guessing the mystery number was lower than their number");
    }

    function testPlayerLostGuessHigher() public {
        bool expected = false;
        bool result = gaming.determineWinner(5, 6, true);

        Assert.equal(expected, result, "The player should have lost by guessing the mystery number was higher than their number");
    }
}

Error

在此处输入图像描述

The problem is that you are testing your contract through another contract. Since the function withdraw requires the caller to be the owner which is the deployer of the contract, the check fails since TestGaming.sol is calling the function; TestGaming.sol is not the deployer of the Gaming contract.

You have to instantiate the Gaming contract from inside the TestGaming contract.

pragma solidity ^0.5.0;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/Gaming.sol";

contract TestGaming {
    uint public initialBalance = 10 ether;
    Gaming gaming;
    address owner;

    function beforeAll() public {
    //---Instead of grabbing Gaming address, deploy it fresh for the test
        gaming = new Gaming();
        owner = gaming.owner();

    }

    function testWithdrawFunds() public {
        uint ownerBalanceBefore = owner.balance;
        gaming.withdrawFunds();
        uint ownerBalanceAfter = owner.balance;

        Assert.equal (initialBalance, ownerBalanceAfter - ownerBalanceBefore, "The owner's balance should have increased by 10 ether");
}

.
.
.

}

This way, TestGaming will be the deployer and thus owner for Gaming and the test will pass.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM