Skip to content

Commit ed10607

Browse files
authored
V3 adoption scripts (#44)
* docs: update agreement.pdf and summary.pdf to reflect recent contract changes and enhancements * feat: add AddChains script and corresponding unit tests - Introduced the AddChains script for adding chains to an existing Agreement contract, including JSON parsing and validation. - Implemented unit tests for the AddChains script to ensure functionality for adding single and multiple chains, as well as handling edge cases like duplicate chains. - Added a sample JSON file for testing chain addition scenarios. * feat: add example JSON files for chains and agreement details - Introduced addChains.json and agreementDetails.json to provide sample data for chain addition and agreement specifications. - Updated paths in AddChains and AdoptSafeHarbor scripts to reference the new example JSON files. * fix: ensure consistent environment variable setup in AddChainsTest - Updated the test_addChains_multipleTimes function to reset the PROTOCOL_PRIVATE_KEY environment variable before each batch addition. - This change ensures that the correct owner key is used consistently, preventing potential test failures due to environment changes. * refactor: simplify key management in AddChains and AdoptSafeHarbor scripts BAD AI. NO PK IN .ENV. DON'T ENBARRASS ME IN FRONT OF PATRICK - Updated AddChains and AdoptSafeHarbor scripts to use msg.sender for ownership validation instead of relying on the PROTOCOL_PRIVATE_KEY environment variable. - Adjusted documentation to reflect changes in environment variable usage and default JSON paths. - Modified unit tests to remove unnecessary environment variable setups, ensuring cleaner test cases and consistent ownership handling. * refactor: improve code readability in AddChains and AdoptSafeHarbor scripts - Simplified function signatures in AddChains and AdoptSafeHarbor scripts for better clarity. - Consolidated console log statements for consistent formatting. - Removed unnecessary blank lines to enhance code cleanliness in unit tests. * refactor: format JSON test data for improved readability - Reformatted envTest.json and parseTest.json files to enhance readability by structuring the JSON data with proper indentation and line breaks. - This change improves clarity and maintainability of test data used in unit tests. * refactor: streamline AddChains script and unit tests for clarity - Simplified function signatures and reduced unnecessary code in the AddChains script for improved readability. - Updated JSON file reading methods to use vm.readFile for consistency. - Enhanced unit tests by removing redundant environment variable setups and improving test data structure. - Consolidated console log statements for better output formatting. * refactor: update AdoptSafeHarbor script to use provided salt for agreement creation - Modified the AdoptSafeHarbor script to directly use the provided salt from the config instead of generating a new one based on the protocol name and timestamp. - This change enhances the clarity and predictability of the agreement creation process. * refactor: update JSON test data and paths for agreement parsing - Replaced the previous test JSON file with a new agreement.json file containing updated protocol details. - Adjusted test cases in AdoptSafeHarborTest to reference the new agreement.json path, ensuring consistency in JSON parsing. - Removed outdated identity and invalid agreement JSON files to streamline test data. * refactor: update JSON key checking in AddChains and AdoptSafeHarbor scripts - Changed the method for checking JSON keys from vm.keyExists to vm.keyExistsJson for improved clarity and consistency in JSON handling. - Adjusted the _parseBountyTerms function in AdoptSafeHarbor to be pure, enhancing its performance and clarity.
1 parent 3b71ed8 commit ed10607

File tree

8 files changed

+918
-0
lines changed

8 files changed

+918
-0
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"agreementAddress": "0x1234567890123456789012345678901234567890",
3+
"chains": [
4+
{
5+
"caip2ChainId": "eip155:137",
6+
"assetRecoveryAddress": "0xAbCdEf1234567890123456789012345678901234",
7+
"accounts": [
8+
{
9+
"accountAddress": "0xAbCdEf1234567890123456789012345678901234",
10+
"childContractScope": 2
11+
}
12+
]
13+
},
14+
{
15+
"caip2ChainId": "eip155:42161",
16+
"assetRecoveryAddress": "0xAbCdEf1234567890123456789012345678901234",
17+
"accounts": [
18+
{
19+
"accountAddress": "0xAbCdEf1234567890123456789012345678901234",
20+
"childContractScope": 1
21+
},
22+
{
23+
"accountAddress": "0x1111111111111111111111111111111111111111",
24+
"childContractScope": 0
25+
}
26+
]
27+
}
28+
]
29+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"protocolName": "Test Protocol",
3+
"agreementURI": "ipfs://QmTestHash",
4+
"contactDetails": [
5+
{
6+
"name": "Security Team",
7+
"contact": "security@test.com"
8+
}
9+
],
10+
"bountyTerms": {
11+
"bountyPercentage": 10,
12+
"bountyCapUSD": 100000,
13+
"aggregateBountyCapUSD": 500000,
14+
"retainable": false,
15+
"identity": 1,
16+
"diligenceRequirements": "KYC Required"
17+
},
18+
"chains": [
19+
{
20+
"caip2ChainId": "eip155:1",
21+
"assetRecoveryAddress": "0x1234567890123456789012345678901234567890",
22+
"accounts": [
23+
{
24+
"accountAddress": "0xAbCdEf1234567890123456789012345678901234",
25+
"childContractScope": 0
26+
}
27+
]
28+
}
29+
]
30+
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity 0.8.30;
3+
4+
import { Script, console } from "forge-std/Script.sol";
5+
import { stdJson } from "forge-std/StdJson.sol";
6+
import { Agreement } from "src/Agreement.sol";
7+
import { Chain as AgreementChain, Account as AgreementAccount, ChildContractScope } from "src/types/AgreementTypes.sol";
8+
9+
/// @title AddChains
10+
/// @notice Script for adding chains to an existing Agreement contract
11+
/// @dev Reads chain details from JSON and calls addChains on the Agreement contract.
12+
/// Validation happens on-chain via the Agreement contract.
13+
contract AddChains is Script {
14+
using stdJson for string;
15+
16+
string private constant DEFAULT_JSON_PATH = "examples/addChains.json";
17+
18+
struct ChainAdditionConfig {
19+
string jsonPath;
20+
address agreement;
21+
}
22+
23+
/// @notice Main entry point - uses environment variables
24+
function run() external {
25+
ChainAdditionConfig memory config = _loadConfigFromEnv();
26+
_executeChainAddition(config);
27+
}
28+
29+
/// @notice Execute with explicit configuration
30+
function run(ChainAdditionConfig calldata config) external {
31+
_executeChainAddition(config);
32+
}
33+
34+
/// @notice Execute with pre-parsed chains
35+
function run(address agreementAddress, AgreementChain[] calldata chains) external {
36+
_executeChainAdditionWithChains(agreementAddress, chains);
37+
}
38+
39+
/// @notice Preview the chains to be added without executing
40+
function preview(string calldata jsonPath) external view returns (AgreementChain[] memory chains) {
41+
string memory json = vm.readFile(jsonPath);
42+
chains = _parseChains(json);
43+
_logChains(chains);
44+
}
45+
46+
function _executeChainAddition(ChainAdditionConfig memory config) internal {
47+
string memory json = vm.readFile(config.jsonPath);
48+
49+
address agreementAddress = config.agreement == address(0)
50+
? json.readAddress(".agreementAddress")
51+
: config.agreement;
52+
53+
AgreementChain[] memory chains = _parseChains(json);
54+
_executeChainAdditionWithChains(agreementAddress, chains);
55+
}
56+
57+
function _executeChainAdditionWithChains(address agreementAddress, AgreementChain[] memory chains) internal {
58+
console.log("Adding", chains.length, "chains to agreement:", agreementAddress);
59+
_logChains(chains);
60+
61+
Agreement agreement = Agreement(agreementAddress);
62+
63+
vm.startBroadcast();
64+
agreement.addChains(chains);
65+
vm.stopBroadcast();
66+
67+
console.log("Chains added successfully!");
68+
}
69+
70+
function _parseChains(string memory json) internal view returns (AgreementChain[] memory chains) {
71+
uint256 count = _getArrayLength(json, ".chains", ".caip2ChainId");
72+
chains = new AgreementChain[](count);
73+
74+
for (uint256 i; i < count; ++i) {
75+
string memory basePath = string.concat(".chains[", _uintToString(i), "]");
76+
chains[i] = AgreementChain({
77+
caip2ChainId: json.readString(string.concat(basePath, ".caip2ChainId")),
78+
assetRecoveryAddress: json.readString(string.concat(basePath, ".assetRecoveryAddress")),
79+
accounts: _parseAccounts(json, _uintToString(i))
80+
});
81+
}
82+
}
83+
84+
function _parseAccounts(
85+
string memory json,
86+
string memory chainIndex
87+
)
88+
internal
89+
view
90+
returns (AgreementAccount[] memory accounts)
91+
{
92+
string memory basePath = string.concat(".chains[", chainIndex, "].accounts");
93+
uint256 count = _getArrayLength(json, basePath, ".accountAddress");
94+
95+
accounts = new AgreementAccount[](count);
96+
for (uint256 i; i < count; ++i) {
97+
string memory indexStr = _uintToString(i);
98+
accounts[i] = AgreementAccount({
99+
accountAddress: json.readString(string.concat(basePath, "[", indexStr, "].accountAddress")),
100+
childContractScope: ChildContractScope(
101+
uint8(json.readUint(string.concat(basePath, "[", indexStr, "].childContractScope")))
102+
)
103+
});
104+
}
105+
}
106+
107+
function _loadConfigFromEnv() internal view returns (ChainAdditionConfig memory config) {
108+
config.jsonPath = vm.envOr("ADD_CHAINS_JSON_PATH", DEFAULT_JSON_PATH);
109+
string memory agreementStr = vm.envOr("AGREEMENT_ADDRESS", string(""));
110+
if (bytes(agreementStr).length > 0) {
111+
config.agreement = vm.parseAddress(agreementStr);
112+
}
113+
}
114+
115+
function _getArrayLength(
116+
string memory json,
117+
string memory arrayPath,
118+
string memory testField
119+
)
120+
internal
121+
view
122+
returns (uint256 count)
123+
{
124+
while (true) {
125+
string memory path = string.concat(arrayPath, "[", _uintToString(count), "]", testField);
126+
if (!vm.keyExistsJson(json, path)) break;
127+
++count;
128+
}
129+
}
130+
131+
function _uintToString(uint256 value) internal pure returns (string memory) {
132+
if (value == 0) return "0";
133+
uint256 temp = value;
134+
uint256 digits;
135+
while (temp != 0) {
136+
++digits;
137+
temp /= 10;
138+
}
139+
bytes memory buffer = new bytes(digits);
140+
while (value != 0) {
141+
--digits;
142+
buffer[digits] = bytes1(uint8(48 + (value % 10)));
143+
value /= 10;
144+
}
145+
return string(buffer);
146+
}
147+
148+
function _logChains(AgreementChain[] memory chains) internal pure {
149+
console.log("Chains to add (", chains.length, "):");
150+
for (uint256 i; i < chains.length; ++i) {
151+
console.log(" [", i, "]", chains[i].caip2ChainId);
152+
}
153+
}
154+
}

0 commit comments

Comments
 (0)