Skip to content

Commit

Permalink
feat: factory deployment + small refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
JordyRo1 committed Jan 22, 2025
1 parent 26e137d commit 2e3ca93
Show file tree
Hide file tree
Showing 5 changed files with 317 additions and 10 deletions.
248 changes: 248 additions & 0 deletions scripts/configs/pragma_sepolia.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
{
"contracts": {
"merkleroot_multisig_ism": {
"name": "merkleroot_multisig_ism",
"constructor": {
"owner": {
"type": "ContractAddress",
"value": "$OWNER_ADDRESS"
},
"validators": {
"type": "Span<felt252>",
"value": [
"0x0000000000000000000000000000000000000000000000000000000000000002"
]
},
"threshold": {
"type": "u32",
"value": "1"
}
}
},
"protocol_fee": {
"name": "protocol_fee",
"constructor": {
"max_protocol_fee_low": {
"type": "u128",
"value": "1000000000000000000"
},
"max_protocol_fee_high": {
"type": "u128",
"value": "0"
},
"protocol_fee_low": {
"type": "u128",
"value": "10000000000000000"
},
"protocol_fee_high": {
"type": "u128",
"value": "0"
},
"beneficiary": {
"type": "ContractAddress",
"value": "$BENEFICIARY_ADDRESS"
},
"owner": {
"type": "ContractAddress",
"value": "$OWNER_ADDRESS"
},
"token_address": {
"type": "ContractAddress",
"value": "0x049D36570D4e46f48e99674bd3fcc84644DdD6b96F7C741B1562B82f9e004dC7"
}
}
},
"merkle_tree_hook": {
"name": "merkle_tree_hook",
"constructor": {
"mailbox": {
"type": "ContractAddress",
"value": "$mailbox"
},
"owner": {
"type": "ContractAddress",
"value": "$OWNER_ADDRESS"
}
}
},
"noop_ism": {
"name": "noop_ism",
"constructor": {}
},
"hook": {
"name": "hook",
"constructor": {}
},
"pausable_ism": {
"name": "pausable_ism",
"constructor": {
"owner": {
"type": "ContractAddress",
"value": "$OWNER_ADDRESS"
}
}
},
"trusted_relayer_ism": {
"name": "trusted_relayer_ism",
"constructor": {
"mailbox": {
"type": "ContractAddress",
"value": "$mailbox"
},
"trusted_relayer": {
"type": "ContractAddress",
"value": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
}
},
"mailbox": {
"name": "mailbox",
"constructor": {
"local_domain": {
"type": "u32",
"value": "6363709"
},
"owner": {
"type": "ContractAddress",
"value": "$OWNER_ADDRESS"
},
"default_ism": {
"type": "ContractAddress",
"value": "$noop_ism"
},
"default_hook": {
"type": "ContractAddress",
"value": "$hook"
},
"required_hook": {
"type": "ContractAddress",
"value": "$hook"
}
}
},
"validator_announce": {
"name": "validator_announce",
"constructor": {
"mailbox": {
"type": "ContractAddress",
"value": "$mailbox"
},
"owner": {
"type": "ContractAddress",
"value": "$OWNER_ADDRESS"
}
}
},
"aggregation": {
"name": "aggregation",
"constructor": {
"owner": {
"type": "ContractAddress",
"value": "$OWNER_ADDRESS"
},
"modules": {
"type": "Span<felt252>",
"value": [
"0x0000000000000000000000000000000000000000000000000000000000000002"
]
},
"threshold": {
"type": "u32",
"value": "1"
}
}
},
"messageid_multisig_ism": {
"name": "messageid_multisig_ism",
"constructor": {
"owner": {
"type": "ContractAddress",
"value": "$OWNER_ADDRESS"
},
"validators": {
"type": "Span<felt252>",
"value": [
"0x0000000000000000000000000000000000000000000000000000000000000003"
]
},
"threshold": {
"type": "u32",
"value": "1"
}
}
},
"default_fallback_routing_ism": {
"name": "default_fallback_routing_ism",
"constructor": {
"owner": {
"type": "ContractAddress",
"value": "$OWNER_ADDRESS"
},
"mailbox": {
"type": "ContractAddress",
"value": "$mailbox"
}
}
},
"domain_routing_ism": {
"name": "domain_routing_ism",
"constructor": {
"owner": {
"type": "ContractAddress",
"value": "$OWNER_ADDRESS"
}
}
},
"domain_routing_hook": {
"name": "domain_routing_hook",
"constructor": {
"mailbox": {
"type": "ContractAddress",
"value": "$mailbox"
},
"owner": {
"type": "ContractAddress",
"value": "$OWNER_ADDRESS"
},
"token_address": {
"type": "ContractAddress",
"value": "0x049D36570D4e46f48e99674bd3fcc84644DdD6b96F7C741B1562B82f9e004dC7"
}
}
},
"XERC20Factory": {
"name": "XERC20Factory",
"constructor": {
"xerc20_class_hash": {
"type": "ClassHash",
"value": "$XERC20_CLASS_HASH"
},
"lockbox_class_hash": {
"type": "ClassHash",
"value": "$LOCKBOX_CLASS_HASH"
},
"owner": {
"type": "ContractAddress",
"value": "$OWNER_ADDRESS"
}
}
}
},
"deploymentOrder": [
"merkleroot_multisig_ism",
"messageid_multisig_ism",
"domain_routing_ism",
"noop_ism",
"pausable_ism",
"aggregation",
"protocol_fee",
"hook",
"mailbox",
"merkle_tree_hook",
"default_fallback_routing_ism",
"trusted_relayer_ism",
"validator_announce",
"domain_routing_hook",
"XERC20Factory"
]
}
63 changes: 53 additions & 10 deletions scripts/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ dotenv.config();

const BUILD_PATH = "../cairo/target/dev/contracts";
const MOCK_BUILD_PATH = "../cairo/target/dev/mocks";
const TOKEN_BUILD_PATH= "../xerc20/target/dev/xerc20"
const ACCOUNT_ADDRESS = process.env.ACCOUNT_ADDRESS;
const CONFIGS_DIR = 'configs';
const DEPLOYMENTS_DIR = 'deployments';
Expand All @@ -38,7 +39,7 @@ function getConfigPath(network: string): string {
throw new Error('NETWORK environment variable is not set');
}

const configFileName = `${network.toLowerCase()}.json`;
const configFileName = `pragma_${network.toLowerCase()}.json`;
const configPath = path.join(CONFIGS_DIR, configFileName);

if (!fs.existsSync(configPath)) {
Expand Down Expand Up @@ -70,12 +71,15 @@ function ensureNetworkDirectory(network: string): string {
function findContractFile(name: string, suffix: string): string {
const mainPath = `${BUILD_PATH}_${name}${suffix}`;
const mockPath = `${MOCK_BUILD_PATH}_${name}${suffix}`;
const xerc20Path = `${TOKEN_BUILD_PATH}_${name}${suffix}`;

if (fs.existsSync(mainPath)) {
return mainPath;
} else if (fs.existsSync(mockPath)) {
console.log(`Using mock contract for ${name} from ${mockPath}`);
return mockPath;
} else if (fs.existsSync(xerc20Path)) {
return xerc20Path;
}

throw new Error(`Contract file not found for ${name} with suffix ${suffix} in either ${BUILD_PATH} or ${MOCK_BUILD_PATH}`);
Expand All @@ -93,26 +97,48 @@ function getCompiledContractCasm(name: string): any {
return json.parse(fs.readFileSync(contractPath).toString("ascii"));
}

function processConstructorArgs(args: Record<string, { type: string; value: string | string[] }>, deployedContracts: DeployedContracts): any {
return Object.entries(args).reduce((acc, [key, { type, value }]) => {
async function processConstructorArgs(
args: Record<string, { type: string; value: string | string[] }>,
deployedContracts: DeployedContracts,
account: Account
): Promise<any> {

if (!ACCOUNT_ADDRESS) {
throw new Error('ACCOUNT_ADDRESS environment variable is not set');
}

if (!process.env.BENEFICIARY_ADDRESS) {
throw new Error('BENEFICIARY_ADDRESS environment variable is not set');
}

const processedArgs: Record<string, string | string[]> = {};

for (const [key, { type, value }] of Object.entries(args)) {
if (typeof value === 'string' && value.startsWith('$')) {
if (value === '$OWNER_ADDRESS') {
acc[key] = ACCOUNT_ADDRESS;
processedArgs[key] = ACCOUNT_ADDRESS as string;
} else if (value === '$BENEFICIARY_ADDRESS') {
acc[key] = process.env.BENEFICIARY_ADDRESS;
processedArgs[key] = process.env.BENEFICIARY_ADDRESS as string;
} else if (value === '$XERC20_CLASS_HASH') {
const xerc20ClassHash = await declareContract(account, 'XERC20');
processedArgs[key] = xerc20ClassHash;
} else if (value === '$LOCKBOX_CLASS_HASH') {
const lockboxClassHash = await declareContract(account, 'XERC20Lockbox');
processedArgs[key] = lockboxClassHash;
} else {
const contractName = value.slice(1);
if (deployedContracts[contractName]) {
acc[key] = deployedContracts[contractName];
processedArgs[key] = deployedContracts[contractName];
} else {
throw new Error(`Contract ${contractName} not yet deployed, required for ${key}`);
}
}
} else {
acc[key] = value;
processedArgs[key] = value;
}
return acc;
}, {} as any);
}

return processedArgs;
}

async function deployContract(
Expand All @@ -125,7 +151,7 @@ async function deployContract(

const compiledContract = getCompiledContract(contractName);
const casm = getCompiledContractCasm(contractName);
const processedArgs = processConstructorArgs(constructorArgs, deployedContracts);
const processedArgs = await processConstructorArgs(constructorArgs, deployedContracts, account);
const constructorCalldata = CallData.compile(processedArgs);
const params: ContractFactoryParams = {
compiledContract,
Expand All @@ -141,6 +167,23 @@ async function deployContract(
return contract.address;
}


async function declareContract(account: Account, name: string): Promise<string> {
console.log(`Declaring contract ${name}...`);
const compiledContract = getCompiledContract(name);
const casm = getCompiledContractCasm(name);

const declareResponse = await account.declareIfNot({
contract: compiledContract,
casm
});

console.log(`Contract ${name} declared with class hash:`, declareResponse.class_hash);

return declareResponse.class_hash;
}


async function deployContracts(): Promise<DeployedContracts> {
try {
if (!NETWORK) {
Expand Down
File renamed without changes.
15 changes: 15 additions & 0 deletions scripts/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"outDir": "./dist"
},
"include": ["./**/*.ts"],
"exclude": ["node_modules"]
}
1 change: 1 addition & 0 deletions xerc20/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v

[[target.starknet-contract]]
sierra = true
casm = true

[tool.fmt]
sort-module-level-items = true
Expand Down

0 comments on commit 2e3ca93

Please sign in to comment.