My Getter doesn't get

I need help debugging what seems like a simple thing:

My Migrator code:

const CoinFlip = artifacts.require("CoinFlipWager");

module.exports = function(deployer, network, accounts) {
    deployer.deploy(CoinFlip).then((instance) => {
        instance.setHouseAddress(accounts[2]);
    });
};

My main.js code, although only concerned at this point about ‘mydebug()’ output, which I call after jQuery doc-ready is done, as I want to see if I’m setting my ‘House’ address & my ‘Bettor’ address.

Heres what I think I’m doing:
1 - migrator sets ‘house’ address to accounts[2] via ‘setter’
2 - sol contract has getBetter and getHouse and setHouse methods
3 - main.js - after instance is returned, I call an initialize function which calls mydebug function, which simply console logs these 2 addresses after calling getter methods

BUT, the console logs show addresses as ‘null’

I’m struggling to figure out why this is.

var web3 = new Web3(Web3.givenProvider);

// Declare var we will load contract instance to
var contractInstance;
var bettorEthAddress;
var houseEthAddress;

// Create a contract instance in Javascript so we can interact with it - replicates contract instance in blockchain
//  by wrapping in some javascript magic so we can then call functions in contract
// Web3 has helper functions for this

$(document).ready(function() {
    // This brings up box for user permission for web page to access MetaMask
    // Returns a promise, so when permission granted, we can do our thing
    // 'Accounts' is an array of address supplied by MetaMask - will be the main address used by MetaMask

    // 'abi' is available after contract is deployed in truffle
    //  go into project, build folder, and look for json file and within this config, near top, you will
    //   see 'abi' array -- copy the whole thing!!
    //    - create new file in dapp folder called 'abi.js' and assign to var there
    //  for 'address', redeploy (migrate --reset from truffle console), and in the output of that,
    //    copy 'contract address:'
    //  'accounts[0]' is the address of whomever is using the contract
    window.ethereum.enable().then((accounts) => {
        // assign contract address for CoinFlipWager.sol we get after compile
        let contractAddress = '0xAded911ECAFaC9Fc8b44ed8f059aF1ec53D76c7D';

        console.log('STEP 1 - main.js - enable function in doc ready');
        console.log('accounts');
        console.log(accounts);

        // create new contract instance
        contractInstance = new web3.eth.Contract(abi, contractAddress, {from: accounts[0]});
        console.log('Contract Instantiated');
        console.log(contractInstance.methods);

        initialize();
    });

    // Click Handler for submitting form to flip the coin to win or lose amount wagered
    $("#flip").click(flipCoin);

    $('#betOption').focus(() => {
        $('#status-msg').html("");
    })

    $('#wagerAmount').focus(() => {
        $('#status-msg').html("");
    })

    $('#flip').click(flipCoin);

});

function mydebug() {
    console.log('In My Debug');
    houseEthAddress = contractInstance.methods.getHouseAdr().call().then((result) => {
        console.log('Get House Result is = ' + result);
        return result;
    });
    bettorEthAddress = contractInstance.methods.getBettorAdr().call().then((result) => {
        console.log('Get Bettor Result is = ' + result);
        return result;
    });
}

// Get's balances of the 'house' and 'bettor' (contract user) addresses
//  Updates screen using jquery
//  Also returns balances for using contracts
async function getBalances(houseWalletAddress, bettorAddress) {
    let houseBalance = '';
    let bettorBalance = '';

    // get the house balance
    await web3.eth.getBalance(houseWalletAddress, (error, result) => {
        if (!error) {
            houseBalance = parseFloat(web3.utils.fromWei(result, "ether"));
        }
        $('#display-house-balance').html(houseBalance + ' ETH');
    });

    await web3.eth.getBalance(bettorAddress, (error, result) => {
        if (!error) {
            bettorBalance = parseFloat(web3.utils.fromWei(result), "ether");
            $('#display-bettor-balance').html(bettorBalance + ' ETH');
        }
    });

    return {houseBalance: houseBalance, bettorBalance: bettorBalance}
}

