package verification import ( "context" "crypto/sha256" "encoding/hex" "encoding/json" "fmt" "path/filepath" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/jackc/pgx/v5/pgxpool" ) // Verifier handles contract verification type Verifier struct { db *pgxpool.Pool client *ethclient.Client chainID int } // NewVerifier creates a new contract verifier func NewVerifier(db *pgxpool.Pool, client *ethclient.Client, chainID int) *Verifier { return &Verifier{ db: db, client: client, chainID: chainID, } } // VerifyRequest represents a verification request type VerifyRequest struct { Address string `json:"address"` CompilerVersion string `json:"compiler_version"` OptimizationEnabled bool `json:"optimization_enabled"` OptimizationRuns int `json:"optimization_runs"` EVMVersion string `json:"evm_version"` SourceCode string `json:"source_code"` ConstructorArgs string `json:"constructor_arguments"` VerificationMethod string `json:"verification_method"` } // Verify verifies a contract func (v *Verifier) Verify(ctx context.Context, req *VerifyRequest) (*VerificationResult, error) { // Get deployed bytecode deployedBytecode, err := v.client.CodeAt(ctx, common.HexToAddress(req.Address), nil) if err != nil { return nil, fmt.Errorf("failed to get deployed bytecode: %w", err) } // Compile source code compiledBytecode, err := v.compileSource(req) if err != nil { return nil, fmt.Errorf("failed to compile source: %w", err) } // Compare bytecodes matches := v.compareBytecode(deployedBytecode, compiledBytecode) result := &VerificationResult{ Address: req.Address, Status: "failed", CompilerVersion: req.CompilerVersion, } if matches { result.Status = "verified" // Store verification in database if err := v.storeVerification(ctx, req, result); err != nil { return nil, fmt.Errorf("failed to store verification: %w", err) } } return result, nil } // compileSource compiles Solidity source code func (v *Verifier) compileSource(req *VerifyRequest) ([]byte, error) { // Create temporary directory _ = filepath.Join("/tmp", "verification", hex.EncodeToString(sha256.New().Sum([]byte(req.Address)))[:16]) // Implementation would: // 1. Create standard JSON input // 2. Run solc compiler // 3. Extract bytecode // Simplified for now return nil, fmt.Errorf("compilation not implemented") } // compareBytecode compares deployed bytecode with compiled bytecode func (v *Verifier) compareBytecode(deployed, compiled []byte) bool { // Remove metadata hash (last 53 bytes) from deployed if len(deployed) < 53 { return false } deployed = deployed[:len(deployed)-53] // Compare if len(deployed) != len(compiled) { return false } for i := range deployed { if deployed[i] != compiled[i] { return false } } return true } // storeVerification stores verification result in database func (v *Verifier) storeVerification(ctx context.Context, req *VerifyRequest, result *VerificationResult) error { query := ` INSERT INTO contracts ( chain_id, address, name, compiler_version, optimization_enabled, optimization_runs, evm_version, source_code, abi, constructor_arguments, verification_status, verification_method, verified_at ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, NOW()) ON CONFLICT (chain_id, address) DO UPDATE SET verification_status = $11, verified_at = NOW(), updated_at = NOW() ` // Parse ABI from compilation result (simplified) var abi json.RawMessage _, err := v.db.Exec(ctx, query, v.chainID, req.Address, nil, // name req.CompilerVersion, req.OptimizationEnabled, req.OptimizationRuns, req.EVMVersion, req.SourceCode, abi, req.ConstructorArgs, result.Status, req.VerificationMethod, ) return err } // VerificationResult represents verification result type VerificationResult struct { Address string `json:"address"` Status string `json:"status"` CompilerVersion string `json:"compiler_version"` Error string `json:"error,omitempty"` }