2

I've been working on the concept of building a MUD type game using Blockchain as the data storage. Note - this is a private network - so ether cost is not really a huge issue for me.

Given a contract that looks like this:

contract EtherWorldStorage {
    /* Constructor */
    address owner;
    mapping (bytes32 => World) Gameworlds;

    mapping (bytes32 => uint) NamesIndex;
    World[] worldContracts;

    function EtherWorldStorage(){
        owner = msg.sender;
    }


    event WorldCreated(bytes32 indexed worldName, address indexed sender, address result );

    function createWorld(bytes32 name) returns (address a){
        if(NamesIndex[name] > 0x0){
            return 0x0;
        }
        World w = new World(name);
        NamesIndex[name] = worldContracts.length - 1;
        Gameworlds[name] = w;
        WorldCreated(name,msg.sender,w);
        return w;
    }

  function getWorldCount() returns (uint i){
        return worldContracts.length;
    }

    function destroyWorld(bytes32 world){

        World w = Gameworlds[world];
        w.destroy(owner);
    }


function getItemPossessorsInventory(InventoryItem item) returns (address a){
        return item.getOwningInventory();
    }

}

When I call the createWorld function from nethereum - I can see the transaction going in, I wait for the mining to complete, but my event is never fired?

Is what I am doing to complex for ethereum? Note - the World contract then instantiates an Area contract, which then instantiates a Door object.

I am estimating the gas price by nethereums var callResult = f.EstimateGasAsync(args).Result;

Where f is the function call.

My .Net code in nethereum looks like this:

public static string CreateWorld(string world)
        {
            var web3 = new Web3(Resources.Server);
            var result = web3.Personal.UnlockAccount.SendRequestAsync("0x54a222aE3d59EF92D715409f31C6eCAf331D0782", Resources.Password, 30).Result;
            if (result != true)
            {
                throw new Exception("Unable to unlock account...");
            }




            var d = Encoding.UTF8.GetBytes(world);


            string address = "0x30d578718e1da379f4B1B1ac5E9be9ba646E0bCF"; // Contract address
            var contract = web3.Eth.GetContract(Resources.ContractInterface2, address);

            var add = contract.GetFunction("createWorld");                         // Add method
            var worldCreatedEvent= contract.GetEvent("WorldCreated");
            var filterAll = worldCreatedEvent.CreateFilterAsync().Result;
            var totalGas = new HexBigInteger(GetGasPrice(add, d).Value*2);

            HexBigInteger gasPrice = new HexBigInteger(new BigInteger(0.144));

            var callResult = add.SendTransactionAsync("0x54a222aE3d59EF92D715409f31C6eCAf331D0782", totalGas,new HexBigInteger(0), d);
            var theResult = GetReceiptAsync(web3, callResult.Result);
            var log = worldCreatedEvent.GetAllChanges<dynamic>(filterAll).Result;


            return log[0].Event;
            return callResult.Result;
        }

No matter what, my log always ends up with 0 elements in it, and even using Ethereum Wallet - I don't see any contract events being raised.

Suggestions?

1

I think I got it sorted- I think I was calling GetAllChanges on the function instead of the event.

In any case- I can see the events being raised now. I added in

event RequestReceived(string s);

So I could track how far in the contract functions the execution was getting to.

0

In case it helps, there is a pattern over here: Is There a Simple Contract Factory Pattern?

I think you'll find more clarity by focusing on the data structure first. This "factory" will make Worlds, so all that's required is an index to the Worlds (and events, etc.)

address[] public worldList;

You can build the index as you go:

World newWorld = new World(name);
return worldList.push(newWorld);

To support your delete function, you will need to know which row in worldList each World address lives on, so modify the mapping slightly:

mapping(address => uint) worldPointer;

and modify the new world process slightly:

worldPointer[newWorld] = worldList.push(newWorld) - 1; // because it returns the array length

That way, worldPointer[world] will give you the row to delete from worldList when you destroy a world.

There's a more complete explanation of a proper delete from an arbitrary row in an array over here: https://medium.com/@robhitchens/solidity-crud-part-2-ed8d8b4f74ec

Hope it helps.

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.