| 522 | } |
| 523 | |
| 524 | std::string ABIFunctions::abiEncodingFunctionSimpleArray( |
| 525 | ArrayType const& _from, |
| 526 | ArrayType const& _to, |
| 527 | EncodingOptions const& _options |
| 528 | ) |
| 529 | { |
| 530 | std::string functionName = |
| 531 | "abi_encode_" + |
| 532 | _from.identifier() + |
| 533 | "_to_" + |
| 534 | _to.identifier() + |
| 535 | _options.toFunctionNameSuffix(); |
| 536 | |
| 537 | solAssert(_from.isDynamicallySized() == _to.isDynamicallySized(), ""); |
| 538 | solAssert(_from.length() == _to.length(), ""); |
| 539 | solAssert(!_from.isByteArrayOrString(), ""); |
| 540 | if (_from.dataStoredIn(DataLocation::Storage)) |
| 541 | solAssert(_from.baseType()->storageBytes() > 16, ""); |
| 542 | |
| 543 | return createFunction(functionName, [&]() { |
| 544 | bool dynamic = _to.isDynamicallyEncoded(); |
| 545 | bool dynamicBase = _to.baseType()->isDynamicallyEncoded(); |
| 546 | bool const usesTail = dynamicBase && !_options.dynamicInplace; |
| 547 | EncodingOptions subOptions(_options); |
| 548 | subOptions.encodeFunctionFromStack = false; |
| 549 | subOptions.padded = true; |
| 550 | std::string elementValues = suffixedVariableNameList("elementValue", 0, numVariablesForType(*_from.baseType(), subOptions)); |
| 551 | Whiskers templ( |
| 552 | usesTail ? |
| 553 | R"( |
| 554 | // <readableTypeNameFrom> -> <readableTypeNameTo> |
| 555 | function <functionName>(value,<maybeLength> pos) <return> { |
| 556 | <declareLength> |
| 557 | pos := <storeLength>(pos, length) |
| 558 | let headStart := pos |
| 559 | let tail := add(pos, mul(length, 0x20)) |
| 560 | let baseRef := <dataAreaFun>(value) |
| 561 | let srcPtr := baseRef |
| 562 | for { let i := 0 } lt(i, length) { i := add(i, 1) } |
| 563 | { |
| 564 | mstore(pos, sub(tail, headStart)) |
| 565 | let <elementValues> := <arrayElementAccess> |
| 566 | tail := <encodeToMemoryFun>(<elementValues>, tail) |
| 567 | srcPtr := <nextArrayElement>(srcPtr) |
| 568 | pos := add(pos, 0x20) |
| 569 | } |
| 570 | pos := tail |
| 571 | <assignEnd> |
| 572 | } |
| 573 | )" : |
| 574 | R"( |
| 575 | // <readableTypeNameFrom> -> <readableTypeNameTo> |
| 576 | function <functionName>(value,<maybeLength> pos) <return> { |
| 577 | <declareLength> |
| 578 | pos := <storeLength>(pos, length) |
| 579 | let baseRef := <dataAreaFun>(value) |
| 580 | let srcPtr := baseRef |
| 581 | for { let i := 0 } lt(i, length) { i := add(i, 1) } |
nothing calls this directly
no test coverage detected