2022-05-24 20:39:40 +02:00
|
|
|
// Copyright 2020 The go-ethereum Authors
|
|
|
|
// This file is part of the go-ethereum library.
|
|
|
|
//
|
|
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2020-09-29 17:40:08 +02:00
|
|
|
package core
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"math/big"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
|
|
"github.com/ethereum/go-ethereum/common/math"
|
2021-07-29 16:06:44 +02:00
|
|
|
"github.com/ethereum/go-ethereum/signer/core/apitypes"
|
2020-09-29 17:40:08 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// GnosisSafeTx is a type to parse the safe-tx returned by the relayer,
|
|
|
|
// it also conforms to the API required by the Gnosis Safe tx relay service.
|
|
|
|
// See 'SafeMultisigTransaction' on https://safe-transaction.mainnet.gnosis.io/
|
|
|
|
type GnosisSafeTx struct {
|
|
|
|
// These fields are only used on output
|
|
|
|
Signature hexutil.Bytes `json:"signature"`
|
|
|
|
SafeTxHash common.Hash `json:"contractTransactionHash"`
|
|
|
|
Sender common.MixedcaseAddress `json:"sender"`
|
|
|
|
// These fields are used both on input and output
|
|
|
|
Safe common.MixedcaseAddress `json:"safe"`
|
|
|
|
To common.MixedcaseAddress `json:"to"`
|
|
|
|
Value math.Decimal256 `json:"value"`
|
|
|
|
GasPrice math.Decimal256 `json:"gasPrice"`
|
|
|
|
Data *hexutil.Bytes `json:"data"`
|
|
|
|
Operation uint8 `json:"operation"`
|
|
|
|
GasToken common.Address `json:"gasToken"`
|
|
|
|
RefundReceiver common.Address `json:"refundReceiver"`
|
|
|
|
BaseGas big.Int `json:"baseGas"`
|
|
|
|
SafeTxGas big.Int `json:"safeTxGas"`
|
|
|
|
Nonce big.Int `json:"nonce"`
|
|
|
|
InputExpHash common.Hash `json:"safeTxHash"`
|
2022-01-18 13:31:25 +01:00
|
|
|
ChainId *math.HexOrDecimal256 `json:"chainId,omitempty"`
|
2020-09-29 17:40:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ToTypedData converts the tx to a EIP-712 Typed Data structure for signing
|
2021-12-05 14:31:41 +01:00
|
|
|
func (tx *GnosisSafeTx) ToTypedData() apitypes.TypedData {
|
2020-09-29 17:40:08 +02:00
|
|
|
var data hexutil.Bytes
|
|
|
|
if tx.Data != nil {
|
|
|
|
data = *tx.Data
|
|
|
|
}
|
2022-01-18 13:31:25 +01:00
|
|
|
var domainType = []apitypes.Type{{Name: "verifyingContract", Type: "address"}}
|
|
|
|
if tx.ChainId != nil {
|
|
|
|
domainType = append([]apitypes.Type{{Name: "chainId", Type: "uint256"}}, domainType[0])
|
|
|
|
}
|
|
|
|
|
2021-12-05 14:31:41 +01:00
|
|
|
gnosisTypedData := apitypes.TypedData{
|
|
|
|
Types: apitypes.Types{
|
2022-01-18 13:31:25 +01:00
|
|
|
"EIP712Domain": domainType,
|
2021-12-05 14:31:41 +01:00
|
|
|
"SafeTx": []apitypes.Type{
|
2020-09-29 17:40:08 +02:00
|
|
|
{Name: "to", Type: "address"},
|
|
|
|
{Name: "value", Type: "uint256"},
|
|
|
|
{Name: "data", Type: "bytes"},
|
|
|
|
{Name: "operation", Type: "uint8"},
|
|
|
|
{Name: "safeTxGas", Type: "uint256"},
|
|
|
|
{Name: "baseGas", Type: "uint256"},
|
|
|
|
{Name: "gasPrice", Type: "uint256"},
|
|
|
|
{Name: "gasToken", Type: "address"},
|
|
|
|
{Name: "refundReceiver", Type: "address"},
|
|
|
|
{Name: "nonce", Type: "uint256"},
|
|
|
|
},
|
|
|
|
},
|
2021-12-05 14:31:41 +01:00
|
|
|
Domain: apitypes.TypedDataDomain{
|
2020-09-29 17:40:08 +02:00
|
|
|
VerifyingContract: tx.Safe.Address().Hex(),
|
2022-01-18 13:31:25 +01:00
|
|
|
ChainId: tx.ChainId,
|
2020-09-29 17:40:08 +02:00
|
|
|
},
|
|
|
|
PrimaryType: "SafeTx",
|
2021-12-05 14:31:41 +01:00
|
|
|
Message: apitypes.TypedDataMessage{
|
2020-09-29 17:40:08 +02:00
|
|
|
"to": tx.To.Address().Hex(),
|
|
|
|
"value": tx.Value.String(),
|
|
|
|
"data": data,
|
|
|
|
"operation": fmt.Sprintf("%d", tx.Operation),
|
|
|
|
"safeTxGas": fmt.Sprintf("%#d", &tx.SafeTxGas),
|
|
|
|
"baseGas": fmt.Sprintf("%#d", &tx.BaseGas),
|
|
|
|
"gasPrice": tx.GasPrice.String(),
|
|
|
|
"gasToken": tx.GasToken.Hex(),
|
|
|
|
"refundReceiver": tx.RefundReceiver.Hex(),
|
|
|
|
"nonce": fmt.Sprintf("%d", tx.Nonce.Uint64()),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
return gnosisTypedData
|
|
|
|
}
|
|
|
|
|
|
|
|
// ArgsForValidation returns a SendTxArgs struct, which can be used for the
|
|
|
|
// common validations, e.g. look up 4byte destinations
|
2021-07-29 16:06:44 +02:00
|
|
|
func (tx *GnosisSafeTx) ArgsForValidation() *apitypes.SendTxArgs {
|
2021-06-09 13:48:47 +02:00
|
|
|
gp := hexutil.Big(tx.GasPrice)
|
2021-07-29 16:06:44 +02:00
|
|
|
args := &apitypes.SendTxArgs{
|
2020-09-29 17:40:08 +02:00
|
|
|
From: tx.Safe,
|
|
|
|
To: &tx.To,
|
|
|
|
Gas: hexutil.Uint64(tx.SafeTxGas.Uint64()),
|
2021-06-09 13:48:47 +02:00
|
|
|
GasPrice: &gp,
|
2020-09-29 17:40:08 +02:00
|
|
|
Value: hexutil.Big(tx.Value),
|
|
|
|
Nonce: hexutil.Uint64(tx.Nonce.Uint64()),
|
|
|
|
Data: tx.Data,
|
|
|
|
Input: nil,
|
2022-01-18 13:31:25 +01:00
|
|
|
ChainID: (*hexutil.Big)(tx.ChainId),
|
2020-09-29 17:40:08 +02:00
|
|
|
}
|
|
|
|
return args
|
|
|
|
}
|