-
Notifications
You must be signed in to change notification settings - Fork 60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: autogenerate decoded state diffs for validations #607
base: main
Are you sure you want to change the base?
Conversation
summary: "Batch inbox address", | ||
detail: "Unstructured storage slot for the address of the BatchInbox proxy." | ||
}); | ||
} | ||
if (_slot == START_BLOCK_SLOT) { | ||
return DecodedSlot({ | ||
kind: "uint256", | ||
oldValue: toUint(_oldValue), | ||
newValue: toUint(_newValue), | ||
summary: "Start block", | ||
detail: "Unstructured storage slot for the start block number." | ||
}); | ||
} | ||
if (_slot == DISPUTE_GAME_FACTORY_SLOT) { | ||
return DecodedSlot({ | ||
kind: "address", | ||
oldValue: toAddress(_oldValue), | ||
newValue: toAddress(_newValue), | ||
summary: "DisputeGameFactory proxy address", | ||
detail: "Unstructured storage slot for the address of the DisputeGameFactory proxy." | ||
}); | ||
} | ||
if (_slot == L2_OUTPUT_ORACLE_SLOT) { | ||
return DecodedSlot({ | ||
kind: "address", | ||
oldValue: toAddress(_oldValue), | ||
newValue: toAddress(_newValue), | ||
summary: "L2OutputOracle proxy address", | ||
detail: "Unstructured storage slot for the address of the L2OutputOracle proxy." | ||
}); | ||
} | ||
|
||
// SuperchainConfig. | ||
if (_slot == PAUSED_SLOT) { | ||
return DecodedSlot({ | ||
kind: "bool", | ||
oldValue: toBool(_oldValue), | ||
newValue: toBool(_newValue), | ||
summary: "Superchain pause status", | ||
detail: "Unstructured storage slot for the pause status of the superchain." | ||
}); | ||
} | ||
if (_slot == GUARDIAN_SLOT) { | ||
return DecodedSlot({ | ||
kind: "address", | ||
oldValue: toAddress(_oldValue), | ||
newValue: toAddress(_newValue), | ||
summary: "Guardian address", | ||
detail: "Unstructured storage slot for the address of the superchain guardian." | ||
}); | ||
} | ||
|
||
// ProtocolVersions. | ||
if (_slot == REQUIRED_SLOT) { | ||
return DecodedSlot({ | ||
kind: "uint256", | ||
oldValue: toUint(_oldValue), | ||
newValue: toUint(_newValue), | ||
summary: "Required protocol version", | ||
detail: "Unstructured storage slot for the required protocol version." | ||
}); | ||
} | ||
if (_slot == RECOMMENDED_SLOT) { | ||
return DecodedSlot({ | ||
kind: "uint256", | ||
oldValue: toUint(_oldValue), | ||
newValue: toUint(_newValue), | ||
summary: "Recommended protocol version", | ||
detail: "Unstructured storage slot for the recommended protocol version." | ||
}); | ||
} | ||
|
||
// Gas paying token slots. | ||
if (_slot == GAS_PAYING_TOKEN_SLOT) { | ||
return DecodedSlot({ | ||
kind: "address", | ||
oldValue: toAddress(_oldValue), | ||
newValue: toAddress(_newValue), | ||
summary: "Gas paying token address", | ||
detail: "Unstructured storage slot for the address of the gas paying token." | ||
}); | ||
} | ||
if (_slot == GAS_PAYING_TOKEN_NAME_SLOT) { | ||
return DecodedSlot({ | ||
kind: "string", | ||
oldValue: vm.toString(_oldValue), | ||
newValue: vm.toString(_newValue), | ||
summary: "Gas paying token name", | ||
detail: "Unstructured storage slot for the name of the gas paying token." | ||
}); | ||
} | ||
if (_slot == GAS_PAYING_TOKEN_SYMBOL_SLOT) { | ||
return DecodedSlot({ | ||
kind: "string", | ||
oldValue: vm.toString(_oldValue), | ||
newValue: vm.toString(_newValue), | ||
summary: "Gas paying token symbol", | ||
detail: "Unstructured storage slot for the symbol of the gas paying token." | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be really great if the new values for addresses were checked to make sure they are contracts where applicable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That feels like a coupling of concerns, this file is purely decoding of state diffs, and we have existing approaches to handle validating the correctness of storage writes
|
||
string memory label = layout[i]._label; | ||
return DecodedSlot({kind: kind, oldValue: oldValue, newValue: newValue, summary: label, detail: ""}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will this work for mappings?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does not support mappings yet, that will come later
@@ -116,6 +118,8 @@ contract NestedSignFromJson is OriginalNestedSignFromJson, CouncilFoundationNest | |||
checkDisputeGameFactory(); | |||
checkPermissionedDisputeGame(); | |||
console.log("All assertions passed!"); | |||
|
|||
StateDiffDecoder.decode(accesses); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file shows example usage, this feature is not used by default
// Read the entire JSON file. | ||
string memory jsonData = vm.readFile(filePath); | ||
|
||
// Get all the top-level keys, which are the chain IDs | ||
string[] memory chainIds = vm.parseJsonKeys(jsonData, "$"); | ||
for (uint256 i = 0; i < chainIds.length; i++) { | ||
string memory chainId = chainIds[i]; | ||
|
||
// Get all the keys of the nested object under currentTopKey. | ||
string memory key = string.concat("$.", chainId); | ||
string[] memory contractNames = vm.parseJsonKeys(jsonData, key); | ||
for (uint256 j = 0; j < contractNames.length; j++) { | ||
string memory contractName = contractNames[j]; | ||
|
||
// Build the JSON path: e.g. ".10.Guardian" | ||
string memory path = string.concat(".", chainId, ".", contractName); | ||
address foundAddress = vm.parseJsonAddress(jsonData, path); | ||
|
||
if (foundAddress == target) { | ||
// If the contract name ends with "Proxy", strip it. | ||
if (contractName.endsWith("Proxy")) { | ||
contractName = contractName.slice(0, bytes(contractName).length - 5); | ||
} | ||
// If the contract name is "OptimismPortal", change it to "OptimismPortal2". | ||
if (contractName.eq("OptimismPortal")) { | ||
contractName = "OptimismPortal2"; | ||
} | ||
// We make a call to see if the contract is a Safe. | ||
if (isGnosisSafe(target)) { | ||
contractName = string.concat(contractName, " (GnosisSafe)"); | ||
} | ||
|
||
return (vm.parseUint(chainId), contractName); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ElliotFriedman @blmalone @prat-gpt when we implement this decoded logging into the new version, we can replace this block with a lookup in the address registry using the getAddressInfo
method that @prat-gpt added
Autogenerates decoded state diffs to the terminal, requires the change in ethereum-optimism/optimism#14378 which is why the submodule is updated. Functionality works but doesn't decode mappings yet
This will also be easy to port to the new superchain-ops approach