fix: align deployment manifest schema
This commit is contained in:
+98
-33
@@ -23,19 +23,23 @@ abstract contract DemoScript is Script {
|
||||
error UnexpectedState(string label, uint256 expected, uint256 actual);
|
||||
error UnexpectedAddress(string label, address expected, address actual);
|
||||
|
||||
struct Actor {
|
||||
string label;
|
||||
address address_;
|
||||
}
|
||||
|
||||
struct Manifest {
|
||||
uint256 schemaVersion;
|
||||
string network;
|
||||
uint256 chainId;
|
||||
uint256 deploymentBlock;
|
||||
string rpcUrl;
|
||||
string explorerUrl;
|
||||
string explorerBaseUrl;
|
||||
address token;
|
||||
address proxy;
|
||||
address implementation;
|
||||
address owner;
|
||||
string[] actorLabels;
|
||||
address[] actors;
|
||||
Actor[] actors;
|
||||
}
|
||||
|
||||
function _requireSupportedChain(uint256 chainId) internal pure {
|
||||
@@ -58,22 +62,23 @@ abstract contract DemoScript is Script {
|
||||
|
||||
function _readManifest(string memory path, bool active) internal view returns (Manifest memory manifest) {
|
||||
string memory json = vm.readFile(path);
|
||||
_assertExactManifestSchema(json);
|
||||
manifest.schemaVersion = vm.parseJsonUint(json, ".schemaVersion");
|
||||
manifest.network = vm.parseJsonString(json, ".network");
|
||||
manifest.chainId = vm.parseJsonUint(json, ".chainId");
|
||||
manifest.deploymentBlock = vm.parseJsonUint(json, ".deploymentBlock");
|
||||
manifest.rpcUrl = vm.parseJsonString(json, ".rpcUrl");
|
||||
manifest.explorerUrl = vm.parseJsonString(json, ".explorerUrl");
|
||||
if (vm.keyExistsJson(json, ".rpcUrl")) manifest.rpcUrl = vm.parseJsonString(json, ".rpcUrl");
|
||||
if (vm.keyExistsJson(json, ".explorerBaseUrl")) {
|
||||
manifest.explorerBaseUrl = vm.parseJsonString(json, ".explorerBaseUrl");
|
||||
}
|
||||
manifest.token = vm.parseJsonAddress(json, ".token");
|
||||
manifest.proxy = vm.parseJsonAddress(json, ".proxy");
|
||||
manifest.implementation = vm.parseJsonAddress(json, ".implementation");
|
||||
manifest.owner = vm.parseJsonAddress(json, ".owner");
|
||||
manifest.actorLabels = vm.parseJsonStringArray(json, ".actorLabels");
|
||||
manifest.actors = vm.parseJsonAddressArray(json, ".actors");
|
||||
|
||||
if (manifest.schemaVersion != 1) revert InvalidManifestSchema(manifest.schemaVersion);
|
||||
if (manifest.chainId != block.chainid) revert ManifestChainMismatch(block.chainid, manifest.chainId);
|
||||
if (active && manifest.deploymentBlock == 0) revert InvalidDeploymentBlock();
|
||||
manifest.actors = _parseActors(json, manifest.chainId);
|
||||
_validateActorConfiguration(manifest);
|
||||
_requireCode("token", manifest.token);
|
||||
_requireCode("proxy", manifest.proxy);
|
||||
@@ -84,29 +89,63 @@ abstract contract DemoScript is Script {
|
||||
if (target == address(0) || target.code.length == 0) revert MissingCode(label, target);
|
||||
}
|
||||
|
||||
function _assertExactManifestSchema(string memory json) private view {
|
||||
string[] memory keys = vm.parseJsonKeys(json, ".");
|
||||
if (keys.length < 9 || keys.length > 11) revert InvalidManifestSchema(0);
|
||||
bool[9] memory required;
|
||||
for (uint256 i; i < keys.length; ++i) {
|
||||
string memory key = keys[i];
|
||||
if (_equals(key, "schemaVersion")) required[0] = true;
|
||||
else if (_equals(key, "network")) required[1] = true;
|
||||
else if (_equals(key, "chainId")) required[2] = true;
|
||||
else if (_equals(key, "deploymentBlock")) required[3] = true;
|
||||
else if (_equals(key, "token")) required[4] = true;
|
||||
else if (_equals(key, "proxy")) required[5] = true;
|
||||
else if (_equals(key, "implementation")) required[6] = true;
|
||||
else if (_equals(key, "owner")) required[7] = true;
|
||||
else if (_equals(key, "actors")) required[8] = true;
|
||||
else if (!_equals(key, "rpcUrl") && !_equals(key, "explorerBaseUrl")) revert InvalidManifestSchema(0);
|
||||
}
|
||||
for (uint256 i; i < required.length; ++i) {
|
||||
if (!required[i]) revert InvalidManifestSchema(0);
|
||||
}
|
||||
}
|
||||
|
||||
function _parseActors(string memory json, uint256 chainId) private view returns (Actor[] memory actors) {
|
||||
uint256 actorCount = chainId == ANVIL_CHAIN_ID ? 3 : 1;
|
||||
actors = new Actor[](actorCount);
|
||||
for (uint256 i; i < actorCount; ++i) {
|
||||
string memory index = vm.toString(i);
|
||||
actors[i].label = vm.parseJsonString(json, string.concat(".actors[", index, "].label"));
|
||||
actors[i].address_ = vm.parseJsonAddress(json, string.concat(".actors[", index, "].address"));
|
||||
}
|
||||
if (vm.keyExistsJson(json, string.concat(".actors[", vm.toString(actorCount), "]"))) {
|
||||
revert InvalidActorConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
function _validateActorConfiguration(Manifest memory manifest) internal pure {
|
||||
if (manifest.actorLabels.length != manifest.actors.length) revert InvalidActorConfiguration();
|
||||
if (manifest.chainId == ANVIL_CHAIN_ID) {
|
||||
if (
|
||||
manifest.actorLabels.length != 3 || !_equals(manifest.network, "anvil")
|
||||
|| !_equals(manifest.actorLabels[0], "owner") || !_equals(manifest.actorLabels[1], "Alice")
|
||||
|| !_equals(manifest.actorLabels[2], "Bob")
|
||||
manifest.actors.length != 3 || !_equals(manifest.network, "anvil")
|
||||
|| !_equals(manifest.actors[0].label, "owner") || !_equals(manifest.actors[1].label, "Alice")
|
||||
|| !_equals(manifest.actors[2].label, "Bob")
|
||||
) revert InvalidActorConfiguration();
|
||||
|
||||
(, address owner) = _deriveLocalActor(ANVIL_CHAIN_ID, 0);
|
||||
(, address alice) = _deriveLocalActor(ANVIL_CHAIN_ID, 1);
|
||||
(, address bob) = _deriveLocalActor(ANVIL_CHAIN_ID, 2);
|
||||
if (
|
||||
manifest.actors[0] != manifest.owner || manifest.actors[0] != owner || manifest.actors[1] != alice
|
||||
|| manifest.actors[2] != bob
|
||||
manifest.actors[0].address_ != manifest.owner || manifest.actors[0].address_ != owner
|
||||
|| manifest.actors[1].address_ != alice || manifest.actors[2].address_ != bob
|
||||
) revert InvalidActorConfiguration();
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
manifest.chainId != BASE_SEPOLIA_CHAIN_ID || manifest.actorLabels.length != 1
|
||||
|| !_equals(manifest.network, "base-sepolia") || !_equals(manifest.actorLabels[0], "owner")
|
||||
|| manifest.actors[0] != manifest.owner
|
||||
manifest.chainId != BASE_SEPOLIA_CHAIN_ID || manifest.actors.length != 1
|
||||
|| !_equals(manifest.network, "baseSepolia") || !_equals(manifest.actors[0].label, "owner")
|
||||
|| manifest.actors[0].address_ != manifest.owner
|
||||
) revert InvalidActorConfiguration();
|
||||
}
|
||||
|
||||
@@ -122,20 +161,46 @@ abstract contract DemoScript is Script {
|
||||
return keccak256(bytes(left)) == keccak256(bytes(right));
|
||||
}
|
||||
|
||||
function _serializeManifest(Manifest memory manifest) internal returns (string memory json) {
|
||||
string memory objectKey = "demo-manifest";
|
||||
vm.serializeUint(objectKey, "schemaVersion", manifest.schemaVersion);
|
||||
vm.serializeString(objectKey, "network", manifest.network);
|
||||
vm.serializeUint(objectKey, "chainId", manifest.chainId);
|
||||
vm.serializeUint(objectKey, "deploymentBlock", manifest.deploymentBlock);
|
||||
vm.serializeString(objectKey, "rpcUrl", manifest.rpcUrl);
|
||||
vm.serializeString(objectKey, "explorerUrl", manifest.explorerUrl);
|
||||
vm.serializeAddress(objectKey, "token", manifest.token);
|
||||
vm.serializeAddress(objectKey, "proxy", manifest.proxy);
|
||||
vm.serializeAddress(objectKey, "implementation", manifest.implementation);
|
||||
vm.serializeAddress(objectKey, "owner", manifest.owner);
|
||||
vm.serializeString(objectKey, "actorLabels", manifest.actorLabels);
|
||||
json = vm.serializeAddress(objectKey, "actors", manifest.actors);
|
||||
function _serializeManifest(Manifest memory manifest) internal view returns (string memory json) {
|
||||
json = string.concat(
|
||||
'{"schemaVersion":',
|
||||
vm.toString(manifest.schemaVersion),
|
||||
',"network":"',
|
||||
manifest.network,
|
||||
'","chainId":',
|
||||
vm.toString(manifest.chainId),
|
||||
',"deploymentBlock":',
|
||||
vm.toString(manifest.deploymentBlock)
|
||||
);
|
||||
if (bytes(manifest.rpcUrl).length != 0) json = string.concat(json, ',"rpcUrl":"', manifest.rpcUrl, '"');
|
||||
if (bytes(manifest.explorerBaseUrl).length != 0) {
|
||||
json = string.concat(json, ',"explorerBaseUrl":"', manifest.explorerBaseUrl, '"');
|
||||
}
|
||||
json = string.concat(
|
||||
json,
|
||||
',"token":"',
|
||||
vm.toString(manifest.token),
|
||||
'","proxy":"',
|
||||
vm.toString(manifest.proxy),
|
||||
'","implementation":"',
|
||||
vm.toString(manifest.implementation),
|
||||
'","owner":"',
|
||||
vm.toString(manifest.owner),
|
||||
'","actors":',
|
||||
_serializeActors(manifest.actors),
|
||||
"}"
|
||||
);
|
||||
}
|
||||
|
||||
function _serializeActors(Actor[] memory actors) private view returns (string memory json) {
|
||||
json = "[";
|
||||
for (uint256 i; i < actors.length; ++i) {
|
||||
if (i != 0) json = string.concat(json, ",");
|
||||
json = string.concat(
|
||||
json, '{"label":"', actors[i].label, '","address":"', vm.toString(actors[i].address_), '"}'
|
||||
);
|
||||
}
|
||||
json = string.concat(json, "]");
|
||||
}
|
||||
|
||||
function _writeManifest(string memory path, Manifest memory manifest) internal {
|
||||
@@ -153,8 +218,8 @@ abstract contract DemoScript is Script {
|
||||
|
||||
function _assertV1State(Manifest memory manifest) internal view {
|
||||
BankV1 bank = BankV1(manifest.proxy);
|
||||
_assertUint("Alice internal balance", 900e6, bank.balanceOf(manifest.actors[1]));
|
||||
_assertUint("Bob internal balance", 500e6, bank.balanceOf(manifest.actors[2]));
|
||||
_assertUint("Alice internal balance", 900e6, bank.balanceOf(manifest.actors[1].address_));
|
||||
_assertUint("Bob internal balance", 500e6, bank.balanceOf(manifest.actors[2].address_));
|
||||
_assertUint("liabilities", 1_400e6, bank.totalLiabilities());
|
||||
_assertUint("reserves", 1_400e6, MockUSDC(manifest.token).balanceOf(manifest.proxy));
|
||||
_assertUint("version", 1, bank.contractVersion());
|
||||
|
||||
Reference in New Issue
Block a user