github.com/bcnmy/go-ethereum@v1.10.27/signer/core/gnosis_safe.go (about)

     1  // Copyright 2020 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/common/hexutil"
    25  	"github.com/ethereum/go-ethereum/common/math"
    26  	"github.com/ethereum/go-ethereum/signer/core/apitypes"
    27  )
    28  
    29  // GnosisSafeTx is a type to parse the safe-tx returned by the relayer,
    30  // it also conforms to the API required by the Gnosis Safe tx relay service.
    31  // See 'SafeMultisigTransaction' on https://safe-transaction.mainnet.gnosis.io/
    32  type GnosisSafeTx struct {
    33  	// These fields are only used on output
    34  	Signature  hexutil.Bytes           `json:"signature"`
    35  	SafeTxHash common.Hash             `json:"contractTransactionHash"`
    36  	Sender     common.MixedcaseAddress `json:"sender"`
    37  	// These fields are used both on input and output
    38  	Safe           common.MixedcaseAddress `json:"safe"`
    39  	To             common.MixedcaseAddress `json:"to"`
    40  	Value          math.Decimal256         `json:"value"`
    41  	GasPrice       math.Decimal256         `json:"gasPrice"`
    42  	Data           *hexutil.Bytes          `json:"data"`
    43  	Operation      uint8                   `json:"operation"`
    44  	GasToken       common.Address          `json:"gasToken"`
    45  	RefundReceiver common.Address          `json:"refundReceiver"`
    46  	BaseGas        big.Int                 `json:"baseGas"`
    47  	SafeTxGas      big.Int                 `json:"safeTxGas"`
    48  	Nonce          big.Int                 `json:"nonce"`
    49  	InputExpHash   common.Hash             `json:"safeTxHash"`
    50  	ChainId        *math.HexOrDecimal256   `json:"chainId,omitempty"`
    51  }
    52  
    53  // ToTypedData converts the tx to a EIP-712 Typed Data structure for signing
    54  func (tx *GnosisSafeTx) ToTypedData() apitypes.TypedData {
    55  	var data hexutil.Bytes
    56  	if tx.Data != nil {
    57  		data = *tx.Data
    58  	}
    59  	var domainType = []apitypes.Type{{Name: "verifyingContract", Type: "address"}}
    60  	if tx.ChainId != nil {
    61  		domainType = append([]apitypes.Type{{Name: "chainId", Type: "uint256"}}, domainType[0])
    62  	}
    63  
    64  	gnosisTypedData := apitypes.TypedData{
    65  		Types: apitypes.Types{
    66  			"EIP712Domain": domainType,
    67  			"SafeTx": []apitypes.Type{
    68  				{Name: "to", Type: "address"},
    69  				{Name: "value", Type: "uint256"},
    70  				{Name: "data", Type: "bytes"},
    71  				{Name: "operation", Type: "uint8"},
    72  				{Name: "safeTxGas", Type: "uint256"},
    73  				{Name: "baseGas", Type: "uint256"},
    74  				{Name: "gasPrice", Type: "uint256"},
    75  				{Name: "gasToken", Type: "address"},
    76  				{Name: "refundReceiver", Type: "address"},
    77  				{Name: "nonce", Type: "uint256"},
    78  			},
    79  		},
    80  		Domain: apitypes.TypedDataDomain{
    81  			VerifyingContract: tx.Safe.Address().Hex(),
    82  			ChainId:           tx.ChainId,
    83  		},
    84  		PrimaryType: "SafeTx",
    85  		Message: apitypes.TypedDataMessage{
    86  			"to":             tx.To.Address().Hex(),
    87  			"value":          tx.Value.String(),
    88  			"data":           data,
    89  			"operation":      fmt.Sprintf("%d", tx.Operation),
    90  			"safeTxGas":      fmt.Sprintf("%#d", &tx.SafeTxGas),
    91  			"baseGas":        fmt.Sprintf("%#d", &tx.BaseGas),
    92  			"gasPrice":       tx.GasPrice.String(),
    93  			"gasToken":       tx.GasToken.Hex(),
    94  			"refundReceiver": tx.RefundReceiver.Hex(),
    95  			"nonce":          fmt.Sprintf("%d", tx.Nonce.Uint64()),
    96  		},
    97  	}
    98  	return gnosisTypedData
    99  }
   100  
   101  // ArgsForValidation returns a SendTxArgs struct, which can be used for the
   102  // common validations, e.g. look up 4byte destinations
   103  func (tx *GnosisSafeTx) ArgsForValidation() *apitypes.SendTxArgs {
   104  	gp := hexutil.Big(tx.GasPrice)
   105  	args := &apitypes.SendTxArgs{
   106  		From:     tx.Safe,
   107  		To:       &tx.To,
   108  		Gas:      hexutil.Uint64(tx.SafeTxGas.Uint64()),
   109  		GasPrice: &gp,
   110  		Value:    hexutil.Big(tx.Value),
   111  		Nonce:    hexutil.Uint64(tx.Nonce.Uint64()),
   112  		Data:     tx.Data,
   113  		Input:    nil,
   114  		ChainID:  (*hexutil.Big)(tx.ChainId),
   115  	}
   116  	return args
   117  }