Add full monorepo: virtual-banker, backend, frontend, docs, scripts, deployment
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
154
backend/verification/verifier.go
Normal file
154
backend/verification/verifier.go
Normal file
@@ -0,0 +1,154 @@
|
||||
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"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user