1

I'm a newbie at ethereum development (which I'm very enthusiastic about) and I'm trying very hard to create my first smart contract.

It's a test contract to bet on horses race.

I'm currently facing an issue that I failed to solve yet.

1) I can't find to way to log the event triggered to debug my code

2) When I initialize my Race struct, the horsesRunningTheRace doesn't seem to be properly set. It tried several ways but no success so far.

Here is my code so far (I simplified and translated it to focus at the issues):

My contract :

contract HorseRacesBet {

    struct Race {
        uint raceId;
        uint stakesSum;
        bool isOver;
        bool areBetsForbidden;
        uint32[] horsesRunningTheRace;
    }

    address public owner = msg.sender;

    uint courseIDGenerator = 0;
    mapping (uint => Race) races;

    modifier ownerOnly()
    {
        if (msg.sender != owner)
            throw;
        _
    }

    event InitRace(uint32[] horsesRunningTheRaceParam);

    function initRace(uint32[] horsesRunningTheRaceParam) ownerOnly returns(uint) {
        InitRace(horsesRunningTheRaceParam);
        races[courseIDGenerator].raceId= courseIDGenerator;
        races[courseIDGenerator].stakesSum=100;
        races[courseIDGenerator].isOver=false;
        races[courseIDGenerator].areBetsForbidden=false;
        for(uint x= 0; x< horsesRunningTheRaceParam.length; x++ ){
           races[courseIDGenerator].horsesRunningTheRace.push(horsesRunningTheRaceParam[x]);
        }
        courseIDGenerator++ ;
        return races[courseIDGenerator].raceId;
    }

    event GetRaceInfos(uint raceId);

    function getRaceInfos(uint raceIdParam) public returns(uint, uint, bool, uint32[], bool){
       GetRaceInfos(raceIdParam);
       return (races[raceIdParam].raceId, races[raceIdParam].stakesSum, races[raceIdParam].isOver, races[raceIdParam].horsesRunningTheRace , races[raceIdParam].areBetsForbidden);
    }
}

The Javascript Mocha test file :

contract('HorseRacesBet', function(accounts) {

    it("should keep a Race struct in the storage on initRace call", function() {
        var horseBetContract = HorseRacesBet.deployed();
        var horsesRunningTheRace = [10, 20, 30];

        horseBetContract.allEvents(function(error, result) {
            // This will catch all Transfer events, regardless of how they originated.
            console.log('event log');
            if (error == null) {
                console.log(result.args);
            }
        });

        horseBetContract.initRace.call(horsesRunningTheRace).then(function(raceId) {
            assert.equal(raceId.valueOf(), 0, "L'id de la course should be 0'");

            horseBetContract.getRaceInfos.call(raceId).then(function(raceDatas){
                assert.equal(raceDatas[0], 0, "The raceId returned should be 0");
                assert.equal(raceDatas[1].valueOf(), 0, "The sum of all bets should be 0.");
                assert.equal(raceDatas[2], false, "The race shouldn't be over");
                for(var i = 0 ; i< raceDatas[3].length; i++){
                    console.log(raceDatas[3][i].valueOf());
                }
                assert.equal(raceDatas[3], horsesRunningTheRace, "The horses running the race should be the one we initialized the race with.");
                assert.equal(raceDatas[4], false, "The bets shouldn't be closed on the race.");
            });
        });
    });
});

And the output of the test:

/usr/local/lib/node_modules/truffle/lib/test.js:322
throw reason;
^
AssertionError: The horses running the race should be the one we initialized the race with.: expected [] to equal [ 10, 20, 30 ]
at /Users/user/Documents/formation/nigthclazz-ethereum/truffle-project/horse-bet/test/horseRacesBet.js:24:16
at process._tickDomainCallback (internal/process/next_tick.js:129:7)

Can anyone point me to what I'm obviously missing here?

0

For your first point, I'm used to declare the fromBlock argument to retrieve all events from the genesis :

horseBetContract.allEvents({ fromBlock: 0 }, function(error, data) { 
    console.log(data); 
});

Otherwise, according to the Truffle official documentation, you could try to use watch (never tried)

horseBetContract.InitRace({fromBlock: "latest"}).watch(function(error, data) { 
    console.log(data); 
});

For the second point, I changed a couple of things in your test to make it work. You contract was fine. Please find below the explanation :

horseBetContract.allEvents({ fromBlock: 0 }, function(error, result) {
        // This will catch all Transfer events, regardless of how they originated.
        console.log('event log');
        if (error == null) {
            console.log(result.args);
        }
});

horseBetContract.initRace(horsesRunningTheRace).then(function(transactionId) {
    console.log("transactionId="+transactionId);

    horseBetContract.getRaceInfos.call(0).then(function(raceDatas){

        assert.equal(raceDatas[0], 0, "The raceId returned should be 0");

        assert.equal(raceDatas[1].valueOf(), 100, "The sum of all bets should be 100.");

        assert.equal(raceDatas[2], false, "The race shouldn't be over");

        var horsesRunningTheRaceParam = [];
        for(var i = 0 ; i < raceDatas[3].length; i++){
            horsesRunningTheRaceParam.push(Number(raceDatas[3][i]));
        }
        assert.deepEqual(horsesRunningTheRaceParam, horsesRunningTheRace, "The horses running the race should be the one we initialized the race with.");

        assert.equal(raceDatas[4], false, "The bets shouldn't be closed on the race.");
    });

});
  1. You need to call initRace function with horseBetContract.initRace(args) instead of horseBetContract.initRace.call(args) because it's not a constant function but a writing function.

  2. The promise of this function returns the transaction ID (hash) : then(function(transactionId) {

  3. In your contract,stakesSum is initialized to 100 and not 0, so your test should be : assert.equal(raceDatas[1].valueOf(), 100, "The sum of all bets should be 100.");

  4. raceDatas[3] returns an array of BigInteger (web3 feature), so I transformed it to a classic number array and made a deep comparison :

        var horsesRunningTheRaceParam = [];
        for(var i = 0 ; i < raceDatas[3].length; i++){
            horsesRunningTheRaceParam.push(Number(raceDatas[3][i]));
        }
        assert.deepEqual(horsesRunningTheRaceParam, horsesRunningTheRace, "The horses running the race should be the one we initialized the race with.");
    

And now the result is correct

  Contract: HorseRacesBet
    ✓ should keep a Race struct in the storage on initRace call


  1 passing (1s)

transactionId=0x2ae252ae144144f2d1db832ba2158ca4ac87861966557d06391265b7e0d91ac6
event log
{ horsesRunningTheRaceParam:
   [ { [String: '10'] s: 1, e: 1, c: [Object] },
     { [String: '20'] s: 1, e: 1, c: [Object] },
     { [String: '30'] s: 1, e: 1, c: [Object] } ] }

Good luck for your learning.

Salut ;)

  • I spent my week-end banging my head against the wall with this one :). You're a life saver. – Benjamin Fontaine Oct 17 '16 at 12:18
  • You're welcome. My pleasure helping you out. – Greg Jeanmart Oct 17 '16 at 12:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.