// Code generated by bitwrap synth; DO NOT EDIT.
// Source schema: ERC020 ERC-020:1.0.0

package prover

import (
	"github.com/consensys/gnark/frontend"
)

// TransferCircuit is generated from schema action "transfer". Parity target: TransferCircuit in prover/circuits.go.
type TransferCircuit struct {
	PreStateRoot  frontend.Variable `gnark:",public"`
	PostStateRoot frontend.Variable `gnark:",public"`
	From          frontend.Variable `gnark:",public"`
	To            frontend.Variable `gnark:",public"`
	Amount        frontend.Variable `gnark:",public"`

	BalanceFrom frontend.Variable
	BalanceTo   frontend.Variable

	PathElements [20]frontend.Variable
	PathIndices  [20]frontend.Variable
}

func (c *TransferCircuit) Define(api frontend.API) error {
	// Range checks from Action.Guard "balances[from] >= amount && to != address(0)"
	diff := api.Sub(c.BalanceFrom, c.Amount)
	api.ToBinary(diff, 64)

	// Merkle membership: balances[from] = BalanceFrom at PreStateRoot
	leaf := synthMimcHash(api, c.From, c.BalanceFrom)
	current := leaf
	for i := 0; i < 20; i++ {
		api.AssertIsBoolean(c.PathIndices[i])
		left := api.Select(c.PathIndices[i], c.PathElements[i], current)
		right := api.Select(c.PathIndices[i], current, c.PathElements[i])
		current = synthMimcHash(api, left, right)
	}
	api.AssertIsEqual(current, c.PreStateRoot)

	// Post-state: composite hash of decremented from + incremented to leaves
	newBalanceFrom := api.Sub(c.BalanceFrom, c.Amount)
	newBalanceTo := api.Add(c.BalanceTo, c.Amount)
	postLeaf := synthMimcHash(api, c.From, newBalanceFrom)
	postLeaf2 := synthMimcHash(api, c.To, newBalanceTo)
	computedPost := synthMimcHash(api, postLeaf, postLeaf2)
	api.AssertIsEqual(computedPost, c.PostStateRoot)
	return nil
}

// ApproveCircuit is generated from schema action "approve". Parity target: ApproveCircuit in prover/circuits.go.
type ApproveCircuit struct {
	PreStateRoot  frontend.Variable `gnark:",public"`
	PostStateRoot frontend.Variable `gnark:",public"`
	Caller        frontend.Variable `gnark:",public"`
	Spender       frontend.Variable `gnark:",public"`
	Amount        frontend.Variable `gnark:",public"`

	Owner frontend.Variable
}

func (c *ApproveCircuit) Define(api frontend.API) error {
	// Role check (Action.Roles contains "owner")
	api.AssertIsEqual(c.Owner, c.Caller)
	// Output arc: allowances[spender] = amount
	postLeaf := synthMimcHash(api, c.Spender, c.Amount)
	api.AssertIsEqual(postLeaf, c.PostStateRoot)
	return nil
}

// TransferFromCircuit is generated from schema action "transferFrom". Parity target: TransferFromCircuit in prover/circuits.go.
type TransferFromCircuit struct {
	PreStateRoot  frontend.Variable `gnark:",public"`
	PostStateRoot frontend.Variable `gnark:",public"`
	From          frontend.Variable `gnark:",public"`
	To            frontend.Variable `gnark:",public"`
	Caller        frontend.Variable `gnark:",public"`
	Amount        frontend.Variable `gnark:",public"`

	BalanceFrom   frontend.Variable
	AllowanceFrom frontend.Variable

	BalancePath    [10]frontend.Variable
	BalanceIndices [10]frontend.Variable
	AllowancePath  [10]frontend.Variable
	AllowanceIdx   [10]frontend.Variable
}

