Skip to content

Commit 77ee711

Browse files
committed
Add onchain EIP-6492 validation
1 parent bd92b57 commit 77ee711

File tree

6 files changed

+124
-5
lines changed

6 files changed

+124
-5
lines changed

auth.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func EIP6492ValidateSignature() ethauth.ValidatorFunc {
101101
return false, "", fmt.Errorf("sig is invalid: %w", err)
102102
}
103103

104-
isValid, err := eip6492.ValidateEIP6492Offchain(ctx, provider, signer, hash, sig, nil)
104+
isValid, err := eip6492.ValidateEIP6492(ctx, provider, signer, hash, sig, nil)
105105
if err != nil {
106106
return false, "", fmt.Errorf("failed to validate: %w", err)
107107
}

core/v2/v2.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1036,7 +1036,7 @@ func (l *signatureTreeDynamicSignatureLeaf) recover(ctx context.Context, payload
10361036
signature := l.signature
10371037

10381038
if provider != nil {
1039-
isValid, err := eip6492.ValidateEIP6492Offchain(ctx, provider, l.address, payload.Digest().Hash, signature, nil)
1039+
isValid, err := eip6492.ValidateEIP6492(ctx, provider, l.address, payload.Digest().Hash, signature, nil)
10401040
if err != nil {
10411041
return nil, nil, fmt.Errorf("unable to validate signature for %v: %w", l.address, err)
10421042
}

core/v3/v3.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1122,7 +1122,7 @@ func (l *signatureTreeSignatureERC1271Leaf) recover(ctx context.Context, payload
11221122
signature := l.Signature
11231123

11241124
if provider != nil {
1125-
isValid, err := eip6492.ValidateEIP6492Offchain(ctx, provider, l.Address, payload.Digest().Hash, signature, nil)
1125+
isValid, err := eip6492.ValidateEIP6492(ctx, provider, l.Address, payload.Digest().Hash, signature, nil)
11261126
if err != nil {
11271127
return nil, nil, fmt.Errorf("unable to validate ERC-1271 signature: %w", err)
11281128
}

eip6492_live_test.go

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package sequence_test
22

33
import (
44
"context"
5+
"strings"
56
"testing"
67

78
"github.com/0xsequence/ethkit/go-ethereum/accounts"
@@ -12,7 +13,9 @@ import (
1213
)
1314

1415
// These tests require a live testchain (make start-testchain or make start-testchain-fork).
15-
// They create a Sequence wallet, sign a message, wrap in EIP-6492, and validate on-chain via ValidateEIP6492Offchain.
16+
// They create a Sequence wallet, sign a message, wrap in EIP-6492, and validate via
17+
// ValidateEIP6492Offchain or ValidateEIP6492Onchain. Onchain tests skip if the validator
18+
// is not deployed at EIP_6492_ADDRESS on the chain.
1619

1720
func TestEIP6492Live_ValidateSequenceWalletMessage_Offchain(t *testing.T) {
1821
// V2 counterfactual wallet on testchain
@@ -83,3 +86,54 @@ func TestEIP6492Live_ValidateDeployedSequenceWallet_Offchain(t *testing.T) {
8386
require.NoError(t, err)
8487
require.True(t, valid, "EIP-6492 offchain validation should succeed for deployed Sequence wallet")
8588
}
89+
90+
func TestEIP6492Live_ValidateSequenceWalletMessage_Onchain(t *testing.T) {
91+
// Same as offchain test but via pre-deployed validator at EIP_6492_ADDRESS.
92+
// Skips if the validator is not deployed on this chain.
93+
wallet, err := testChain.V2DummySequenceWallet(13, true)
94+
require.NoError(t, err)
95+
96+
message := []byte("hello world onchain!")
97+
_, eip191Message := accounts.TextAndHash(message)
98+
99+
sig, err := wallet.SignMessage([]byte(eip191Message))
100+
require.NoError(t, err)
101+
102+
wrapped, err := sequence.EIP6492Signature(sig, wallet.GetWalletConfig())
103+
require.NoError(t, err)
104+
105+
digest := common.BytesToHash(accounts.TextHash(message))
106+
ctx := context.Background()
107+
108+
valid, err := eip6492.ValidateEIP6492Onchain(ctx, testChain.Provider, wallet.Address(), digest, wrapped, nil)
109+
if err != nil && strings.Contains(err.Error(), "returned no data") {
110+
t.Skipf("EIP-6492 validator not deployed on this chain: %v", err)
111+
}
112+
require.NoError(t, err)
113+
require.True(t, valid, "EIP-6492 onchain validation should succeed for Sequence wallet message signature")
114+
}
115+
116+
func TestEIP6492Live_ValidateDeployedSequenceWallet_Onchain(t *testing.T) {
117+
// Deployed wallet, validated via onchain contract. Skips if validator not deployed.
118+
wallet, err := testChain.V2DummySequenceWallet(14, false)
119+
require.NoError(t, err)
120+
121+
message := []byte("deployed wallet onchain sign")
122+
_, eip191Message := accounts.TextAndHash(message)
123+
124+
sig, err := wallet.SignMessage([]byte(eip191Message))
125+
require.NoError(t, err)
126+
127+
wrapped, err := sequence.EIP6492Signature(sig, wallet.GetWalletConfig())
128+
require.NoError(t, err)
129+
130+
digest := common.BytesToHash(accounts.TextHash(message))
131+
ctx := context.Background()
132+
133+
valid, err := eip6492.ValidateEIP6492Onchain(ctx, testChain.Provider, wallet.Address(), digest, wrapped, nil)
134+
if err != nil && strings.Contains(err.Error(), "returned no data") {
135+
t.Skipf("EIP-6492 validator not deployed on this chain: %v", err)
136+
}
137+
require.NoError(t, err)
138+
require.True(t, valid, "EIP-6492 onchain validation should succeed for deployed Sequence wallet")
139+
}

lib/eip6492/eip6492.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ contract ValidateSigOffchain {
187187

188188
const EIP_6492_OFFCHAIN_DEPLOY_CODE = "0x608060405234801561001057600080fd5b5060405161124a38038061124a83398101604081905261002f91610124565b600060405161003d906100dd565b604051809103906000f080158015610059573d6000803e3d6000fd5b5090506000816001600160a01b0316638f0684308686866040518463ffffffff1660e01b815260040161008e939291906101fb565b6020604051808303816000875af11580156100ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100d19190610244565b9050806000526001601ff35b610fdc8061026e83390190565b634e487b7160e01b600052604160045260246000fd5b60005b8381101561011b578181015183820152602001610103565b50506000910152565b60008060006060848603121561013957600080fd5b83516001600160a01b038116811461015057600080fd5b6020850151604086015191945092506001600160401b038082111561017457600080fd5b818601915086601f83011261018857600080fd5b81518181111561019a5761019a6100ea565b604051601f8201601f19908116603f011681019083821181831017156101c2576101c26100ea565b816040528281528960208487010111156101db57600080fd5b6101ec836020830160208801610100565b80955050505050509250925092565b60018060a01b0384168152826020820152606060408201526000825180606084015261022e816080850160208701610100565b601f01601f191691909101608001949350505050565b60006020828403121561025657600080fd5b8151801515811461026657600080fd5b939250505056fe608060405234801561001057600080fd5b50610fbc806100206000396000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c806376be4cea1161005057806376be4cea146100a65780638f068430146100b957806398ef1ed8146100cc57600080fd5b80631c6453271461006c5780633d787b6314610093575b600080fd5b61007f61007a366004610ad4565b6100df565b604051901515815260200160405180910390f35b61007f6100a1366004610ad4565b61023d565b61007f6100b4366004610b3e565b61031e565b61007f6100c7366004610ad4565b6108e1565b61007f6100da366004610ad4565b61096e565b6040517f76be4cea00000000000000000000000000000000000000000000000000000000815260009030906376be4cea9061012890889088908890889088908190600401610bc3565b6020604051808303816000875af1925050508015610181575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261017e91810190610c45565b60015b610232573d8080156101af576040519150601f19603f3d011682016040523d82523d6000602084013e6101b4565b606091505b508051600181900361022757816000815181106101d3576101d3610c69565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f0100000000000000000000000000000000000000000000000000000000000000149250610235915050565b600092505050610235565b90505b949350505050565b6040517f76be4cea00000000000000000000000000000000000000000000000000000000815260009030906376be4cea906102879088908890889088906001908990600401610bc3565b6020604051808303816000875af19250505080156102e0575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526102dd91810190610c45565b60015b610232573d80801561030e576040519150601f19603f3d011682016040523d82523d6000602084013e610313565b606091505b506000915050610235565b600073ffffffffffffffffffffffffffffffffffffffff87163b6060827f64926492649264926492649264926492649264926492649264926492649264928888610369602082610c98565b610375928b9290610cd8565b61037e91610d02565b1490508015610484576000606089828a610399602082610c98565b926103a693929190610cd8565b8101906103b39190610e18565b955090925090508415806103c45750865b1561047d576000808373ffffffffffffffffffffffffffffffffffffffff16836040516103f19190610eb2565b6000604051808303816000865af19150503d806000811461042e576040519150601f19603f3d011682016040523d82523d6000602084013e610433565b606091505b50915091508161047a57806040517f9d0d6e2d0000000000000000000000000000000000000000000000000000000081526004016104719190610f18565b60405180910390fd5b50505b50506104be565b87878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b80806104ca5750600083115b156106bb576040517f1626ba7e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b1690631626ba7e90610523908c908690600401610f2b565b602060405180830381865afa92505050801561057a575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261057791810190610f44565b60015b61060f573d8080156105a8576040519150601f19603f3d011682016040523d82523d6000602084013e6105ad565b606091505b50851580156105bc5750600084115b156105db576105d08b8b8b8b8b600161031e565b9450505050506108d7565b806040517f6f2a95990000000000000000000000000000000000000000000000000000000081526004016104719190610f18565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f1626ba7e000000000000000000000000000000000000000000000000000000001480158161065f575086155b801561066b5750600085115b1561068b5761067f8c8c8c8c8c600161031e565b955050505050506108d7565b841580156106965750825b80156106a0575087155b156106af57806000526001601ffd5b94506108d79350505050565b6041871461074b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5369676e617475726556616c696461746f72237265636f7665725369676e657260448201527f3a20696e76616c6964207369676e6174757265206c656e6774680000000000006064820152608401610471565b600061075a6020828a8c610cd8565b61076391610d02565b90506000610775604060208b8d610cd8565b61077e91610d02565b905060008a8a604081811061079557610795610c69565b919091013560f81c915050601b81148015906107b557508060ff16601c14155b15610842576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f5369676e617475726556616c696461746f723a20696e76616c6964207369676e60448201527f617475726520762076616c7565000000000000000000000000000000000000006064820152608401610471565b6040805160008152602081018083528e905260ff831691810191909152606081018490526080810183905273ffffffffffffffffffffffffffffffffffffffff8e169060019060a0016020604051602081039080840390855afa1580156108ad573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff161496505050505050505b9695505050505050565b6040517f76be4cea00000000000000000000000000000000000000000000000000000000815260009030906376be4cea9061092b9088908890889088906001908990600401610bc3565b6020604051808303816000875af115801561094a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102329190610c45565b6040517f76be4cea00000000000000000000000000000000000000000000000000000000815260009030906376be4cea906109b790889088908890889088908190600401610bc3565b6020604051808303816000875af1925050508015610a10575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252610a0d91810190610c45565b60015b610232573d808015610a3e576040519150601f19603f3d011682016040523d82523d6000602084013e610a43565b606091505b5080516001819003610a6257816000815181106101d3576101d3610c69565b8082fd5b73ffffffffffffffffffffffffffffffffffffffff81168114610a8857600080fd5b50565b60008083601f840112610a9d57600080fd5b50813567ffffffffffffffff811115610ab557600080fd5b602083019150836020828501011115610acd57600080fd5b9250929050565b60008060008060608587031215610aea57600080fd5b8435610af581610a66565b935060208501359250604085013567ffffffffffffffff811115610b1857600080fd5b610b2487828801610a8b565b95989497509550505050565b8015158114610a8857600080fd5b60008060008060008060a08789031215610b5757600080fd5b8635610b6281610a66565b955060208701359450604087013567ffffffffffffffff811115610b8557600080fd5b610b9189828a01610a8b565b9095509350506060870135610ba581610b30565b91506080870135610bb581610b30565b809150509295509295509295565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a060408201528360a0820152838560c0830137600060c085830181019190915292151560608201529015156080820152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909101019392505050565b600060208284031215610c5757600080fd5b8151610c6281610b30565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b81810381811115610cd2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b92915050565b60008085851115610ce857600080fd5b83861115610cf557600080fd5b5050820193919092039150565b80356020831015610cd2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff602084900360031b1b1692915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112610d7e57600080fd5b813567ffffffffffffffff80821115610d9957610d99610d3e565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610ddf57610ddf610d3e565b81604052838152866020858801011115610df857600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600060608486031215610e2d57600080fd5b8335610e3881610a66565b9250602084013567ffffffffffffffff80821115610e5557600080fd5b610e6187838801610d6d565b93506040860135915080821115610e7757600080fd5b50610e8486828701610d6d565b9150509250925092565b60005b83811015610ea9578181015183820152602001610e91565b50506000910152565b60008251610ec4818460208701610e8e565b9190910192915050565b60008151808452610ee6816020860160208601610e8e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610c626020830184610ece565b8281526040602082015260006102356040830184610ece565b600060208284031215610f5657600080fd5b81517fffffffff0000000000000000000000000000000000000000000000000000000081168114610c6257600080fdfea26469706673582212201a72aed4b15ffb05b6502997a9bb655992e06590bd26b336dfbb153d7ff6f34b64736f6c63430008120033"
189189
const EIP_6492_SUFFIX = "0x6492649264926492649264926492649264926492649264926492649264926492"
190+
const EIP_6492_ADDRESS = "0x0000000044dE9306b161ddE8D58682054e70c766"
190191

191192
var EIP6492MagicBytes = hexutil.MustDecode(EIP_6492_SUFFIX)
192193

@@ -213,6 +214,28 @@ func DecodeEIP6492Signature(signature []byte) (common.Address, []byte, []byte, e
213214
return create2Factory, factoryCalldata, sigToValidate, nil
214215
}
215216

217+
func ValidateEIP6492(
218+
ctx context.Context,
219+
provider *ethrpc.Provider,
220+
signer common.Address,
221+
hash common.Hash,
222+
signature []byte,
223+
block *big.Int,
224+
) (bool, error) {
225+
validatorAddr := common.HexToAddress(EIP_6492_ADDRESS)
226+
code, err := provider.CodeAt(ctx, validatorAddr, block)
227+
if err == nil && len(code) > 0 {
228+
// Validate using the deployed EIP-6492 validator
229+
valid, onchainErr := ValidateEIP6492Onchain(ctx, provider, signer, hash, signature, block)
230+
if onchainErr == nil && valid {
231+
return true, nil
232+
}
233+
}
234+
235+
// Fall back to offchain validation
236+
return ValidateEIP6492Offchain(ctx, provider, signer, hash, signature, block)
237+
}
238+
216239
func ValidateEIP6492Offchain(
217240
ctx context.Context,
218241
provider *ethrpc.Provider,
@@ -252,3 +275,45 @@ func ValidateEIP6492Offchain(
252275
expectedResult := hexutil.MustDecode("0x01")
253276
return bytes.Equal(result, expectedResult), nil
254277
}
278+
279+
// ValidateEIP6492Onchain validates an EIP-6492 signature by calling the pre-deployed
280+
// UniversalSigValidator at EIP_6492_ADDRESS and invoking isValidSigWithSideEffects.
281+
// It takes the same arguments as ValidateEIP6492Offchain but uses the onchain contract
282+
// instead of deployment via constructor.
283+
func ValidateEIP6492Onchain(
284+
ctx context.Context,
285+
provider *ethrpc.Provider,
286+
signer common.Address,
287+
hash common.Hash,
288+
signature []byte,
289+
block *big.Int,
290+
) (bool, error) {
291+
calldata, err := ethcoder.AbiEncodeMethodCalldata(
292+
"isValidSigWithSideEffects(address,bytes32,bytes)",
293+
[]interface{}{signer, hash, signature},
294+
)
295+
if err != nil {
296+
return false, err
297+
}
298+
299+
contractAddr := common.HexToAddress(EIP_6492_ADDRESS)
300+
msg := ethereum.CallMsg{
301+
To: &contractAddr,
302+
Data: calldata,
303+
}
304+
305+
result, err := provider.CallContract(ctx, msg, block)
306+
if err != nil {
307+
return false, err
308+
}
309+
310+
if len(result) == 0 {
311+
return false, fmt.Errorf("contract call returned no data: validator may not be deployed at %s or call reverted", EIP_6492_ADDRESS)
312+
}
313+
314+
var valid bool
315+
if err := ethcoder.AbiDecoder([]string{"bool"}, result, []interface{}{&valid}); err != nil {
316+
return false, err
317+
}
318+
return valid, nil
319+
}

signature.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ func IsValidTypedDataSignature(address common.Address, encodedTypedData []byte,
216216
}
217217

218218
func IsValidSignature(log logger.Logger, walletAddress common.Address, digest common.Hash, seqSig []byte, walletContexts WalletContexts, chainID *big.Int, provider *ethrpc.Provider) (bool, error) {
219-
eip6492isValid, _ := eip6492.ValidateEIP6492Offchain(context.Background(), provider, walletAddress, digest, seqSig, nil)
219+
eip6492isValid, _ := eip6492.ValidateEIP6492(context.Background(), provider, walletAddress, digest, seqSig, nil)
220220
if eip6492isValid {
221221
return true, nil
222222
}

0 commit comments

Comments
 (0)