155 lines
4.1 KiB
Go
155 lines
4.1 KiB
Go
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"`
|
|
}
|
|
|