func (c *TransferFromCircuit) Define(api frontend.API) error {
	// Range checks from Action.Guard "balances[from] >= amount && allowances[from][caller] >= amount"
	diff1 := api.Sub(c.BalanceFrom, c.Amount)
	api.ToBinary(diff1, 64)
	diff2 := api.Sub(c.AllowanceFrom, c.Amount)
	api.ToBinary(diff2, 64)

	// Balance Merkle proof (depth 10)
	balanceLeaf := synthMimcHash(api, c.From, c.BalanceFrom)
	current := balanceLeaf
	for i := 0; i < 10; i++ {
		api.AssertIsBoolean(c.BalanceIndices[i])
		left := api.Select(c.BalanceIndices[i], c.BalancePath[i], current)
		right := api.Select(c.BalanceIndices[i], current, c.BalancePath[i])
		current = synthMimcHash(api, left, right)
	}
	balanceRoot := current

	// Allowance Merkle proof — nested key allowanceKey = hash(from, caller)
	allowanceKey := synthMimcHash(api, c.From, c.Caller)
	allowanceLeaf := synthMimcHash(api, allowanceKey, c.AllowanceFrom)
	current = allowanceLeaf
	for i := 0; i < 10; i++ {
		api.AssertIsBoolean(c.AllowanceIdx[i])
		left := api.Select(c.AllowanceIdx[i], c.AllowancePath[i], current)
		right := api.Select(c.AllowanceIdx[i], current, c.AllowancePath[i])
		current = synthMimcHash(api, left, right)
	}
	allowanceRoot := current

	// Composite pre-state root = hash(balanceRoot, allowanceRoot)
	computedRoot := synthMimcHash(api, balanceRoot, allowanceRoot)
	api.AssertIsEqual(computedRoot, c.PreStateRoot)

	// Post-state: decremented balance + decremented allowance
	newBalance := api.Sub(c.BalanceFrom, c.Amount)
	newAllowance := api.Sub(c.AllowanceFrom, c.Amount)
	postBalanceLeaf := synthMimcHash(api, c.From, newBalance)
	postAllowanceLeaf := synthMimcHash(api, allowanceKey, newAllowance)
	computedPost := synthMimcHash(api, postBalanceLeaf, postAllowanceLeaf)
	api.AssertIsEqual(computedPost, c.PostStateRoot)
	return nil
}

// MintCircuit is generated from schema action "mint". Parity target: MintCircuit in prover/circuits.go.
type MintCircuit struct {
	PreStateRoot  frontend.Variable `gnark:",public"`
	PostStateRoot frontend.Variable `gnark:",public"`
	Caller        frontend.Variable `gnark:",public"`
	To            frontend.Variable `gnark:",public"`
	Amount        frontend.Variable `gnark:",public"`

	Minter    frontend.Variable
	BalanceTo frontend.Variable
}

func (c *MintCircuit) Define(api frontend.API) error {
	// Role check (Action.Roles contains "minter")
	api.AssertIsEqual(c.Caller, c.Minter)
	// Output arc: balances[to] += amount
	newBalance := api.Add(c.BalanceTo, c.Amount)
	postLeaf := synthMimcHash(api, c.To, newBalance)
	api.AssertIsEqual(postLeaf, c.PostStateRoot)
	return nil
}

// BurnCircuit is generated from schema action "burn". Parity target: BurnCircuit in prover/circuits.go.
type BurnCircuit struct {
	PreStateRoot  frontend.Variable `gnark:",public"`
	PostStateRoot frontend.Variable `gnark:",public"`
	From          frontend.Variable `gnark:",public"`
	Amount        frontend.Variable `gnark:",public"`

	BalanceFrom frontend.Variable

	PathElements [20]frontend.Variable
	PathIndices  [20]frontend.Variable
}

func (c *BurnCircuit) Define(api frontend.API) error {
	// Range checks derived from Action.Guard "balances[from] >= amount"
	diff := api.Sub(c.BalanceFrom, c.Amount)
	api.ToBinary(diff, 64)

	// Merkle membership: balances[from] = BalanceFrom at PreStateRoot
	leaf := synthMimcHash(api, c.From, c.BalanceFrom)
	current := leaf
	for i := 0; i < 20; i++ {
		api.AssertIsBoolean(c.PathIndices[i])
		left := api.Select(c.PathIndices[i], c.PathElements[i], current)
		right := api.Select(c.PathIndices[i], current, c.PathElements[i])
		current = synthMimcHash(api, left, right)
	}
	api.AssertIsEqual(current, c.PreStateRoot)

	// Post-state: balances[from] decremented
	newBalance := api.Sub(c.BalanceFrom, c.Amount)
	postLeaf := synthMimcHash(api, c.From, newBalance)
	api.AssertIsEqual(postLeaf, c.PostStateRoot)
	return nil
}
