signer, core: support chainId for GnosisSafeTx (#24231)
This commit is contained in:
parent
51eb5f8ca8
commit
7dec26db2a
@ -31,6 +31,7 @@ type GnosisSafeTx struct {
|
||||
SafeTxGas big.Int `json:"safeTxGas"`
|
||||
Nonce big.Int `json:"nonce"`
|
||||
InputExpHash common.Hash `json:"safeTxHash"`
|
||||
ChainId *math.HexOrDecimal256 `json:"chainId,omitempty"`
|
||||
}
|
||||
|
||||
// ToTypedData converts the tx to a EIP-712 Typed Data structure for signing
|
||||
@ -39,9 +40,14 @@ func (tx *GnosisSafeTx) ToTypedData() apitypes.TypedData {
|
||||
if tx.Data != nil {
|
||||
data = *tx.Data
|
||||
}
|
||||
var domainType = []apitypes.Type{{Name: "verifyingContract", Type: "address"}}
|
||||
if tx.ChainId != nil {
|
||||
domainType = append([]apitypes.Type{{Name: "chainId", Type: "uint256"}}, domainType[0])
|
||||
}
|
||||
|
||||
gnosisTypedData := apitypes.TypedData{
|
||||
Types: apitypes.Types{
|
||||
"EIP712Domain": []apitypes.Type{{Name: "verifyingContract", Type: "address"}},
|
||||
"EIP712Domain": domainType,
|
||||
"SafeTx": []apitypes.Type{
|
||||
{Name: "to", Type: "address"},
|
||||
{Name: "value", Type: "uint256"},
|
||||
@ -57,6 +63,7 @@ func (tx *GnosisSafeTx) ToTypedData() apitypes.TypedData {
|
||||
},
|
||||
Domain: apitypes.TypedDataDomain{
|
||||
VerifyingContract: tx.Safe.Address().Hex(),
|
||||
ChainId: tx.ChainId,
|
||||
},
|
||||
PrimaryType: "SafeTx",
|
||||
Message: apitypes.TypedDataMessage{
|
||||
@ -88,6 +95,7 @@ func (tx *GnosisSafeTx) ArgsForValidation() *apitypes.SendTxArgs {
|
||||
Nonce: hexutil.Uint64(tx.Nonce.Uint64()),
|
||||
Data: tx.Data,
|
||||
Input: nil,
|
||||
ChainID: (*hexutil.Big)(tx.ChainId),
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
@ -532,3 +532,133 @@ func TestGnosisCustomData(t *testing.T) {
|
||||
t.Fatalf("Error, got %x, wanted %x", sighash, expSigHash)
|
||||
}
|
||||
}
|
||||
|
||||
var gnosisTypedDataWithChainId = `
|
||||
{
|
||||
"types": {
|
||||
"EIP712Domain": [
|
||||
{ "type": "uint256", "name": "chainId" },
|
||||
{ "type": "address", "name": "verifyingContract" }
|
||||
],
|
||||
"SafeTx": [
|
||||
{ "type": "address", "name": "to" },
|
||||
{ "type": "uint256", "name": "value" },
|
||||
{ "type": "bytes", "name": "data" },
|
||||
{ "type": "uint8", "name": "operation" },
|
||||
{ "type": "uint256", "name": "safeTxGas" },
|
||||
{ "type": "uint256", "name": "baseGas" },
|
||||
{ "type": "uint256", "name": "gasPrice" },
|
||||
{ "type": "address", "name": "gasToken" },
|
||||
{ "type": "address", "name": "refundReceiver" },
|
||||
{ "type": "uint256", "name": "nonce" }
|
||||
]
|
||||
},
|
||||
"domain": {
|
||||
"verifyingContract": "0x111dAE35D176A9607053e0c46e91F36AFbC1dc57",
|
||||
"chainId": "4"
|
||||
},
|
||||
"primaryType": "SafeTx",
|
||||
"message": {
|
||||
"to": "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa",
|
||||
"value": "0",
|
||||
"data": "0xa9059cbb00000000000000000000000099d580d3a7fe7bd183b2464517b2cd7ce5a8f15a0000000000000000000000000000000000000000000000000de0b6b3a7640000",
|
||||
"operation": 0,
|
||||
"safeTxGas": 0,
|
||||
"baseGas": 0,
|
||||
"gasPrice": "0",
|
||||
"gasToken": "0x0000000000000000000000000000000000000000",
|
||||
"refundReceiver": "0x0000000000000000000000000000000000000000",
|
||||
"nonce": 15
|
||||
}
|
||||
}`
|
||||
|
||||
var gnosisTxWithChainId = `
|
||||
{
|
||||
"safe": "0x111dAE35D176A9607053e0c46e91F36AFbC1dc57",
|
||||
"to": "0x5592EC0cfb4dbc12D3aB100b257153436a1f0FEa",
|
||||
"value": "0",
|
||||
"data": "0xa9059cbb00000000000000000000000099d580d3a7fe7bd183b2464517b2cd7ce5a8f15a0000000000000000000000000000000000000000000000000de0b6b3a7640000",
|
||||
"operation": 0,
|
||||
"gasToken": "0x0000000000000000000000000000000000000000",
|
||||
"safeTxGas": 0,
|
||||
"baseGas": 0,
|
||||
"gasPrice": "0",
|
||||
"refundReceiver": "0x0000000000000000000000000000000000000000",
|
||||
"nonce": 15,
|
||||
"executionDate": "2022-01-10T20:00:12Z",
|
||||
"submissionDate": "2022-01-10T19:59:59.689989Z",
|
||||
"modified": "2022-01-10T20:00:31.903635Z",
|
||||
"blockNumber": 9968802,
|
||||
"transactionHash": "0xc9fef30499ee8984974ab9dddd9d15c2a97c1a4393935dceed5efc3af9fc41a4",
|
||||
"safeTxHash": "0x6619dab5401503f2735256e12b898e69eb701d6a7e0d07abf1be4bb8aebfba29",
|
||||
"executor": "0xbc2BB26a6d821e69A38016f3858561a1D80d4182",
|
||||
"isExecuted": true,
|
||||
"isSuccessful": true,
|
||||
"ethGasPrice": "2500000009",
|
||||
"gasUsed": 82902,
|
||||
"fee": "207255000746118",
|
||||
"chainId": "4",
|
||||
"origin": null,
|
||||
"dataDecoded": {
|
||||
"method": "transfer",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "to",
|
||||
"type": "address",
|
||||
"value": "0x99D580d3a7FE7BD183b2464517B2cD7ce5A8F15A"
|
||||
},
|
||||
{
|
||||
"name": "value",
|
||||
"type": "uint256",
|
||||
"value": "1000000000000000000"
|
||||
}
|
||||
]
|
||||
},
|
||||
"confirmationsRequired": 1,
|
||||
"confirmations": [
|
||||
{
|
||||
"owner": "0xbc2BB26a6d821e69A38016f3858561a1D80d4182",
|
||||
"submissionDate": "2022-01-10T19:59:59.722500Z",
|
||||
"transactionHash": null,
|
||||
"signature": "0x5ca34641bcdee06e7b99143bfe34778195ca41022bd35837b96c204c7786be9d6dfa6dba43b53cd92da45ac728899e1561b232d28f38ba82df45f164caba38be1b",
|
||||
"signatureType": "EOA"
|
||||
}
|
||||
],
|
||||
"signatures": "0x5ca34641bcdee06e7b99143bfe34778195ca41022bd35837b96c204c7786be9d6dfa6dba43b53cd92da45ac728899e1561b232d28f38ba82df45f164caba38be1b"
|
||||
}
|
||||
`
|
||||
|
||||
func TestGnosisTypedDataWithChainId(t *testing.T) {
|
||||
var td apitypes.TypedData
|
||||
err := json.Unmarshal([]byte(gnosisTypedDataWithChainId), &td)
|
||||
if err != nil {
|
||||
t.Fatalf("unmarshalling failed '%v'", err)
|
||||
}
|
||||
_, sighash, err := sign(td)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expSigHash := common.FromHex("0x6619dab5401503f2735256e12b898e69eb701d6a7e0d07abf1be4bb8aebfba29")
|
||||
if !bytes.Equal(expSigHash, sighash) {
|
||||
t.Fatalf("Error, got %x, wanted %x", sighash, expSigHash)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGnosisCustomData tests the scenario where a user submits only the gnosis-safe
|
||||
// specific data, and we fill the TypedData struct on our side
|
||||
func TestGnosisCustomDataWithChainId(t *testing.T) {
|
||||
var tx core.GnosisSafeTx
|
||||
err := json.Unmarshal([]byte(gnosisTxWithChainId), &tx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var td = tx.ToTypedData()
|
||||
_, sighash, err := sign(td)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expSigHash := common.FromHex("0x6619dab5401503f2735256e12b898e69eb701d6a7e0d07abf1be4bb8aebfba29")
|
||||
if !bytes.Equal(expSigHash, sighash) {
|
||||
t.Fatalf("Error, got %x, wanted %x", sighash, expSigHash)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user