Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v2 signature decoding validates EIP-6492 signatures #177

Merged
merged 1 commit into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading