MCPcopy Create free account
hub / github.com/argotorg/solidity / abiDecode

Method abiDecode

libsolidity/codegen/CompilerUtils.cpp:246–420  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

244}
245
246void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMemory)
247{
248 /// Stack: <source_offset> <length>
249 if (m_context.useABICoderV2())
250 {
251 // Use the new Yul-based decoding function
252 auto stackHeightBefore = m_context.stackHeight();
253 abiDecodeV2(_typeParameters, _fromMemory);
254 solAssert(m_context.stackHeight() - stackHeightBefore == sizeOnStack(_typeParameters) - 2);
255 return;
256 }
257
258 //@todo this does not yet support nested dynamic arrays
259 size_t encodedSize = 0;
260 for (auto const& t: _typeParameters)
261 encodedSize += t->decodingType()->calldataHeadSize();
262
263 Whiskers templ(R"({
264 if lt(len, <encodedSize>) { <revertString> }
265 })");
266 templ("encodedSize", std::to_string(encodedSize));
267 templ("revertString", m_context.revertReasonIfDebug("Calldata too short"));
268 m_context.appendInlineAssembly(templ.render(), {"len"});
269
270 m_context << Instruction::DUP2 << Instruction::ADD;
271 m_context << Instruction::SWAP1;
272 /// Stack: <input_end> <source_offset>
273
274 // Retain the offset pointer as base_offset, the point from which the data offsets are computed.
275 m_context << Instruction::DUP1;
276 for (Type const* parameterType: _typeParameters)
277 {
278 // stack: v1 v2 ... v(k-1) input_end base_offset current_offset
279 Type const* type = parameterType->decodingType();
280 solUnimplementedAssert(type, "No decoding type found.");
281 if (type->category() == Type::Category::Array)
282 {
283 auto const& arrayType = dynamic_cast<ArrayType const&>(*type);
284 solUnimplementedAssert(!arrayType.baseType()->isDynamicallyEncoded(), "Nested arrays not yet implemented.");
285 if (_fromMemory)
286 {
287 solUnimplementedAssert(
288 arrayType.baseType()->isValueType(),
289 "Nested memory arrays not yet implemented here."
290 );
291 // @todo If base type is an array or struct, it is still calldata-style encoded, so
292 // we would have to convert it like below.
293 solAssert(arrayType.location() == DataLocation::Memory);
294 if (arrayType.isDynamicallySized())
295 {
296 // compute data pointer
297 m_context << Instruction::DUP1 << Instruction::MLOAD;
298 // stack: v1 v2 ... v(k-1) input_end base_offset current_offset data_offset
299
300 fetchFreeMemoryPointer();
301 // stack: v1 v2 ... v(k-1) input_end base_offset current_offset data_offset dstmem
302 moveIntoStack(4);
303 // stack: v1 v2 ... v(k-1) dstmem input_end base_offset current_offset data_offset

Callers 4

appendConstructorMethod · 0.80
visitMethod · 0.80

Calls 15

ArrayUtilsClass · 0.85
WhiskersClass · 0.85
convertTypeFunction · 0.85
calldataHeadSizeMethod · 0.80
revertReasonIfDebugMethod · 0.80
appendInlineAssemblyMethod · 0.80
renderMethod · 0.80
calldataStrideMethod · 0.80
copyArrayToMemoryMethod · 0.80
to_stringFunction · 0.50
useABICoderV2Method · 0.45
stackHeightMethod · 0.45

Tested by

no test coverage detected