Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
//there, we record our given slot in that spot in that table -- however,
//we alter it in one key way. Before entry, we check if the slot's
//*parent* has a spot in the table, based on address (same for both child
//and parent), parentType, and the parent's slot address (which can be
//found as the slotAddress of the slot's path object, if it exists -- if
//it doesn't then we conclude that no the parent does not have a spot in
//the table). If the parent has a slot in the table already, then we
//alter the child slot by replacing its path with the parent slot. This
//will keep the slotAddress the same, but since the versions kept in the
//table here are supposed to preserve path information, we'll be
//replacing a fairly bare-bones Slot object with one with a full path.
//we do NOT want to distinguish between types with and without "_ptr" on
//the end here! (or _slice)
debug("typeIdentifier %s", typeIdentifier);
typeIdentifier = Codec.Ast.Utils.regularizeTypeIdentifier(typeIdentifier);
parentType = Codec.Ast.Utils.regularizeTypeIdentifier(parentType);
debug("slot %o", slot);
let hexSlotAddress = Codec.Conversion.toHexString(
Codec.Storage.Utils.slotAddress(slot),
Codec.Evm.Utils.WORD_SIZE
);
let parentAddress = slot.path
? Codec.Conversion.toHexString(
Codec.Storage.Utils.slotAddress(slot.path),
Codec.Evm.Utils.WORD_SIZE
)
: undefined;
//this is going to be messy and procedural, sorry. but let's start with
//the easy stuff: create the new address if needed, clone if not
function* decodeMappingKeyCore(indexDefinition, keyDefinition) {
let scopes = yield select(data.views.scopes.inlined);
let currentAssignments = yield select(data.proc.assignments);
let currentDepth = yield select(data.current.functionDepth);
//why the loop? see the end of the block it heads for an explanatory
//comment
while (true) {
let indexId = indexDefinition.id;
//indices need to be identified by stackframe
let indexIdObj = { astId: indexId, stackframe: currentDepth };
let fullIndexId = stableKeccak256(indexIdObj);
const indexReference = (currentAssignments.byId[fullIndexId] || {}).ref;
if (Codec.Ast.Utils.isSimpleConstant(indexDefinition)) {
//while the main case is the next one, where we look for a prior
//assignment, we need this case (and need it first) for two reasons:
//1. some constant expressions (specifically, string and hex literals)
//aren't sourcemapped to and so won't have a prior assignment
//2. if the key type is bytesN but the expression is constant, the
//value will go on the stack *left*-padded instead of right-padded,
//so looking for a prior assignment will read the wrong value.
//so instead it's preferable to use the constant directly.
debug("about to decode simple literal");
return yield* decode(keyDefinition, {
location: "definition",
definition: indexDefinition
});
} else if (indexReference) {
//if a prior assignment is found
let splicedDefinition;
debug("about to decode simple literal");
return yield* decode(keyDefinition, {
location: "definition",
definition: indexDefinition
});
} else if (indexReference) {
//if a prior assignment is found
let splicedDefinition;
//in general, we want to decode using the key definition, not the index
//definition. however, the key definition may have the wrong location
//on it. so, when applicable, we splice the index definition location
//onto the key definition location.
if (Codec.Ast.Utils.isReference(indexDefinition)) {
splicedDefinition = Codec.Ast.Utils.spliceLocation(
keyDefinition,
Codec.Ast.Utils.referenceType(indexDefinition)
);
//we could put code here to add on the "_ptr" ending when absent,
//but we presently ignore that ending, so we'll skip that
} else {
splicedDefinition = keyDefinition;
}
debug("about to decode");
return yield* decode(splicedDefinition, indexReference);
} else if (
indexDefinition.referencedDeclaration &&
scopes[indexDefinition.referencedDeclaration]
) {
//there's one more reason we might have failed to decode it: it might be a
//constant state variable. Unfortunately, we don't know how to decode all
//those at the moment, but we can handle the ones we do know how to decode.
//In the future hopefully we will decode all of them
//we alter it in one key way. Before entry, we check if the slot's
//*parent* has a spot in the table, based on address (same for both child
//and parent), parentType, and the parent's slot address (which can be
//found as the slotAddress of the slot's path object, if it exists -- if
//it doesn't then we conclude that no the parent does not have a spot in
//the table). If the parent has a slot in the table already, then we
//alter the child slot by replacing its path with the parent slot. This
//will keep the slotAddress the same, but since the versions kept in the
//table here are supposed to preserve path information, we'll be
//replacing a fairly bare-bones Slot object with one with a full path.
//we do NOT want to distinguish between types with and without "_ptr" on
//the end here! (or _slice)
debug("typeIdentifier %s", typeIdentifier);
typeIdentifier = Codec.Ast.Utils.regularizeTypeIdentifier(typeIdentifier);
parentType = Codec.Ast.Utils.regularizeTypeIdentifier(parentType);
debug("slot %o", slot);
let hexSlotAddress = Codec.Conversion.toHexString(
Codec.Storage.Utils.slotAddress(slot),
Codec.Evm.Utils.WORD_SIZE
);
let parentAddress = slot.path
? Codec.Conversion.toHexString(
Codec.Storage.Utils.slotAddress(slot.path),
Codec.Evm.Utils.WORD_SIZE
)
: undefined;
//this is going to be messy and procedural, sorry. but let's start with
//the easy stuff: create the new address if needed, clone if not
let newState = {
}
//otherwise, we're good to go, so let's find the contract node and
//put it all together
//to get the contract node, we go up twice from the function node;
//the path from one to the other should have a very specific form,
//so this is easy
let contractPointer = pointer.replace(/\/nodes\/\d+$/, "");
let contractNode = jsonpointer.get(ast, contractPointer);
return {
[instruction.pc]: {
source,
pointer,
node,
name: node.name,
id: node.id,
mutability: Codec.Ast.Utils.mutability(node),
contractPointer,
contractNode,
contractName: contractNode.name,
contractId: contractNode.id,
contractKind: contractNode.contractKind,
isDesignatedInvalid: false
}
};
})
)