Array initialization problem and event logging with Truffle

benjifontainebenjifontaine Posts: 1Member
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);
}
});
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 ?

Thanks a lot.
Benjamin


Comments

  • robhitchensrobhitchens Posts: 3Member
    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)
    throw;
    _;
    }

    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;
    raceIndex.push(raceId);
    LogInitRace(raceId);
    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
    raceStructs[raceId].raceHorses.push(horseId);
    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.