malleable

package
v0.64.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 19, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

README

Malleable Sapient

Build MalleableSapient signatures by locating byte ranges in call data, and optionally compute the image hash.

ABI calldata paths use abicalldata.NewPath() (see lib/abicalldata); this package supplies Builder, repeat constraints, and ComputeImageHash.

Usage

payload := v3.NewCallsPayload(...)

permitValue := abicalldata.NewPath().
    CallData(0).
    ABI(trailsABI, "hydrateExecute").
    ArgBytesData("packedPayload").
    EncodedCallsPayload().
    EncodedCallData(0).
    ABI(erc2612ABI, "permit").
    ArgSlot("value").
    AsSelector()

transferValue := abicalldata.NewPath().
    CallData(0).
    ABI(trailsABI, "hydrateExecute").
    ArgBytesData("packedPayload").
    EncodedCallsPayload().
    EncodedCallData(1).
    ABI(erc20ABI, "transferFrom").
    ArgSlot("_value").
    AsSelector()

b := malleable.NewBuilder(&payload, &malleable.BuilderOptions{
    ValidateRepeats:     true,
    MergeAdjacentStatic: true,
})

b.Repeat(permitValue, transferValue) // repeat constraint

// mark other malleable fields
b.Malleable(abicalldata.NewPath().
    CallData(0).
    ABI(trailsABI, "hydrateExecute").
    ArgBytesData("packedPayload").
    EncodedCallsPayload().
    EncodedCallData(0).
    ABI(erc2612ABI, "permit").
    ArgSlot("deadline").
    AsSelector(),
)

sig, _, err := b.Build()

If ABI params are unnamed, use index-based selectors:

value := abicalldata.NewPath().
    CallData(0).
    ABI(erc20ABI, "transferFrom").
    ArgSlotIndex(2).
    AsSelector()

Path semantics (when to rebind .ABI after nested steps) are documented in the abicalldata README.

Compute the image hash:

hash, err := malleable.ComputeImageHash(&payload, sig, chainID)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ComputeImageHash

func ComputeImageHash(payload *v3.CallsPayload, signature []byte, chainID *big.Int) (common.Hash, error)

func EncodeSignature

func EncodeSignature(statics []StaticSection, repeats []RepeatSection) ([]byte, error)

func ValidateSignature

func ValidateSignature(payload *v3.CallsPayload, signature []byte) error

Types

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

func NewBuilder

func NewBuilder(payload *v3.CallsPayload, opts *BuilderOptions) *Builder

func (*Builder) Build

func (b *Builder) Build() ([]byte, *Plan, error)

func (*Builder) Malleable

func (b *Builder) Malleable(sel abicalldata.Selector) *Builder

func (*Builder) Repeat

type BuilderOptions

type BuilderOptions struct {
	ValidateRepeats     bool
	MergeAdjacentStatic bool
	MaxOffset           uint32
	MaxSize             uint32
}

type Plan

type Plan struct {
	Static []StaticSection
	Repeat []RepeatSection
}

func (*Plan) DebugString

func (p *Plan) DebugString() string

type RepeatSection

type RepeatSection struct {
	TIndex  uint8
	CIndex  uint16
	Size    uint16
	TIndex2 uint8
	CIndex2 uint16
}

func (RepeatSection) Kind

func (s RepeatSection) Kind() SectionKind

type Section

type Section interface {
	Kind() SectionKind
}

func DecodeSignature

func DecodeSignature(sig []byte) ([]Section, error)

type SectionKind

type SectionKind uint8
const (
	SectionStatic SectionKind = iota
	SectionRepeat
)

type SpanWithCall

type SpanWithCall struct {
	CallIndex int
	abicalldata.Span
}

type StaticSection

type StaticSection struct {
	TIndex uint8
	CIndex uint16
	Size   uint16
}

func (StaticSection) Kind

func (s StaticSection) Kind() SectionKind

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL