fix: align deployment manifest schema
This commit is contained in:
+145
-41
@@ -125,18 +125,38 @@ contract ScriptPreflightTest is Test {
|
||||
harness.readManifest(path, true);
|
||||
}
|
||||
|
||||
function testManifestRejectsNonParallelActorArrays() public {
|
||||
function testAnvilManifestRejectsUnexpectedActorObjectCount() public {
|
||||
string memory path = _writeManifest(31337, 1, TOKEN, PROXY, IMPLEMENTATION);
|
||||
_etchManifestContracts();
|
||||
vm.writeJson('["owner","Alice"]', path, ".actorLabels");
|
||||
vm.expectRevert(DemoScript.InvalidActorConfiguration.selector);
|
||||
vm.writeJson(
|
||||
string.concat(
|
||||
'[{"label":"owner","address":"',
|
||||
vm.toString(OWNER),
|
||||
'"},{"label":"Alice","address":"',
|
||||
vm.toString(ALICE),
|
||||
'"}]'
|
||||
),
|
||||
path,
|
||||
".actors"
|
||||
);
|
||||
vm.expectRevert();
|
||||
harness.readManifest(path, true);
|
||||
}
|
||||
|
||||
function testAnvilManifestRejectsUnexpectedActorLabels() public {
|
||||
string memory path = _writeManifest(31337, 1, TOKEN, PROXY, IMPLEMENTATION);
|
||||
_etchManifestContracts();
|
||||
vm.writeJson('["owner","Mallory","Bob"]', path, ".actorLabels");
|
||||
vm.writeJson(
|
||||
string.concat(
|
||||
'[{"label":"owner","address":"',
|
||||
vm.toString(OWNER),
|
||||
'"},{"label":"Mallory","address":"',
|
||||
vm.toString(ALICE),
|
||||
'"},{"label":"Bob","address":"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"}]'
|
||||
),
|
||||
path,
|
||||
".actors"
|
||||
);
|
||||
vm.expectRevert(DemoScript.InvalidActorConfiguration.selector);
|
||||
harness.readManifest(path, true);
|
||||
}
|
||||
@@ -146,7 +166,11 @@ contract ScriptPreflightTest is Test {
|
||||
_etchManifestContracts();
|
||||
vm.writeJson(
|
||||
string.concat(
|
||||
'["', vm.toString(ALICE), '","', vm.toString(OWNER), '","0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"]'
|
||||
'[{"label":"owner","address":"',
|
||||
vm.toString(ALICE),
|
||||
'"},{"label":"Alice","address":"',
|
||||
vm.toString(OWNER),
|
||||
'"},{"label":"Bob","address":"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"}]'
|
||||
),
|
||||
path,
|
||||
".actors"
|
||||
@@ -156,11 +180,20 @@ contract ScriptPreflightTest is Test {
|
||||
}
|
||||
|
||||
function testBaseManifestRequiresOnlyOwnerActor() public {
|
||||
string memory path = _writeBaseManifest();
|
||||
string memory path = _writePublicBaseManifest();
|
||||
vm.chainId(84532);
|
||||
_etchManifestContracts();
|
||||
vm.writeJson('["owner","Alice"]', path, ".actorLabels");
|
||||
vm.writeJson(string.concat('["', vm.toString(OWNER), '","', vm.toString(ALICE), '"]'), path, ".actors");
|
||||
vm.writeJson(
|
||||
string.concat(
|
||||
'[{"label":"owner","address":"',
|
||||
vm.toString(OWNER),
|
||||
'"},{"label":"Alice","address":"',
|
||||
vm.toString(ALICE),
|
||||
'"}]'
|
||||
),
|
||||
path,
|
||||
".actors"
|
||||
);
|
||||
vm.expectRevert(DemoScript.InvalidActorConfiguration.selector);
|
||||
harness.readManifest(path, true);
|
||||
}
|
||||
@@ -169,6 +202,41 @@ contract ScriptPreflightTest is Test {
|
||||
assertEq(harness.educationalWarning(), unicode"Educational demo — mock token — never use real funds.");
|
||||
}
|
||||
|
||||
function testNestedActorsRoundTripThroughManifestSerialization() public {
|
||||
string memory path = _writePublicAnvilManifest();
|
||||
_etchManifestContracts();
|
||||
DemoScript.Manifest memory manifest = harness.readManifest(path, true);
|
||||
assertEq(manifest.actors[0].label, "owner");
|
||||
assertEq(manifest.actors[1].address_, ALICE);
|
||||
|
||||
string memory serialized = harness.serializeManifest(manifest);
|
||||
assertFalse(_contains(serialized, "actorLabels"));
|
||||
assertFalse(_contains(serialized, "explorerUrl"));
|
||||
vm.writeFile(path, serialized);
|
||||
DemoScript.Manifest memory roundTrip = harness.readManifest(path, true);
|
||||
assertEq(roundTrip.actors[2].label, "Bob");
|
||||
assertEq(roundTrip.actors[2].address_, 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC);
|
||||
}
|
||||
|
||||
function testLegacyParallelActorManifestIsRejected() public {
|
||||
string memory path = _writeLegacyParallelActorManifest();
|
||||
_etchManifestContracts();
|
||||
vm.expectRevert(abi.encodeWithSelector(DemoScript.InvalidManifestSchema.selector, uint256(0)));
|
||||
harness.readManifest(path, true);
|
||||
}
|
||||
|
||||
function testBaseSepoliaManifestUsesCamelCaseAndOmitsUnavailableUrls() public {
|
||||
string memory path = _writePublicBaseManifest();
|
||||
vm.chainId(84532);
|
||||
_etchManifestContracts();
|
||||
DemoScript.Manifest memory manifest = harness.readManifest(path, true);
|
||||
assertEq(manifest.network, "baseSepolia");
|
||||
assertEq(manifest.rpcUrl, "");
|
||||
assertEq(manifest.explorerBaseUrl, "");
|
||||
assertEq(manifest.actors[0].label, "owner");
|
||||
assertEq(manifest.actors[0].address_, OWNER);
|
||||
}
|
||||
|
||||
function testSerializedManifestContainsPublicAddressesAndNoSecrets() public {
|
||||
DemoScript.Manifest memory manifest = DemoScript.Manifest({
|
||||
schemaVersion: 1,
|
||||
@@ -176,12 +244,11 @@ contract ScriptPreflightTest is Test {
|
||||
chainId: 31337,
|
||||
deploymentBlock: 0,
|
||||
rpcUrl: "http://127.0.0.1:8545",
|
||||
explorerUrl: "",
|
||||
explorerBaseUrl: "",
|
||||
token: TOKEN,
|
||||
proxy: PROXY,
|
||||
implementation: IMPLEMENTATION,
|
||||
owner: OWNER,
|
||||
actorLabels: _labels(),
|
||||
actors: _actors()
|
||||
});
|
||||
|
||||
@@ -212,12 +279,12 @@ contract ScriptPreflightTest is Test {
|
||||
assertEq(BankV1(proxy).owner(), OWNER);
|
||||
assertEq(address(BankV1(proxy).asset()), token);
|
||||
assertEq(BankV1(proxy).contractVersion(), 1);
|
||||
assertEq(manifest.actorLabels[0], "owner");
|
||||
assertEq(manifest.actorLabels[1], "Alice");
|
||||
assertEq(manifest.actorLabels[2], "Bob");
|
||||
assertEq(manifest.actors[0], OWNER);
|
||||
assertEq(manifest.actors[1], ALICE);
|
||||
assertEq(manifest.actors[2], 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC);
|
||||
assertEq(manifest.actors[0].label, "owner");
|
||||
assertEq(manifest.actors[1].label, "Alice");
|
||||
assertEq(manifest.actors[2].label, "Bob");
|
||||
assertEq(manifest.actors[0].address_, OWNER);
|
||||
assertEq(manifest.actors[1].address_, ALICE);
|
||||
assertEq(manifest.actors[2].address_, 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC);
|
||||
}
|
||||
|
||||
function testSeedV1DemoExecutesExactActOneStateAndCheckStateAcceptsIt() public {
|
||||
@@ -227,12 +294,12 @@ contract ScriptPreflightTest is Test {
|
||||
new SeedV1Demo().run();
|
||||
|
||||
BankV1 bank = BankV1(manifest.proxy);
|
||||
assertEq(bank.balanceOf(manifest.actors[1]), 900e6);
|
||||
assertEq(bank.balanceOf(manifest.actors[2]), 500e6);
|
||||
assertEq(bank.balanceOf(manifest.actors[1].address_), 900e6);
|
||||
assertEq(bank.balanceOf(manifest.actors[2].address_), 500e6);
|
||||
assertEq(bank.totalLiabilities(), 1_400e6);
|
||||
assertEq(MockUSDC(manifest.token).balanceOf(manifest.proxy), 1_400e6);
|
||||
assertEq(MockUSDC(manifest.token).balanceOf(manifest.actors[1]), 1_100e6);
|
||||
assertEq(MockUSDC(manifest.token).balanceOf(manifest.actors[2]), 500e6);
|
||||
assertEq(MockUSDC(manifest.token).balanceOf(manifest.actors[1].address_), 1_100e6);
|
||||
assertEq(MockUSDC(manifest.token).balanceOf(manifest.actors[2].address_), 500e6);
|
||||
|
||||
vm.setEnv("DEMO_EXPECTED_STAGE", "v1");
|
||||
new CheckState().run();
|
||||
@@ -266,7 +333,7 @@ contract ScriptPreflightTest is Test {
|
||||
vm.toString(chainId),
|
||||
',"deploymentBlock":',
|
||||
vm.toString(deploymentBlock),
|
||||
',"rpcUrl":"http://127.0.0.1:8545","explorerUrl":"","token":"',
|
||||
',"rpcUrl":"http://127.0.0.1:8545","token":"',
|
||||
vm.toString(token),
|
||||
'","proxy":"',
|
||||
vm.toString(proxy),
|
||||
@@ -274,11 +341,11 @@ contract ScriptPreflightTest is Test {
|
||||
vm.toString(implementation),
|
||||
'","owner":"',
|
||||
vm.toString(OWNER),
|
||||
'","actorLabels":["owner","Alice","Bob"],"actors":["',
|
||||
'","actors":[{"label":"owner","address":"',
|
||||
vm.toString(OWNER),
|
||||
'","',
|
||||
'"},{"label":"Alice","address":"',
|
||||
vm.toString(ALICE),
|
||||
'","0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"]}'
|
||||
'"},{"label":"Bob","address":"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"}]}'
|
||||
);
|
||||
vm.writeFile(path, json);
|
||||
}
|
||||
@@ -293,12 +360,12 @@ contract ScriptPreflightTest is Test {
|
||||
manifest = harness.readManifest(path, true);
|
||||
}
|
||||
|
||||
function _writeBaseManifest() internal returns (string memory path) {
|
||||
path = string.concat(fixtureDir, "/base-manifest.json");
|
||||
function _writePublicAnvilManifest() internal returns (string memory path) {
|
||||
path = string.concat(fixtureDir, "/public-anvil-manifest.json");
|
||||
vm.writeFile(
|
||||
path,
|
||||
string.concat(
|
||||
'{"schemaVersion":1,"network":"base-sepolia","chainId":84532,"deploymentBlock":1,"rpcUrl":"https://sepolia.base.org","explorerUrl":"https://sepolia.basescan.org","token":"',
|
||||
'{"schemaVersion":1,"network":"anvil","chainId":31337,"deploymentBlock":1,"rpcUrl":"http://127.0.0.1:8545","token":"',
|
||||
vm.toString(TOKEN),
|
||||
'","proxy":"',
|
||||
vm.toString(PROXY),
|
||||
@@ -306,9 +373,53 @@ contract ScriptPreflightTest is Test {
|
||||
vm.toString(IMPLEMENTATION),
|
||||
'","owner":"',
|
||||
vm.toString(OWNER),
|
||||
'","actorLabels":["owner"],"actors":["',
|
||||
'","actors":[{"label":"owner","address":"',
|
||||
vm.toString(OWNER),
|
||||
'"]}'
|
||||
'"},{"label":"Alice","address":"',
|
||||
vm.toString(ALICE),
|
||||
'"},{"label":"Bob","address":"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"}]}'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function _writeLegacyParallelActorManifest() internal returns (string memory path) {
|
||||
path = string.concat(fixtureDir, "/legacy-parallel-actors.json");
|
||||
vm.writeFile(
|
||||
path,
|
||||
string.concat(
|
||||
'{"schemaVersion":1,"network":"anvil","chainId":31337,"deploymentBlock":1,"rpcUrl":"http://127.0.0.1:8545","token":"',
|
||||
vm.toString(TOKEN),
|
||||
'","proxy":"',
|
||||
vm.toString(PROXY),
|
||||
'","implementation":"',
|
||||
vm.toString(IMPLEMENTATION),
|
||||
'","owner":"',
|
||||
vm.toString(OWNER),
|
||||
'","actorLabels":["owner","Alice","Bob"],"actors":[{"label":"owner","address":"',
|
||||
vm.toString(OWNER),
|
||||
'"},{"label":"Alice","address":"',
|
||||
vm.toString(ALICE),
|
||||
'"},{"label":"Bob","address":"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"}]}'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function _writePublicBaseManifest() internal returns (string memory path) {
|
||||
path = string.concat(fixtureDir, "/public-base-manifest.json");
|
||||
vm.writeFile(
|
||||
path,
|
||||
string.concat(
|
||||
'{"schemaVersion":1,"network":"baseSepolia","chainId":84532,"deploymentBlock":1,"token":"',
|
||||
vm.toString(TOKEN),
|
||||
'","proxy":"',
|
||||
vm.toString(PROXY),
|
||||
'","implementation":"',
|
||||
vm.toString(IMPLEMENTATION),
|
||||
'","owner":"',
|
||||
vm.toString(OWNER),
|
||||
'","actors":[{"label":"owner","address":"',
|
||||
vm.toString(OWNER),
|
||||
'"}]}'
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -319,18 +430,11 @@ contract ScriptPreflightTest is Test {
|
||||
vm.etch(IMPLEMENTATION, hex"00");
|
||||
}
|
||||
|
||||
function _labels() internal pure returns (string[] memory labels) {
|
||||
labels = new string[](3);
|
||||
labels[0] = "owner";
|
||||
labels[1] = "Alice";
|
||||
labels[2] = "Bob";
|
||||
}
|
||||
|
||||
function _actors() internal pure returns (address[] memory actors) {
|
||||
actors = new address[](3);
|
||||
actors[0] = OWNER;
|
||||
actors[1] = ALICE;
|
||||
actors[2] = 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC;
|
||||
function _actors() internal pure returns (DemoScript.Actor[] memory actors) {
|
||||
actors = new DemoScript.Actor[](3);
|
||||
actors[0] = DemoScript.Actor({label: "owner", address_: OWNER});
|
||||
actors[1] = DemoScript.Actor({label: "Alice", address_: ALICE});
|
||||
actors[2] = DemoScript.Actor({label: "Bob", address_: 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC});
|
||||
}
|
||||
|
||||
function _contains(string memory haystack, string memory needle) internal pure returns (bool) {
|
||||
|
||||
Reference in New Issue
Block a user