function flipCoin() {
    let validated = true;
    let betOption = $("#betOption option:selected").val();
    let betAmount = $('#wagerAmount').val() > 0 ? $('#wagerAmount').val() : "0";

    console.log ("STEP 2 - Main.js flipCoin function");

    // Validate Input
    if (betOption === 'choose' || betAmount === 0) {
        $('#status-msg').html("You must select 'Heads/Tails' & wager an amount > 0");
        validated = false;
        console.log('changing validated to false 1');
    }

    // Get bettorAccount
    console.log('bettor addr');
    console.log(bettorEthAddress);
    console.log('house addr');
    console.log(houseEthAddress);

    // Get balances to re-verify
    preBetBalances =  getBalances(houseEthAddress, bettorEthAddress);
    console.log('pre bet bal');
    console.log(preBetBalances);
    console.log('bet amount = ' + betAmount);
    // verify balances
    if (betAmount > preBetBalances.houseBalance || betAmount > preBetBalances.bettorBalance) {
        $('#status-msg').html("You can't bet more than either your balance or the house balance");
        validated = false;
        console.log('changing validated to false 2');
    }

    // json object arg for send
    let config = {
        house: address[2],
        betOption: betOption,
        betAmount: web3.utils.toWei(betAmount, "ether"),
    }

    console.log ("STEP 3 - Main.js flipCoin function - about to call placeWager contract method");
    console.log('validated  = ' + validated);
    if (validated) {
        console.log('config = ');
        console.log(config);
    }
}

async function initialize() {
    await mydebug();
}

My Solidity code

import "./Ownable.sol";
pragma solidity 0.5.12;

contract CoinFlipWager is Ownable{

    //TODO - look at migrator in genesis project
    //  1 - DONE -- setHouseAddress() method in this contract
    //  2 - DONE -- in the migrator, set it to accounts[2]
    //  In placeWager, pass in betAmount, betOption, return flip result (as a string), winner, loser, payout
    //  In placeWager, call flip(), then -> if betOption == flip result, figure out how to take money and pay money
    //     in solidity docs, there is a 'Withdrawal' example to use (don't use transfer directly) and my evernote notes
    //  After working, add requires & asserts - rewatch solidity 101 videos  for all of it, starting with events!!!!!!!!
    //    events is last section in Additional Solidity concepts

    // Vars
    address bettor;
    address house;

    // Based on coin flip result, we will assign above to addresses as winner & loser
    mapping (address => uint) winner;
    mapping (address => uint) loser;

    // Lets assign the addresses
    constructor() public payable {
        address bettor = msg.sender;
    }

    // Getters
    function getBettorAdr() public view returns(address) {
        return bettor;
    }
    function getHouseAdr() public view returns(address) {
        return house;
    }

    // Setters
    // In migration file, we set houseAdr to be accounts[2], from our ganache block of adrs
    function setHouseAddress(address houseAdr) public {
        address house = houseAdr;
    }


    // Coin flip
    //  0 - heads
    //  1 - tails
    function flip() public view returns (uint) {
        return now % 2;
    }
}

Have you tried adding async... await where you set the house address in the deploy function? This is the only thing I’m seeing at the moment related to your question.

I also noticed something that could be separate problem. In the contract solidity code you assign the bettor address inside the contract constructor:

 // Lets assign the addresses
    constructor() public payable {
        address bettor = msg.sender;
    }

In this context msg.sender is the contract owner who deployed the contract. A regular user placing bets would not be deploying the contract. The contract gets deployed once by the owner, then gets used my times by many different players who place the bets.

1 Like

Hi @freedomfflow

Why are you declaring a new local bettor and house variable ?

Lines 25 and 39 of your smart contract ?

You should remove the address here if you want to use your contract storage variable.

   // Lets assign the addresses
   constructor() public payable {
       bettor = msg.sender;
   }

The same here is you want to use your contract storage and not a local variable

    function setHouseAddress(address houseAdr) public {
        house = houseAdr;
    }