ParserMappingSlot
数据在 json storage
的编码格式: encoding:mapping
array
类型为固定长度的数组,同时具备维度的区别
array
类型在 storage
中 通过 key,value
表明数据的类型
"t_mapping(t_int256,t_uint256)": {
"encoding": "mapping",
"key": "t_int256",
"label": "mapping(int256 => uint256)",
"numberOfBytes": "32",
"value": "t_uint256"
}
mapping
数据的具体存储位置和 mapping
键值和层数相关
- 因此,
mapping
类型需要记录当前数据的baseSlot
- 每层键值决定了下一层数据的起始
slot
- 键值类型决定了键值的编码格式
type SolidityMapping struct {
SlotIndex common.Hash
KeyTyp SolidityTyp
ValueTyp Variable `json:"value_typ"`
}
- 根据键值传参判断当前
mapping
的层数 - 计算最外层数据的起始
slot
存储位置 - 每进入一层,就进入新的
mapping
数据解析过程
- 重新计算当前层的数据起始存储
slot
- 根据数据类型获取具体的数值
// slotIndex = abi.encode(key,slot)
func (m MappingValue) Keys(ks []string) interface{} {
var slotIndex = m.baseSlotIndex
//k := ks[0]
var keyByte []byte
for index, k := range ks {
if index != 0 && index+1 <= len(ks) {
m.keyTyp = m.valueTyp.(*SolidityMapping).KeyTyp
m.valueTyp = m.valueTyp.(*SolidityMapping).ValueTyp
}
switch m.keyTyp {
case UintTy:
keyByte = encodeUintString(k)
case IntTy:
keyByte = encodeIntString(k)
case BytesTy:
keyByte = encodeByteString(k)
case StringTy:
keyByte = []byte(k)
case AddressTy:
keyByte = encodeHexString(k)
default:
panic("invalid key type")
}
slotIndex = crypto.Keccak256Hash(keyByte, slotIndex.Bytes())
}
reflect.ValueOf(m.valueTyp).Elem().FieldByName("SlotIndex").Set(reflect.ValueOf(slotIndex))
return m.valueTyp.Value(m.f)
}