Creación de instancias de contrato a partir de métodos de contrato

He estado trabajando en el concepto de construir un juego tipo MUD usando Blockchain como almacenamiento de datos. Nota: esta es una red privada, por lo que el costo del éter no es realmente un gran problema para mí.

Dado un contrato que se ve así:

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();
    }

}

Cuando llamo a la función createWorld desde nethereum, puedo ver la transacción, espero a que se complete la extracción, pero mi evento nunca se activa.

¿Lo que estoy haciendo es complejo para ethereum? Nota: el contrato mundial luego instancia un contrato de área, que luego instancia un objeto de puerta.

Estoy estimando el precio del gas por nethereums var callResult = f.EstimateGasAsync(args).Result;

Donde f es la llamada a la función.

Mi código .Net en nethereum se ve así:

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;
        }

Pase lo que pase, mi registro siempre termina con 0 elementos, e incluso usando Ethereum Wallet, no veo que se genere ningún evento de contrato.

¿Sugerencias?

Respuestas (2)

Creo que lo solucioné. Creo que estaba llamando a GetAllChanges en la función en lugar del evento.

En cualquier caso, puedo ver los eventos que se plantean ahora. agregué

event RequestReceived(string s);

Entonces pude rastrear hasta dónde llegaba la ejecución en las funciones del contrato.

En caso de que ayude, aquí hay un patrón: ¿Existe un patrón de fábrica de contrato simple?

Creo que encontrará más claridad centrándose primero en la estructura de datos. Esta "fábrica" ​​hará mundos, por lo que todo lo que se requiere es un índice de los mundos (y eventos, etc.)

address[] public worldList;

Puedes construir el índice a medida que avanzas:

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

Para admitir su función de eliminación, necesitará saber en qué fila de worldList vive cada dirección mundial, así que modifique ligeramente la asignación:

mapping(address => uint) worldPointer;

y modifique ligeramente el proceso del nuevo mundo:

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

De esa manera, worldPointer[world]te dará la fila para borrar worldListcuando destruyas un mundo.

Hay una explicación más completa de una eliminación adecuada de una fila arbitraria en una matriz aquí: https://medium.com/@robhitchens/solidity-crud-part-2-ed8d8b4f74ec

Espero eso ayude.