面試題:Solidity中Mapping是如何存儲的?
泰嶽區塊鏈採用的是EVM solidity合約。那麼Map在solidity合約裏面到底怎麼存儲的呢?我們寫一個測試用例來測試一下。
pragma solidity ^0.6.0;
// SPDX-License-Identifier: MIT
contract Test1{
uint256 public pID;
uint256 public rID;
string public contractName;
//簡單寫一個玩家id,
mapping(uint256=>uint256) public plyid; //rid -> pid
mapping(address=>uint256) public plyAddr_id;
constructor() public{
rID = 1;
contractName = "test1";
}
function joinGame() public{
if (plyAddr_id[msg.sender] == 0){
pID++;
plyAddr_id[msg.sender] = pID ;
plyid[rID] = pID;
}
}
}
這個是一個簡單的存儲合約,用戶地址可以調用。
裏面存儲的變量有:uint256 ,string 和map
先對solidity的存儲有一個大概的瞭解。
solidity存儲分爲兩種:storage和memory 。storage存儲是永久存儲的(任何修改都需要消耗gas)storage一般放到構造函數聲明,memory是臨時存儲,比如函數傳參,返回值,函數內部調用。
針對這個面試題,主要是要了解storage。廢話少說,直接進入調試模式。
從這個圖裏面可以看到5個storage存儲空間,剛好匹配的是我定義的5個存儲,因爲EVM存儲都是存儲在默克耳樹上面。所以都是KEY/Value形式,
其中2,3,4 key 是0,1,2這些事標準的變量。分別是,pID,rID和contractName,另外兩個map,其實都是根據map裏面的key/value來生成對於的存儲key,比如5,就是我最開始的加入遊戲生成的1,如果我再加入一個值,這個storage就會多出一個,也就是說嗎:
Map在solidity存儲其實也就是key/value的存儲。這個key 0xf4f7797edbff68274daf92f2532a33b46087e1df1e392890bd510c458053e66c 生成是這麼生成的,首選這個存儲的是plyAddr_id它裏面的key是address,所以會用這個address+偏移量,這些都是會擴產到32位去處理。最後拿相加的結果進行Hash。得到這個地址索引的key。