Array initialization problem and event logging with Truffle

benjifontainebenjifontaine Member Posts: 1
Hi everyone,

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 seems to be properly set. It tried several ways but no success so far.

Here is my code so far:

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); } }); { assert.equal(raceId.valueOf(), 0, "L'id de la course should be 0'");{ 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 ?

Thanks a lot.


  • robhitchensrobhitchens Member Posts: 3
    I think the trouble starts with returning a dynamic array. As a general practice, I like to avoid For loops in contracts - keep the function cost knowable.

    From experience, a combination of array and struct makes an iterable data set without too much headache. I made it so you can iterate over the races and the horses in each race. Everything returned is of fixed length. The loopy stuff would go in the UI/tests. (It was prettier with indents :-)

    pragma solidity ^0.4.6;

    contract HorseRacesBet {

    struct RaceStruct {
    bytes32 raceId;
    uint stakesSum;
    bool isOver;
    bool areBetsForbidden;
    bytes32[] raceHorses;
    uint index; // point back to the raceIndex

    bytes32[] raceIndex; // a list of valid race Id

    address public owner = msg.sender;

    mapping (bytes32 => RaceStruct) raceStructs;

    modifier ownerOnly()
    if (msg.sender != owner)

    event LogInitRace(bytes32 raceId);
    event LogHorseAddedToRace(bytes32 raceId, bytes32 horseId);

    // use client-side Id generation such as uuid.

    function initRace(bytes32 raceId, uint stake) ownerOnly returns(bool success) {

    if(raceIndex[raceStructs[raceId].index] == raceId) throw; // this race Id already exists, so not allowed
    raceStructs[raceId].index = raceIndex.length;
    raceStructs[raceId].raceId = raceId;
    raceStructs[raceId].stakesSum = stake;
    return true;

    function getRaceCount() public constant returns (uint count) {
    return raceIndex.length;

    function getRaceIdAtIndex(uint index) public constant returns(bytes32 raceId) {
    return raceIndex[index];

    function addHorseToRace(bytes32 raceId, bytes32 horseId) returns(bool success) {
    if(raceIndex[raceStructs[raceId].index] != raceId) throw; // Not a known race Id, so not allowed
    LogHorseAddedToRace(raceId, horseId);
    return true;

    function getRaceHorseCount(bytes32 raceId) public constant returns(uint numberHorses) {
    return raceStructs[raceId].raceHorses.length;

    function getRaceHorseIdAtIndex(bytes32 raceId, uint index) public constant returns(bytes32 horseId) {
    return raceStructs[raceId].raceHorses[index];

    function getRaceInfo(bytes32 raceId) public constant returns(uint stakeSum, bool isOver, bool areBetsForbidden, uint raceIndex, uint horseCount){
    return (raceStructs[raceId].stakesSum, raceStructs[raceId].isOver, raceStructs[raceId].areBetsForbidden, raceStructs[raceId].index, getRaceHorseCount(raceId));
Sign In or Register to comment.