/** * Synor Compiler SDK Examples for C * * Demonstrates smart contract compilation and analysis: * - WASM contract compilation and optimization * - ABI extraction and encoding * - Contract analysis and security scanning * - Validation and verification */ #include #include #include #include // Helper function to create a minimal valid WASM module for testing void create_minimal_wasm(uint8_t** wasm, size_t* wasm_len) { static const uint8_t minimal_wasm[] = { 0x00, 0x61, 0x73, 0x6d, // Magic: \0asm 0x01, 0x00, 0x00, 0x00, // Version: 1 // Type section 0x01, 0x07, 0x01, 0x60, 0x02, 0x7f, 0x7f, 0x01, 0x7f, // Function section 0x03, 0x02, 0x01, 0x00, // Export section 0x07, 0x08, 0x01, 0x04, 0x61, 0x64, 0x64, 0x00, 0x00, // Code section 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b }; *wasm_len = sizeof(minimal_wasm); *wasm = (uint8_t*)malloc(*wasm_len); memcpy(*wasm, minimal_wasm, *wasm_len); } void compile_contract_example(synor_compiler_t* compiler) { printf("=== Contract Compilation ===\n"); synor_error_t err; uint8_t* wasm; size_t wasm_len; create_minimal_wasm(&wasm, &wasm_len); synor_compile_options_t options = { .optimization_level = SYNOR_OPTIMIZATION_SIZE, .use_wasm_opt = true, .validate = true, .extract_metadata = true, .generate_abi = true, .strip_options = { .strip_debug = true, .strip_producers = true, .strip_names = true, .strip_custom = true, .strip_unused = true } }; synor_compile_result_t* result = NULL; err = synor_compile(compiler, wasm, wasm_len, &options, &result); free(wasm); if (err != SYNOR_OK) { fprintf(stderr, "Failed to compile contract\n"); return; } printf("Compilation result:\n"); printf(" Contract ID: %s\n", synor_compile_result_get_contract_id(result)); printf(" Code hash: %s\n", synor_compile_result_get_code_hash(result)); printf(" Original size: %zu bytes\n", synor_compile_result_get_original_size(result)); printf(" Optimized size: %zu bytes\n", synor_compile_result_get_optimized_size(result)); printf(" Size reduction: %.1f%%\n", synor_compile_result_get_size_reduction(result)); printf(" Estimated deploy gas: %lu\n", synor_compile_result_get_estimated_deploy_gas(result)); // Get metadata if available synor_contract_metadata_t* metadata = synor_compile_result_get_metadata(result); if (metadata) { printf("\nMetadata:\n"); printf(" Name: %s\n", synor_metadata_get_name(metadata)); printf(" Version: %s\n", synor_metadata_get_version(metadata)); printf(" SDK Version: %s\n", synor_metadata_get_sdk_version(metadata)); } // Get ABI if available synor_contract_abi_t* abi = synor_compile_result_get_abi(result); if (abi) { printf("\nABI:\n"); printf(" Functions: %zu\n", synor_abi_get_function_count(abi)); printf(" Events: %zu\n", synor_abi_get_event_count(abi)); printf(" Errors: %zu\n", synor_abi_get_error_count(abi)); } synor_compile_result_free(result); printf("\n"); } void compilation_modes_example(synor_compiler_t* compiler) { printf("=== Compilation Modes ===\n"); synor_error_t err; uint8_t* wasm; size_t wasm_len; create_minimal_wasm(&wasm, &wasm_len); // Development mode: fast compilation, debugging support printf("Development mode:\n"); synor_compile_result_t* dev_result = NULL; err = synor_contracts_compile_dev(compiler, wasm, wasm_len, &dev_result); if (err == SYNOR_OK) { printf(" Size: %zu bytes\n", synor_compile_result_get_optimized_size(dev_result)); printf(" Optimization: none\n"); } // Production mode: maximum optimization printf("\nProduction mode:\n"); synor_compile_result_t* prod_result = NULL; err = synor_contracts_compile_production(compiler, wasm, wasm_len, &prod_result); if (err == SYNOR_OK) { printf(" Size: %zu bytes\n", synor_compile_result_get_optimized_size(prod_result)); printf(" Optimization: aggressive\n"); if (dev_result) { printf(" Size savings: %zu bytes\n", synor_compile_result_get_optimized_size(dev_result) - synor_compile_result_get_optimized_size(prod_result)); } synor_compile_result_free(prod_result); } if (dev_result) synor_compile_result_free(dev_result); // Custom optimization levels printf("\nOptimization levels:\n"); synor_optimization_level_t levels[] = { SYNOR_OPTIMIZATION_NONE, SYNOR_OPTIMIZATION_BASIC, SYNOR_OPTIMIZATION_SIZE, SYNOR_OPTIMIZATION_AGGRESSIVE }; const char* level_names[] = {"NONE", "BASIC", "SIZE", "AGGRESSIVE"}; for (int i = 0; i < 4; i++) { synor_compile_options_t options = { .optimization_level = levels[i] }; synor_compile_result_t* result = NULL; err = synor_compile(compiler, wasm, wasm_len, &options, &result); if (err == SYNOR_OK) { printf(" %s: %zu bytes\n", level_names[i], synor_compile_result_get_optimized_size(result)); synor_compile_result_free(result); } } free(wasm); printf("\n"); } void abi_example(synor_compiler_t* compiler) { printf("=== ABI Operations ===\n"); synor_error_t err; uint8_t* wasm; size_t wasm_len; create_minimal_wasm(&wasm, &wasm_len); // Extract ABI from WASM synor_contract_abi_t* abi = NULL; err = synor_abi_extract(compiler, wasm, wasm_len, &abi); free(wasm); if (err != SYNOR_OK) { fprintf(stderr, "Failed to extract ABI\n"); return; } printf("Contract: %s\n", synor_abi_get_name(abi)); printf("Version: %s\n", synor_abi_get_version(abi)); // List functions size_t func_count = synor_abi_get_function_count(abi); if (func_count > 0) { printf("\nFunctions:\n"); for (size_t i = 0; i < func_count; i++) { synor_abi_function_t* func = synor_abi_get_function(abi, i); char inputs[256] = ""; size_t input_count = synor_abi_function_get_input_count(func); for (size_t j = 0; j < input_count; j++) { synor_abi_param_t* param = synor_abi_function_get_input(func, j); char temp[64]; snprintf(temp, sizeof(temp), "%s: %s%s", synor_abi_param_get_name(param), synor_abi_param_get_type_name(param), j < input_count - 1 ? ", " : ""); strncat(inputs, temp, sizeof(inputs) - strlen(inputs) - 1); } char outputs[128] = "void"; size_t output_count = synor_abi_function_get_output_count(func); if (output_count > 0) { outputs[0] = '\0'; for (size_t j = 0; j < output_count; j++) { synor_abi_param_t* param = synor_abi_function_get_output(func, j); char temp[64]; snprintf(temp, sizeof(temp), "%s%s", synor_abi_param_get_type_name(param), j < output_count - 1 ? ", " : ""); strncat(outputs, temp, sizeof(outputs) - strlen(outputs) - 1); } } char modifiers[32] = ""; if (synor_abi_function_is_view(func)) strcat(modifiers, "view "); if (synor_abi_function_is_payable(func)) strcat(modifiers, "payable"); printf(" %s(%s) -> %s %s\n", synor_abi_function_get_name(func), inputs, outputs, modifiers); printf(" Selector: %s\n", synor_abi_function_get_selector(func)); } } // List events size_t event_count = synor_abi_get_event_count(abi); if (event_count > 0) { printf("\nEvents:\n"); for (size_t i = 0; i < event_count; i++) { synor_abi_event_t* event = synor_abi_get_event(abi, i); char params[256] = ""; size_t param_count = synor_abi_event_get_param_count(event); for (size_t j = 0; j < param_count; j++) { synor_abi_event_param_t* param = synor_abi_event_get_param(event, j); char temp[64]; snprintf(temp, sizeof(temp), "%s%s: %s%s", synor_abi_event_param_is_indexed(param) ? "indexed " : "", synor_abi_event_param_get_name(param), synor_abi_event_param_get_type_name(param), j < param_count - 1 ? ", " : ""); strncat(params, temp, sizeof(params) - strlen(params) - 1); } printf(" %s(%s)\n", synor_abi_event_get_name(event), params); printf(" Topic: %s\n", synor_abi_event_get_topic(event)); } } // Encode a function call if (func_count > 0) { synor_abi_function_t* func = synor_abi_get_function(abi, 0); const char* args[] = {"arg1", "arg2"}; uint8_t* encoded; size_t encoded_len; err = synor_abi_encode_call(compiler, func, args, 2, &encoded, &encoded_len); if (err == SYNOR_OK) { printf("\nEncoded call to %s: ", synor_abi_function_get_name(func)); for (size_t i = 0; i < encoded_len && i < 20; i++) { printf("%02x", encoded[i]); } printf("...\n"); // Decode a result char** decoded; size_t decoded_count; err = synor_abi_decode_result(compiler, func, encoded, encoded_len, &decoded, &decoded_count); if (err == SYNOR_OK) { printf("Decoded result: "); for (size_t i = 0; i < decoded_count; i++) { printf("%s%s", decoded[i], i < decoded_count - 1 ? ", " : ""); } printf("\n"); synor_string_array_free(decoded, decoded_count); } free(encoded); } } synor_abi_free(abi); printf("\n"); } void analysis_example(synor_compiler_t* compiler) { printf("=== Contract Analysis ===\n"); synor_error_t err; uint8_t* wasm; size_t wasm_len; create_minimal_wasm(&wasm, &wasm_len); // Full analysis synor_contract_analysis_t* analysis = NULL; err = synor_analysis_analyze(compiler, wasm, wasm_len, &analysis); if (err != SYNOR_OK) { fprintf(stderr, "Failed to analyze contract\n"); free(wasm); return; } // Size breakdown synor_size_breakdown_t* size = synor_analysis_get_size_breakdown(analysis); if (size) { printf("Size breakdown:\n"); printf(" Code: %zu bytes\n", synor_size_breakdown_get_code(size)); printf(" Data: %zu bytes\n", synor_size_breakdown_get_data(size)); printf(" Functions: %zu bytes\n", synor_size_breakdown_get_functions(size)); printf(" Memory: %zu bytes\n", synor_size_breakdown_get_memory(size)); printf(" Exports: %zu bytes\n", synor_size_breakdown_get_exports(size)); printf(" Imports: %zu bytes\n", synor_size_breakdown_get_imports(size)); printf(" Total: %zu bytes\n", synor_size_breakdown_get_total(size)); } // Function analysis size_t func_count = synor_analysis_get_function_count(analysis); if (func_count > 0) { printf("\nFunction analysis:\n"); for (size_t i = 0; i < 5 && i < func_count; i++) { synor_function_analysis_t* func = synor_analysis_get_function(analysis, i); printf(" %s:\n", synor_function_analysis_get_name(func)); printf(" Size: %zu bytes\n", synor_function_analysis_get_size(func)); printf(" Instructions: %zu\n", synor_function_analysis_get_instruction_count(func)); printf(" Locals: %zu\n", synor_function_analysis_get_local_count(func)); printf(" Exported: %s\n", synor_function_analysis_is_exported(func) ? "true" : "false"); printf(" Estimated gas: %lu\n", synor_function_analysis_get_estimated_gas(func)); } } // Import analysis size_t import_count = synor_analysis_get_import_count(analysis); if (import_count > 0) { printf("\nImports:\n"); for (size_t i = 0; i < import_count; i++) { synor_import_analysis_t* imp = synor_analysis_get_import(analysis, i); printf(" %s.%s (%s)\n", synor_import_analysis_get_module(imp), synor_import_analysis_get_name(imp), synor_import_analysis_get_kind(imp)); } } // Gas analysis synor_gas_analysis_t* gas = synor_analysis_get_gas_analysis(analysis); if (gas) { printf("\nGas analysis:\n"); printf(" Deployment: %lu\n", synor_gas_analysis_get_deployment_gas(gas)); printf(" Memory init: %lu\n", synor_gas_analysis_get_memory_init_gas(gas)); printf(" Data section: %lu\n", synor_gas_analysis_get_data_section_gas(gas)); } synor_analysis_free(analysis); // Extract metadata synor_contract_metadata_t* metadata = NULL; err = synor_analysis_extract_metadata(compiler, wasm, wasm_len, &metadata); if (err == SYNOR_OK) { printf("\nContract metadata:\n"); printf(" Name: %s\n", synor_metadata_get_name(metadata)); printf(" Version: %s\n", synor_metadata_get_version(metadata)); printf(" Build timestamp: %s\n", synor_metadata_get_build_timestamp(metadata)); synor_metadata_free(metadata); } // Estimate deployment gas uint64_t gas_estimate; err = synor_analysis_estimate_deploy_gas(compiler, wasm, wasm_len, &gas_estimate); if (err == SYNOR_OK) { printf("\nEstimated deployment gas: %lu\n", gas_estimate); } free(wasm); printf("\n"); } void validation_example(synor_compiler_t* compiler) { printf("=== Contract Validation ===\n"); synor_error_t err; uint8_t* wasm; size_t wasm_len; create_minimal_wasm(&wasm, &wasm_len); // Full validation synor_validation_result_t* result = NULL; err = synor_validation_validate(compiler, wasm, wasm_len, &result); if (err == SYNOR_OK) { printf("Valid: %s\n", synor_validation_result_is_valid(result) ? "true" : "false"); printf("Exports: %zu\n", synor_validation_result_get_export_count(result)); printf("Imports: %zu\n", synor_validation_result_get_import_count(result)); printf("Functions: %zu\n", synor_validation_result_get_function_count(result)); printf("Memory pages: %zu\n", synor_validation_result_get_memory_pages(result)); // Print errors size_t error_count = synor_validation_result_get_error_count(result); if (error_count > 0) { printf("\nValidation errors:\n"); for (size_t i = 0; i < error_count; i++) { synor_validation_error_t* error = synor_validation_result_get_error(result, i); printf(" [%s] %s\n", synor_validation_error_get_code(error), synor_validation_error_get_message(error)); const char* location = synor_validation_error_get_location(error); if (location) { printf(" at %s\n", location); } } } // Print warnings size_t warning_count = synor_validation_result_get_warning_count(result); if (warning_count > 0) { printf("\nWarnings:\n"); for (size_t i = 0; i < warning_count; i++) { printf(" %s\n", synor_validation_result_get_warning(result, i)); } } synor_validation_result_free(result); } // Quick validation bool is_valid; err = synor_validation_is_valid(compiler, wasm, wasm_len, &is_valid); printf("\nQuick validation: %s\n", is_valid ? "true" : "false"); // Get validation errors only synor_validation_error_list_t* errors = NULL; err = synor_validation_get_errors(compiler, wasm, wasm_len, &errors); if (err == SYNOR_OK) { printf("Error count: %zu\n", synor_validation_error_list_count(errors)); synor_validation_error_list_free(errors); } // Validate required exports const char* required[] = {"init", "execute", "query"}; bool has_required; err = synor_validation_validate_exports(compiler, wasm, wasm_len, required, 3, &has_required); printf("Has required exports: %s\n", has_required ? "true" : "false"); // Validate memory constraints bool memory_valid; err = synor_validation_validate_memory(compiler, wasm, wasm_len, 16, &memory_valid); printf("Memory within 16 pages: %s\n", memory_valid ? "true" : "false"); free(wasm); printf("\n"); } void security_example(synor_compiler_t* compiler) { printf("=== Security Scanning ===\n"); synor_error_t err; uint8_t* wasm; size_t wasm_len; create_minimal_wasm(&wasm, &wasm_len); synor_security_scan_result_t* security = NULL; err = synor_analysis_security_scan(compiler, wasm, wasm_len, &security); free(wasm); if (err != SYNOR_OK) { fprintf(stderr, "Failed to scan contract\n"); return; } printf("Security score: %d/100\n", synor_security_scan_get_score(security)); size_t issue_count = synor_security_scan_get_issue_count(security); if (issue_count > 0) { printf("\nSecurity issues:\n"); for (size_t i = 0; i < issue_count; i++) { synor_security_issue_t* issue = synor_security_scan_get_issue(security, i); const char* severity = synor_security_issue_get_severity(issue); const char* icon; if (strcmp(severity, "critical") == 0) icon = "[CRIT]"; else if (strcmp(severity, "high") == 0) icon = "[HIGH]"; else if (strcmp(severity, "medium") == 0) icon = "[MED]"; else if (strcmp(severity, "low") == 0) icon = "[LOW]"; else icon = "[???]"; printf("%s [%s] %s\n", icon, synor_security_issue_get_severity(issue), synor_security_issue_get_type(issue)); printf(" %s\n", synor_security_issue_get_description(issue)); const char* location = synor_security_issue_get_location(issue); if (location) { printf(" at %s\n", location); } } } else { printf("No security issues found!\n"); } size_t rec_count = synor_security_scan_get_recommendation_count(security); if (rec_count > 0) { printf("\nRecommendations:\n"); for (size_t i = 0; i < rec_count; i++) { printf(" • %s\n", synor_security_scan_get_recommendation(security, i)); } } synor_security_scan_result_free(security); printf("\n"); } int main(int argc, char** argv) { synor_error_t err; // Initialize client synor_compiler_config_t config = { .api_key = getenv("SYNOR_API_KEY") ? getenv("SYNOR_API_KEY") : "your-api-key", .endpoint = "https://compiler.synor.io/v1", .timeout_ms = 60000, .retries = 3, .debug = false, .default_optimization_level = SYNOR_OPTIMIZATION_SIZE, .max_contract_size = 256 * 1024, .use_wasm_opt = true, .validate = true, .extract_metadata = true, .generate_abi = true }; synor_compiler_t* compiler = NULL; err = synor_compiler_init(&config, &compiler); if (err != SYNOR_OK) { fprintf(stderr, "Failed to initialize compiler client: %s\n", synor_error_string(err)); return 1; } // Check service health bool healthy; err = synor_compiler_health_check(compiler, &healthy); printf("Service healthy: %s\n\n", healthy ? "true" : "false"); // Run examples compile_contract_example(compiler); compilation_modes_example(compiler); abi_example(compiler); analysis_example(compiler); validation_example(compiler); security_example(compiler); // Cleanup synor_compiler_free(compiler); return 0; }