diff --git a/signature.go b/signature.go index 561995ee..4fa1b1b4 100644 --- a/signature.go +++ b/signature.go @@ -271,6 +271,51 @@ func EIP6492Signature(signature []byte, config core.WalletConfig) ([]byte, error return signature, nil } +func EIP6492SignatureWithMultipleDeployments(signature []byte, configs []core.WalletConfig) ([]byte, error) { + if len(configs) == 1 { + return EIP6492Signature(signature, configs[0]) + } + + var txns Transactions + for _, config := range configs { + context := SequenceContextForWalletConfig(config) + factory := context.FactoryAddress + if factory == (common.Address{}) { + return nil, fmt.Errorf("unknown factory address for wallet config type %T", config) + } + + mainModule := context.MainModuleAddress + imageHash := config.ImageHash().Hash + deploy, err := contracts.V2.WalletFactory.ABI.Pack("deploy", mainModule, imageHash) + if err != nil { + return nil, fmt.Errorf("unable to encode deploy call: %w", err) + } + + txns = append(txns, &Transaction{ + RevertOnError: true, + To: factory, + Data: deploy, + }) + } + + encodedTxns, err := txns.EncodedTransactions() + if err != nil { + return nil, err + } + + execdata, err := contracts.WalletMainModule.Encode("execute", encodedTxns, big.NewInt(0), []byte{}) + if err != nil { + return nil, err + } + + signature, err = ethcoder.AbiCoder([]string{"address", "bytes", "bytes"}, []interface{}{sequenceContextV2.GuestModuleAddress, execdata, signature}) + if err != nil { + return nil, fmt.Errorf("unable to encode eip-6492 signature: %w", err) + } + signature = append(signature, eip6492.EIP6492MagicBytes...) + return signature, nil +} + func UnwrapEIP6492Signature(signature []byte) ([]byte, error) { if !bytes.HasSuffix(signature, eip6492.EIP6492MagicBytes) { return signature, nil diff --git a/signature_test.go b/signature_test.go index 939ef9a1..c68c8d0c 100644 --- a/signature_test.go +++ b/signature_test.go @@ -9,7 +9,9 @@ import ( "github.com/0xsequence/ethkit/go-ethereum/accounts" "github.com/0xsequence/ethkit/go-ethereum/crypto" "github.com/0xsequence/go-sequence" + "github.com/0xsequence/go-sequence/core" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const ( @@ -62,6 +64,39 @@ func TestIsValidMessageSignatureSequence(t *testing.T) { assert.True(t, isValid) } +func TestIsValideMessageSignatureSequence_EIP6492SignatureWithMultipleDeployments(t *testing.T) { + message := "hello world!" + + eoa, err := ethwallet.NewWalletFromRandomEntropy() + require.NoError(t, err) + wallet, err := sequence.NewWalletSingleOwner(eoa) + require.NoError(t, err) + + walletChild, err := sequence.NewWalletSingleOwner(wallet) + require.NoError(t, err) + + provider, err := ethrpc.NewProvider(rpcURLEthereum) + assert.NoError(t, err) + + err = wallet.Connect(provider, nil) + assert.NoError(t, err) + + err = walletChild.Connect(provider, nil) + assert.NoError(t, err) + + _, eip191Message := accounts.TextAndHash([]byte(message)) + + signature, err := walletChild.SignMessage([]byte(eip191Message)) + assert.NoError(t, err) + + signature, err = sequence.EIP6492SignatureWithMultipleDeployments(signature, []core.WalletConfig{wallet.GetWalletConfig(), walletChild.GetWalletConfig()}) + assert.NoError(t, err) + + isValid, err := sequence.IsValidMessageSignature(walletChild.Address(), []byte(message), signature, big.NewInt(1), provider, nil) + assert.NoError(t, err) + assert.True(t, isValid) +} + /* const message = "hi!"