Coverage Report

Created: 2025-06-24 07:59

/src/solidity/libsolidity/interface/StorageLayout.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
  This file is part of solidity.
3
4
  solidity is free software: you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation, either version 3 of the License, or
7
  (at your option) any later version.
8
9
  solidity is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
// SPDX-License-Identifier: GPL-3.0
18
19
#include <libsolidity/interface/StorageLayout.h>
20
21
#include <libsolidity/ast/TypeProvider.h>
22
23
using namespace std::literals;
24
using namespace solidity;
25
using namespace solidity::frontend;
26
27
Json StorageLayout::generate(ContractDefinition const& _contractDef, DataLocation const _location)
28
0
{
29
0
  solAssert(!m_contract, "");
30
0
  m_contract = &_contractDef;
31
0
  m_types.clear();
32
33
0
  auto typeType = dynamic_cast<TypeType const*>(_contractDef.type());
34
0
  solAssert(typeType, "");
35
0
  auto contractType = dynamic_cast<ContractType const*>(typeType->actualType());
36
0
  solAssert(contractType, "");
37
38
0
  Json variables = Json::array();
39
0
  for (auto [var, slot, offset]: contractType->linearizedStateVariables(_location))
40
0
    variables.emplace_back(generate(*var, slot, offset));
41
42
0
  Json layout;
43
0
  layout["storage"] = std::move(variables);
44
0
  layout["types"] = std::move(m_types);
45
46
0
  return layout;
47
0
}
48
49
Json StorageLayout::generate(VariableDeclaration const& _var, u256 const& _slot, unsigned _offset)
50
0
{
51
0
  Json varEntry;
52
0
  Type const* varType = _var.type();
53
54
0
  varEntry["label"] = _var.name();
55
0
  varEntry["astId"] = static_cast<int>(_var.id());
56
0
  varEntry["contract"] = m_contract->fullyQualifiedName();
57
0
  varEntry["slot"] = _slot.str();
58
0
  varEntry["offset"] = _offset;
59
0
  varEntry["type"] = typeKeyName(varType);
60
61
0
  generate(varType);
62
63
0
  return varEntry;
64
0
}
65
66
void StorageLayout::generate(Type const* _type)
67
0
{
68
0
  if (m_types.contains(typeKeyName(_type)))
69
0
    return;
70
71
  // Register it now to cut recursive visits.
72
0
  Json& typeInfo = m_types[typeKeyName(_type)];
73
0
  typeInfo["label"] = _type->toString(true);
74
0
  typeInfo["numberOfBytes"] = u256(_type->storageBytes() * _type->storageSize()).str();
75
76
0
  if (auto structType = dynamic_cast<StructType const*>(_type))
77
0
  {
78
0
    Json members = Json::array();
79
0
    auto const& structDef = structType->structDefinition();
80
0
    for (auto const& member: structDef.members())
81
0
    {
82
0
      auto const& offsets = structType->storageOffsetsOfMember(member->name());
83
0
      members.emplace_back(generate(*member, offsets.first, offsets.second));
84
0
    }
85
0
    typeInfo["members"] = std::move(members);
86
0
    typeInfo["encoding"] = "inplace";
87
0
  }
88
0
  else if (auto mappingType = dynamic_cast<MappingType const*>(_type))
89
0
  {
90
0
    typeInfo["key"] = typeKeyName(mappingType->keyType());
91
0
    typeInfo["value"] = typeKeyName(mappingType->valueType());
92
0
    generate(mappingType->keyType());
93
0
    generate(mappingType->valueType());
94
0
    typeInfo["encoding"] = "mapping";
95
0
  }
96
0
  else if (auto arrayType = dynamic_cast<ArrayType const*>(_type))
97
0
  {
98
0
    if (arrayType->isByteArrayOrString())
99
0
      typeInfo["encoding"] = "bytes";
100
0
    else
101
0
    {
102
0
      typeInfo["base"] = typeKeyName(arrayType->baseType());
103
0
      generate(arrayType->baseType());
104
0
      typeInfo["encoding"] = arrayType->isDynamicallySized() ? "dynamic_array" : "inplace";
105
0
    }
106
0
  }
107
0
  else
108
0
  {
109
0
    solAssert(_type->isValueType(), "");
110
0
    typeInfo["encoding"] = "inplace";
111
0
  }
112
113
0
  solAssert(typeInfo.contains("encoding"), "");
114
0
}
115
116
std::string StorageLayout::typeKeyName(Type const* _type)
117
0
{
118
0
  if (auto refType = dynamic_cast<ReferenceType const*>(_type))
119
0
    return TypeProvider::withLocationIfReference(refType->location(), _type)->richIdentifier();
120
0
  return _type->richIdentifier();
121
0
}