-
Notifications
You must be signed in to change notification settings - Fork 3
Base Sepolia #77
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
Base Sepolia #77
Conversation
WalkthroughThis update adds a new environment variable ( Changes
Sequence Diagram(s)sequenceDiagram
participant TR as Test Runner
participant A as Anvil Instance
participant VC as Viem Client
participant HMC as HatsModulesClient
TR->>A: Start Anvil instance for blockchain simulation
TR->>VC: Initialize Base Sepolia client
TR->>HMC: Retrieve modules for deployment
loop For each module
TR->>HMC: Invoke createNewInstance(module, args)
HMC-->>TR: Return new module instance
TR->>HMC: Verify hat ID and module parameters
HMC-->>TR: Return parameter details
end
Poem
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Also need to update the workflow action here |
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.
Looking good
test/baseSepoliaDeployments.test.ts
Outdated
import type { Module, Registry } from "@hatsprotocol/modules-sdk"; | ||
import "dotenv/config"; | ||
|
||
describe("Base deployments", () => { |
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.
should be "Base Sepolia" 👀
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.
nice catch! fixed in 9dcde05
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.
Actionable comments posted: 1
🧹 Nitpick comments (5)
test/baseSepoliaDeployments.test.ts (5)
35-37
: Consider using an environment variable for the private keyHardcoding private keys in test files can be a security risk, especially if the repository is public. Consider using an environment variable instead.
deployerAccount = privateKeyToAccount( - "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + process.env.TEST_PRIVATE_KEY || "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", );
74-79
: Add more descriptive comment for skipped moduleThe current comment doesn't explain which module is being skipped or why it has dependencies on external contracts. A more descriptive comment would improve code clarity.
- // the unlock module has dependencies on other external contracts + // Skip the Unlock module as it has dependencies on other external contracts that are not available in the test environment
101-135
: Refactor duplicated type conversion logicThe logic for converting types is duplicated between immutable and mutable arguments. Consider extracting this into a reusable function.
+ // Helper function to convert arguments based on their TypeScript type + function convertArgByType(exampleArg: unknown, tsType: string): unknown { + if (tsType === "bigint") { + return BigInt(exampleArg as string); + } else if (tsType === "bigint[]") { + return (exampleArg as Array<string>).map((val) => BigInt(val)); + } else { + return exampleArg; + } + } // prepare immutable args for (let i = 0; i < module.creationArgs.immutable.length; i++) { - let arg: unknown; const exampleArg = module.creationArgs.immutable[i].example; const tsType = solidityToTypescriptType( module.creationArgs.immutable[i].type, ); - if (tsType === "bigint") { - arg = BigInt(exampleArg as string); - } else if (tsType === "bigint[]") { - arg = (exampleArg as Array<string>).map((val) => BigInt(val)); - } else { - arg = exampleArg; - } + const arg = convertArgByType(exampleArg, tsType); immutableArgs.push(arg); } // prepare mutable args for (let i = 0; i < module.creationArgs.mutable.length; i++) { - let arg: unknown; const exampleArg = module.creationArgs.mutable[i].example; const tsType = solidityToTypescriptType( module.creationArgs.mutable[i].type, ); - if (tsType === "bigint") { - arg = BigInt(exampleArg as string); - } else if (tsType === "bigint[]") { - arg = (exampleArg as Array<string>).map((val) => BigInt(val)); - } else { - arg = exampleArg; - } + const arg = convertArgByType(exampleArg, tsType); mutableArgs.push(arg); }
84-84
: Extract chain ID as a constantThe Base Sepolia chain ID is hardcoded as a string. Consider extracting it as a constant for better maintainability.
+ const BASE_SEPOLIA_CHAIN_ID = "84532"; + + // Later in the code: - if (module.deployments[i].chainId === "84532") { + if (module.deployments[i].chainId === BASE_SEPOLIA_CHAIN_ID) {
159-172
: Enhance parameter testing with specific assertionsThe current parameter testing only checks if parameters can be read, but doesn't verify their values. Consider enhancing the test to verify actual parameter values against expected values.
test("Test module parameters", async () => { for (let i = 0; i < instances.length; i++) { let instance = instances[i]; const module = await hatsModulesClient.getModuleByInstance(instance); const res = await hatsModulesClient.getInstanceParameters(instance); if (res === undefined || res.length !== module?.parameters.length) { throw new Error( `Error: could not read all parameters from the instance of module ${module?.name}`, ); } + + // Verify that parameters match expected values + expect(res).toBeDefined(); + expect(res.length).toBe(module?.parameters.length); + + // Additional assertions can be added here to verify specific parameter values + // For example: + // if (module?.name === "SomeSpecificModule") { + // expect(res[0]).toBe(expectedValue); + // } } }, 30000);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Lite
📒 Files selected for processing (1)
test/baseSepoliaDeployments.test.ts
(1 hunks)
🔇 Additional comments (2)
test/baseSepoliaDeployments.test.ts (2)
66-66
: Update comment to reflect correct networkThe comment refers to "goerli" but the test is actually for Base Sepolia deployments.
- // create new module instance for each module which is deployed on goerli + // create new module instance for each module which is deployed on Base Sepolia
1-173
: Overall assessment: Well-structured test file with minor improvements neededThe test file is well-structured and covers important test scenarios for Base Sepolia deployments. The code is generally well-written with clear variable names and logical organization. The suggestions above would enhance maintainability, error handling, and test robustness.
test("Test create all modules", async () => { | ||
const modules = hatsModulesClient.getModules(); | ||
|
||
// create new module instance for each module which is deployed on goerli | ||
for (const [id, module] of Object.entries(modules)) { | ||
console.log(`Testing module: ${module.name}`); | ||
if (module.name === "JokeRace Eligibility") { | ||
continue; | ||
} | ||
|
||
// the unlock module has dependencies on other external contracts | ||
if ( | ||
module.implementationAddress === | ||
"0x4c7803041851f7a17Fc6b5Ff5c911FC748160637" | ||
) { | ||
continue; | ||
} | ||
|
||
// check if module is deployed on base sepolia. If not, then skip | ||
let isOnBaseSepolia = false; | ||
for (let i = 0; i < module.deployments.length; i++) { | ||
if (module.deployments[i].chainId === "84532") { | ||
isOnBaseSepolia = true; | ||
break; | ||
} | ||
} | ||
if (!isOnBaseSepolia) { | ||
continue; | ||
} | ||
|
||
const hatId = module.creationArgs.useHatId | ||
? BigInt( | ||
"0x0000000100000000000000000000000000000000000000000000000000000000", | ||
) | ||
: BigInt("0"); | ||
const immutableArgs: unknown[] = []; | ||
const mutableArgs: unknown[] = []; | ||
|
||
// prepare immutable args | ||
for (let i = 0; i < module.creationArgs.immutable.length; i++) { | ||
let arg: unknown; | ||
const exampleArg = module.creationArgs.immutable[i].example; | ||
const tsType = solidityToTypescriptType( | ||
module.creationArgs.immutable[i].type, | ||
); | ||
if (tsType === "bigint") { | ||
arg = BigInt(exampleArg as string); | ||
} else if (tsType === "bigint[]") { | ||
arg = (exampleArg as Array<string>).map((val) => BigInt(val)); | ||
} else { | ||
arg = exampleArg; | ||
} | ||
|
||
immutableArgs.push(arg); | ||
} | ||
|
||
// prepare mutable args | ||
for (let i = 0; i < module.creationArgs.mutable.length; i++) { | ||
let arg: unknown; | ||
const exampleArg = module.creationArgs.mutable[i].example; | ||
const tsType = solidityToTypescriptType( | ||
module.creationArgs.mutable[i].type, | ||
); | ||
if (tsType === "bigint") { | ||
arg = BigInt(exampleArg as string); | ||
} else if (tsType === "bigint[]") { | ||
arg = (exampleArg as Array<string>).map((val) => BigInt(val)); | ||
} else { | ||
arg = exampleArg; | ||
} | ||
|
||
mutableArgs.push(arg); | ||
} | ||
|
||
// create new module instance | ||
const res = await hatsModulesClient.createNewInstance({ | ||
account: deployerAccount, | ||
moduleId: id, | ||
hatId: hatId, | ||
immutableArgs: immutableArgs, | ||
mutableArgs: mutableArgs, | ||
}); | ||
|
||
instances.push(res.newInstance); | ||
|
||
// check correct hat Id in the new instance | ||
const hatIdResult = await publicClient.readContract({ | ||
address: res.newInstance as Address, | ||
abi: module.abi, | ||
functionName: "hatId", | ||
args: [], | ||
}); | ||
expect(hatIdResult).toBe(hatId); | ||
} | ||
}, 30000); |
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.
🛠️ Refactor suggestion
Add error handling for module instance creation
The test doesn't handle errors that might occur during module instance creation. Consider adding try/catch blocks to provide more informative error messages.
test("Test create all modules", async () => {
const modules = hatsModulesClient.getModules();
// create new module instance for each module which is deployed on Base Sepolia
for (const [id, module] of Object.entries(modules)) {
console.log(`Testing module: ${module.name}`);
if (module.name === "JokeRace Eligibility") {
continue;
}
// Skip the Unlock module as it has dependencies on other external contracts
if (
module.implementationAddress ===
"0x4c7803041851f7a17Fc6b5Ff5c911FC748160637"
) {
continue;
}
// check if module is deployed on base sepolia. If not, then skip
let isOnBaseSepolia = false;
for (let i = 0; i < module.deployments.length; i++) {
if (module.deployments[i].chainId === "84532") {
isOnBaseSepolia = true;
break;
}
}
if (!isOnBaseSepolia) {
continue;
}
const hatId = module.creationArgs.useHatId
? BigInt(
"0x0000000100000000000000000000000000000000000000000000000000000000",
)
: BigInt("0");
const immutableArgs: unknown[] = [];
const mutableArgs: unknown[] = [];
// prepare immutable args
for (let i = 0; i < module.creationArgs.immutable.length; i++) {
// ... [immutable args preparation]
}
// prepare mutable args
for (let i = 0; i < module.creationArgs.mutable.length; i++) {
// ... [mutable args preparation]
}
// create new module instance
+ try {
const res = await hatsModulesClient.createNewInstance({
account: deployerAccount,
moduleId: id,
hatId: hatId,
immutableArgs: immutableArgs,
mutableArgs: mutableArgs,
});
instances.push(res.newInstance);
// check correct hat Id in the new instance
const hatIdResult = await publicClient.readContract({
address: res.newInstance as Address,
abi: module.abi,
functionName: "hatId",
args: [],
});
expect(hatIdResult).toBe(hatId);
+ } catch (error) {
+ console.error(`Failed to create instance for module ${module.name}:`, error);
+ throw new Error(`Failed to create instance for module ${module.name}: ${error instanceof Error ? error.message : String(error)}`);
+ }
}
}, 30000);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
test("Test create all modules", async () => { | |
const modules = hatsModulesClient.getModules(); | |
// create new module instance for each module which is deployed on goerli | |
for (const [id, module] of Object.entries(modules)) { | |
console.log(`Testing module: ${module.name}`); | |
if (module.name === "JokeRace Eligibility") { | |
continue; | |
} | |
// the unlock module has dependencies on other external contracts | |
if ( | |
module.implementationAddress === | |
"0x4c7803041851f7a17Fc6b5Ff5c911FC748160637" | |
) { | |
continue; | |
} | |
// check if module is deployed on base sepolia. If not, then skip | |
let isOnBaseSepolia = false; | |
for (let i = 0; i < module.deployments.length; i++) { | |
if (module.deployments[i].chainId === "84532") { | |
isOnBaseSepolia = true; | |
break; | |
} | |
} | |
if (!isOnBaseSepolia) { | |
continue; | |
} | |
const hatId = module.creationArgs.useHatId | |
? BigInt( | |
"0x0000000100000000000000000000000000000000000000000000000000000000", | |
) | |
: BigInt("0"); | |
const immutableArgs: unknown[] = []; | |
const mutableArgs: unknown[] = []; | |
// prepare immutable args | |
for (let i = 0; i < module.creationArgs.immutable.length; i++) { | |
let arg: unknown; | |
const exampleArg = module.creationArgs.immutable[i].example; | |
const tsType = solidityToTypescriptType( | |
module.creationArgs.immutable[i].type, | |
); | |
if (tsType === "bigint") { | |
arg = BigInt(exampleArg as string); | |
} else if (tsType === "bigint[]") { | |
arg = (exampleArg as Array<string>).map((val) => BigInt(val)); | |
} else { | |
arg = exampleArg; | |
} | |
immutableArgs.push(arg); | |
} | |
// prepare mutable args | |
for (let i = 0; i < module.creationArgs.mutable.length; i++) { | |
let arg: unknown; | |
const exampleArg = module.creationArgs.mutable[i].example; | |
const tsType = solidityToTypescriptType( | |
module.creationArgs.mutable[i].type, | |
); | |
if (tsType === "bigint") { | |
arg = BigInt(exampleArg as string); | |
} else if (tsType === "bigint[]") { | |
arg = (exampleArg as Array<string>).map((val) => BigInt(val)); | |
} else { | |
arg = exampleArg; | |
} | |
mutableArgs.push(arg); | |
} | |
// create new module instance | |
const res = await hatsModulesClient.createNewInstance({ | |
account: deployerAccount, | |
moduleId: id, | |
hatId: hatId, | |
immutableArgs: immutableArgs, | |
mutableArgs: mutableArgs, | |
}); | |
instances.push(res.newInstance); | |
// check correct hat Id in the new instance | |
const hatIdResult = await publicClient.readContract({ | |
address: res.newInstance as Address, | |
abi: module.abi, | |
functionName: "hatId", | |
args: [], | |
}); | |
expect(hatIdResult).toBe(hatId); | |
} | |
}, 30000); | |
test("Test create all modules", async () => { | |
const modules = hatsModulesClient.getModules(); | |
// create new module instance for each module which is deployed on Base Sepolia | |
for (const [id, module] of Object.entries(modules)) { | |
console.log(`Testing module: ${module.name}`); | |
if (module.name === "JokeRace Eligibility") { | |
continue; | |
} | |
// Skip the Unlock module as it has dependencies on other external contracts | |
if ( | |
module.implementationAddress === | |
"0x4c7803041851f7a17Fc6b5Ff5c911FC748160637" | |
) { | |
continue; | |
} | |
// check if module is deployed on base sepolia. If not, then skip | |
let isOnBaseSepolia = false; | |
for (let i = 0; i < module.deployments.length; i++) { | |
if (module.deployments[i].chainId === "84532") { | |
isOnBaseSepolia = true; | |
break; | |
} | |
} | |
if (!isOnBaseSepolia) { | |
continue; | |
} | |
const hatId = module.creationArgs.useHatId | |
? BigInt( | |
"0x0000000100000000000000000000000000000000000000000000000000000000", | |
) | |
: BigInt("0"); | |
const immutableArgs: unknown[] = []; | |
const mutableArgs: unknown[] = []; | |
// prepare immutable args | |
for (let i = 0; i < module.creationArgs.immutable.length; i++) { | |
let arg: unknown; | |
const exampleArg = module.creationArgs.immutable[i].example; | |
const tsType = solidityToTypescriptType( | |
module.creationArgs.immutable[i].type, | |
); | |
if (tsType === "bigint") { | |
arg = BigInt(exampleArg as string); | |
} else if (tsType === "bigint[]") { | |
arg = (exampleArg as Array<string>).map((val) => BigInt(val)); | |
} else { | |
arg = exampleArg; | |
} | |
immutableArgs.push(arg); | |
} | |
// prepare mutable args | |
for (let i = 0; i < module.creationArgs.mutable.length; i++) { | |
let arg: unknown; | |
const exampleArg = module.creationArgs.mutable[i].example; | |
const tsType = solidityToTypescriptType( | |
module.creationArgs.mutable[i].type, | |
); | |
if (tsType === "bigint") { | |
arg = BigInt(exampleArg as string); | |
} else if (tsType === "bigint[]") { | |
arg = (exampleArg as Array<string>).map((val) => BigInt(val)); | |
} else { | |
arg = exampleArg; | |
} | |
mutableArgs.push(arg); | |
} | |
// create new module instance | |
try { | |
const res = await hatsModulesClient.createNewInstance({ | |
account: deployerAccount, | |
moduleId: id, | |
hatId: hatId, | |
immutableArgs: immutableArgs, | |
mutableArgs: mutableArgs, | |
}); | |
instances.push(res.newInstance); | |
// check correct hat Id in the new instance | |
const hatIdResult = await publicClient.readContract({ | |
address: res.newInstance as Address, | |
abi: module.abi, | |
functionName: "hatId", | |
args: [], | |
}); | |
expect(hatIdResult).toBe(hatId); | |
} catch (error) { | |
console.error(`Failed to create instance for module ${module.name}:`, error); | |
throw new Error( | |
`Failed to create instance for module ${module.name}: ${ | |
error instanceof Error ? error.message : String(error) | |
}` | |
); | |
} | |
} | |
}, 30000); |
Summary by CodeRabbit