Solidity

從合約方法創建合約實例

  • June 4, 2018

我一直在研究使用區塊鏈作為數據儲存來建構 MUD 類型遊戲的概念。注意 - 這是一個專用網路 - 所以乙太成本對我來說並不是一個大問題。

給定一個看起來像這樣的契約:

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

}

當我從 nethereum 呼叫 createWorld 函式時 - 我可以看到交易正在進行,我等待探勘完成,但我的事件從未被觸發?

我正在為乙太坊做複雜的事情嗎?注意 - World 合約然後實例化一個 Area 合約,然後實例化一個 Door 對象。

我正在通過 nethereums var callResult = f.EstimateGasAsync(args).Result;

其中 f 是函式呼叫。

我在 nethereum 中的 .Net 程式碼如下所示:

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

無論如何,我的日誌總是以 0 個元素結束,即使使用乙太坊錢包 - 我也沒有看到任何合約事件被引發。

建議?

我想我把它整理好了——我想我是在函式而不是事件上呼叫 GetAllChanges。

無論如何-我可以看到現在正在引發的事件。我添加了

event RequestReceived(string s);

因此,我可以跟踪執行在合約功能中的進展情況。

如果有幫助,這裡有一個模式:有簡單的契約工廠模式嗎?

我認為通過首先關注資料結構,您會發現更清晰。這個“工廠”將製作世界,所以所需要的只是世界(和事件等)的索引。

address[] public worldList;

您可以隨時建構索引:

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

為了支持您的刪除功能,您需要知道每個 World 地址位於 worldList 中的哪一行,因此稍微修改映射:

mapping(address => uint) worldPointer;

並稍微修改新世界程序:

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

這樣,當您摧毀一個世界時,worldPointer[world]將為您提供要刪除的行。worldList

這裡有一個從數組中的任意行正確刪除的更完整的解釋:https ://medium.com/@robhitchens/solidity-crud-part-2-ed8d8b4f74ec

希望能幫助到你。

引用自:https://ethereum.stackexchange.com/questions/26714