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

Method popStorageArrayElement

libsolidity/codegen/ArrayUtils.cpp:493–579  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

491}
492
493void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
494{
495 solAssert(_type.location() == DataLocation::Storage, "");
496 solAssert(_type.isDynamicallySized(), "");
497 if (!_type.isByteArrayOrString() && _type.baseType()->storageBytes() < 32)
498 solAssert(_type.baseType()->isValueType(), "Invalid storage size for non-value type.");
499
500 if (_type.isByteArrayOrString())
501 {
502 m_context << Instruction::DUP1 << Instruction::SLOAD << Instruction::DUP1;
503 m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1);
504 util::Whiskers code(R"({
505 if iszero(length) {
506 mstore(0, <panicSelector>)
507 mstore(4, <emptyArrayPop>)
508 revert(0, 0x24)
509 }
510 switch gt(length, 31)
511 case 0 {
512 // short byte array
513 // Zero-out the suffix including the least significant byte.
514 let mask := sub(exp(0x100, sub(33, length)), 1)
515 length := sub(length, 1)
516 slot_value := or(and(not(mask), slot_value), mul(length, 2))
517 }
518 case 1 {
519 // long byte array
520 mstore(0, ref)
521 let slot := keccak256(0, 0x20)
522 switch length
523 case 32
524 {
525 let data := sload(slot)
526 sstore(slot, 0)
527 data := and(data, not(0xff))
528 slot_value := or(data, 62)
529 }
530 default
531 {
532 let offset_inside_slot := and(sub(length, 1), 0x1f)
533 slot := add(slot, div(sub(length, 1), 32))
534 let data := sload(slot)
535
536 // Zero-out the suffix of the byte array by masking it.
537 // ((1<<(8 * (32 - offset))) - 1)
538 let mask := sub(exp(0x100, sub(32, offset_inside_slot)), 1)
539 data := and(not(mask), data)
540 sstore(slot, data)
541
542 // Reduce the length by 1
543 slot_value := sub(slot_value, 2)
544 }
545 }
546 sstore(ref, slot_value)
547 })");
548 code("panicSelector", util::selectorFromSignatureU256("Panic(uint256)").str());
549 code("emptyArrayPop", std::to_string(unsigned(util::PanicCode::EmptyArrayPop)));
550 m_context.appendInlineAssembly(code.render(), {"ref", "slot_value", "length"});

Callers 1

visitMethod · 0.80

Calls 15

isByteArrayOrStringMethod · 0.80
callYulFunctionMethod · 0.80
strMethod · 0.80
appendInlineAssemblyMethod · 0.80
renderMethod · 0.80
setToZeroMethod · 0.80
to_stringFunction · 0.50
SourceLocationClass · 0.50
locationMethod · 0.45
isDynamicallySizedMethod · 0.45

Tested by

no test coverage detected