Skip to content

Commit

Permalink
v2 signature decoding validates EIP-6492 signatures (#177)
Browse files Browse the repository at this point in the history
  • Loading branch information
ScreamingHawk authored Dec 16, 2024
1 parent 4d55d19 commit 0a2c8eb
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 22 deletions.
35 changes: 13 additions & 22 deletions core/v2/v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,19 @@ import (
"io"
"math/big"

"github.com/0xsequence/ethkit/ethcontract"
"github.com/0xsequence/ethkit/ethrpc"
"github.com/0xsequence/ethkit/go-ethereum/accounts/abi/bind"
"github.com/0xsequence/ethkit/go-ethereum/common"
"github.com/0xsequence/ethkit/go-ethereum/common/hexutil"
"github.com/0xsequence/ethkit/go-ethereum/crypto"
"github.com/0xsequence/go-sequence/contracts"
"github.com/0xsequence/go-sequence/core"
"github.com/0xsequence/go-sequence/eip6492"
)

const (
nestedLeafImageHashPrefix = "Sequence nested config:\n"
subdigestLeafImageHashPrefix = "Sequence static digest:\n"
)

var isValidSignatureMagicValue = [4]byte{0x16, 0x26, 0xba, 0x7e}

var Core core.Core[*WalletConfig, core.Signature[*WalletConfig]] = v2Core{}

func init() {
Expand Down Expand Up @@ -1055,27 +1051,22 @@ func (l *signatureTreeDynamicSignatureLeaf) recover(ctx context.Context, subdige

case dynamicSignatureTypeEIP1271:
effectiveWeight := l.weight
signature := l.signature

if provider != nil {
contract := ethcontract.NewContractCaller(l.address, contracts.IERC1271.ABI, provider)

var results []any
err := contract.Call(&bind.CallOpts{Context: ctx}, &results, "isValidSignature", subdigest.Hash, l.signature)
isValid, err := eip6492.ValidateEIP6492Offchain(ctx, provider, l.address, subdigest.Hash, signature, nil)
if err != nil {
return nil, nil, fmt.Errorf("unable to call isValidSignature on %v: %w", l.address, err)
}

if len(results) != 1 {
return nil, nil, fmt.Errorf("expected single return value from isValidSignature, got %v", len(results))
return nil, nil, fmt.Errorf("unable to validate signature for %v: %w", l.address, err)
}

magicValue, ok := results[0].([4]byte)
if !ok {
return nil, nil, fmt.Errorf("expected [4]byte return value from isValidSignature, got %T", results[0])
if !isValid {
return nil, nil, fmt.Errorf("invalid eip1271 signature for %v", l.address)
}

if magicValue != isValidSignatureMagicValue {
return nil, nil, fmt.Errorf("isValidSignature returned %v, expected %v", hexutil.Encode(magicValue[:]), hexutil.Encode(isValidSignatureMagicValue[:]))
if eip6492.IsEIP6492Signature(signature) {
// Decode the signature and use the nested signature for config recovery
_, _, signature, err = eip6492.DecodeEIP6492Signature(signature)
if err != nil {
return nil, nil, fmt.Errorf("unable to decode eip6492 signature: %w", err)
}
}
} else {
// Set the effective weight to 0
Expand All @@ -1087,7 +1078,7 @@ func (l *signatureTreeDynamicSignatureLeaf) recover(ctx context.Context, subdige
signerSignatures.Insert(l.address, core.SignerSignature{
Subdigest: subdigest,
Type: l.type_.signerSignatureType(),
Signature: l.signature,
Signature: signature,
})

return &WalletConfigTreeAddressLeaf{
Expand Down
24 changes: 24 additions & 0 deletions eip6492/eip6492.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package eip6492
import (
"bytes"
"context"
"fmt"
"math/big"

"github.com/0xsequence/ethkit/ethcoder"
Expand Down Expand Up @@ -189,6 +190,29 @@ const EIP_6492_SUFFIX = "0x64926492649264926492649264926492649264926492649264926

var EIP6492MagicBytes = hexutil.MustDecode(EIP_6492_SUFFIX)

func IsEIP6492Signature(signature []byte) bool {
return bytes.HasSuffix(signature, EIP6492MagicBytes)
}

func DecodeEIP6492Signature(signature []byte) (common.Address, []byte, []byte, error) {
if !IsEIP6492Signature(signature) {
return common.Address{}, nil, nil, fmt.Errorf("not an eip6492 signature")
}

// Strip the magic bytes
signature = signature[:len(signature)-32]

var create2Factory common.Address
var factoryCalldata []byte
var sigToValidate []byte

if err := ethcoder.AbiDecoder([]string{"address", "bytes", "bytes"}, signature, []interface{}{&create2Factory, &factoryCalldata, &sigToValidate}); err != nil {
return common.Address{}, nil, nil, err
}

return create2Factory, factoryCalldata, sigToValidate, nil
}

func ValidateEIP6492Offchain(
ctx context.Context,
provider *ethrpc.Provider,
Expand Down

0 comments on commit 0a2c8eb

Please sign in to comment.