package main import ( "encoding/json" "fmt" "strconv" "time" "github.com/hyperledger/fabric-contract-api-go/contractapi" ) // ReserveManagerContract provides functions for managing reserves type ReserveManagerContract struct { contractapi.Contract } // Reserve represents a reserve backing tokenized assets type Reserve struct { ReserveID string `json:"reserveId"` AssetType string `json:"assetType"` // EUR, USD, etc. TotalAmount string `json:"totalAmount"` BackedAmount string `json:"backedAmount"` // Amount already backing tokens AvailableAmount string `json:"availableAmount"` // Available for new tokens Attestor string `json:"attestor"` AttestationHash string `json:"attestationHash"` LastVerified string `json:"lastVerified"` CreatedAt string `json:"createdAt"` UpdatedAt string `json:"updatedAt"` } // AttestationRequest represents a request to attest to reserves type AttestationRequest struct { ReserveID string `json:"reserveId"` AssetType string `json:"assetType"` TotalAmount string `json:"totalAmount"` Attestor string `json:"attestor"` AttestationHash string `json:"attestationHash"` Proof string `json:"proof"` } // VerifyReserve verifies that reserves are sufficient for tokenization func (s *ReserveManagerContract) VerifyReserve(ctx contractapi.TransactionContextInterface, reserveID string, amount string) (bool, error) { reserveJSON, err := ctx.GetStub().GetState(reserveID) if err != nil { return false, fmt.Errorf("failed to read reserve from world state: %v", err) } if reserveJSON == nil { return false, fmt.Errorf("reserve %s does not exist", reserveID) } var reserve Reserve err = json.Unmarshal(reserveJSON, &reserve) if err != nil { return false, err } // Parse amounts requestAmount, err := strconv.ParseFloat(amount, 64) if err != nil { return false, fmt.Errorf("invalid amount: %v", err) } availableAmount, err := strconv.ParseFloat(reserve.AvailableAmount, 64) if err != nil { return false, fmt.Errorf("invalid available amount: %v", err) } // Check if sufficient reserve available if requestAmount > availableAmount { return false, fmt.Errorf("insufficient reserve: requested %f, available %f", requestAmount, availableAmount) } // Verify attestation is recent (within 24 hours) lastVerified, err := time.Parse(time.RFC3339, reserve.LastVerified) if err != nil { return false, fmt.Errorf("invalid last verified timestamp: %v", err) } if time.Since(lastVerified) > 24*time.Hour { return false, fmt.Errorf("reserve attestation is stale (older than 24 hours)") } return true, nil } // CreateReserve creates a new reserve with attestation func (s *ReserveManagerContract) CreateReserve(ctx contractapi.TransactionContextInterface, requestJSON string) error { var request AttestationRequest err := json.Unmarshal([]byte(requestJSON), &request) if err != nil { return fmt.Errorf("failed to unmarshal attestation request: %v", err) } // Check if reserve already exists existing, err := ctx.GetStub().GetState(request.ReserveID) if err != nil { return fmt.Errorf("failed to read from world state: %v", err) } if existing != nil { return fmt.Errorf("reserve %s already exists", request.ReserveID) } // Parse total amount totalAmount, err := strconv.ParseFloat(request.TotalAmount, 64) if err != nil { return fmt.Errorf("invalid total amount: %v", err) } // Create reserve reserve := Reserve{ ReserveID: request.ReserveID, AssetType: request.AssetType, TotalAmount: request.TotalAmount, BackedAmount: "0.00", AvailableAmount: request.TotalAmount, Attestor: request.Attestor, AttestationHash: request.AttestationHash, LastVerified: time.Now().Format(time.RFC3339), CreatedAt: time.Now().Format(time.RFC3339), UpdatedAt: time.Now().Format(time.RFC3339), } reserveJSON, err := json.Marshal(reserve) if err != nil { return err } err = ctx.GetStub().PutState(request.ReserveID, reserveJSON) if err != nil { return fmt.Errorf("failed to put reserve to world state: %v", err) } // Emit event eventPayload := fmt.Sprintf(`{"reserveId":"%s","action":"create","amount":"%s","attestor":"%s"}`, request.ReserveID, request.TotalAmount, request.Attestor) err = ctx.GetStub().SetEvent("ReserveCreated", []byte(eventPayload)) if err != nil { return fmt.Errorf("failed to emit event: %v", err) } return nil } // AttestReserve updates reserve attestation func (s *ReserveManagerContract) AttestReserve(ctx contractapi.TransactionContextInterface, requestJSON string) error { var request AttestationRequest err := json.Unmarshal([]byte(requestJSON), &request) if err != nil { return fmt.Errorf("failed to unmarshal attestation request: %v", err) } // Get existing reserve reserveJSON, err := ctx.GetStub().GetState(request.ReserveID) if err != nil { return fmt.Errorf("failed to read reserve from world state: %v", err) } if reserveJSON == nil { return fmt.Errorf("reserve %s does not exist", request.ReserveID) } var reserve Reserve err = json.Unmarshal(reserveJSON, &reserve) if err != nil { return err } // Update attestation reserve.Attestor = request.Attestor reserve.AttestationHash = request.AttestationHash reserve.TotalAmount = request.TotalAmount // Recalculate available amount totalAmount, err := strconv.ParseFloat(request.TotalAmount, 64) if err != nil { return fmt.Errorf("invalid total amount: %v", err) } backedAmount, err := strconv.ParseFloat(reserve.BackedAmount, 64) if err != nil { return fmt.Errorf("invalid backed amount: %v", err) } availableAmount := totalAmount - backedAmount reserve.AvailableAmount = fmt.Sprintf("%.2f", availableAmount) reserve.LastVerified = time.Now().Format(time.RFC3339) reserve.UpdatedAt = time.Now().Format(time.RFC3339) updatedJSON, err := json.Marshal(reserve) if err != nil { return err } err = ctx.GetStub().PutState(request.ReserveID, updatedJSON) if err != nil { return fmt.Errorf("failed to update reserve in world state: %v", err) } // Emit event eventPayload := fmt.Sprintf(`{"reserveId":"%s","action":"attest","amount":"%s","attestor":"%s"}`, request.ReserveID, request.TotalAmount, request.Attestor) err = ctx.GetStub().SetEvent("ReserveAttested", []byte(eventPayload)) if err != nil { return fmt.Errorf("failed to emit event: %v", err) } return nil } // AllocateReserve allocates reserve amount for token backing func (s *ReserveManagerContract) AllocateReserve(ctx contractapi.TransactionContextInterface, reserveID string, amount string) error { reserveJSON, err := ctx.GetStub().GetState(reserveID) if err != nil { return fmt.Errorf("failed to read reserve from world state: %v", err) } if reserveJSON == nil { return fmt.Errorf("reserve %s does not exist", reserveID) } var reserve Reserve err = json.Unmarshal(reserveJSON, &reserve) if err != nil { return err } // Parse amounts allocateAmount, err := strconv.ParseFloat(amount, 64) if err != nil { return fmt.Errorf("invalid amount: %v", err) } availableAmount, err := strconv.ParseFloat(reserve.AvailableAmount, 64) if err != nil { return fmt.Errorf("invalid available amount: %v", err) } if allocateAmount > availableAmount { return fmt.Errorf("insufficient available reserve: requested %f, available %f", allocateAmount, availableAmount) } // Update reserve backedAmount, err := strconv.ParseFloat(reserve.BackedAmount, 64) if err != nil { return fmt.Errorf("invalid backed amount: %v", err) } reserve.BackedAmount = fmt.Sprintf("%.2f", backedAmount+allocateAmount) reserve.AvailableAmount = fmt.Sprintf("%.2f", availableAmount-allocateAmount) reserve.UpdatedAt = time.Now().Format(time.RFC3339) updatedJSON, err := json.Marshal(reserve) if err != nil { return err } err = ctx.GetStub().PutState(reserveID, updatedJSON) if err != nil { return fmt.Errorf("failed to update reserve in world state: %v", err) } return nil } // GetReserve returns reserve details func (s *ReserveManagerContract) GetReserve(ctx contractapi.TransactionContextInterface, reserveID string) (*Reserve, error) { reserveJSON, err := ctx.GetStub().GetState(reserveID) if err != nil { return nil, fmt.Errorf("failed to read from world state: %v", err) } if reserveJSON == nil { return nil, fmt.Errorf("reserve %s does not exist", reserveID) } var reserve Reserve err = json.Unmarshal(reserveJSON, &reserve) if err != nil { return nil, err } return &reserve, nil } // Enforce1To1Backing verifies 1:1 backing ratio func (s *ReserveManagerContract) Enforce1To1Backing(ctx contractapi.TransactionContextInterface, reserveID string) (bool, error) { reserve, err := s.GetReserve(ctx, reserveID) if err != nil { return false, err } totalAmount, err := strconv.ParseFloat(reserve.TotalAmount, 64) if err != nil { return false, err } backedAmount, err := strconv.ParseFloat(reserve.BackedAmount, 64) if err != nil { return false, err } // Check if total reserve >= backed amount (1:1 ratio) return totalAmount >= backedAmount, nil } func main() { chaincode, err := contractapi.NewChaincode(&ReserveManagerContract{}) if err != nil { fmt.Printf("Error creating reserve manager chaincode: %v", err) return } if err := chaincode.Start(); err != nil { fmt.Printf("Error starting reserve manager chaincode: %v", err) } }