code.vegaprotocol.io/vega@v0.79.0/core/bridges/erc20_common.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package bridges
    17  
    18  import (
    19  	"bytes"
    20  	"encoding/hex"
    21  	"fmt"
    22  
    23  	"code.vegaprotocol.io/vega/core/nodewallets/eth/clef"
    24  	"code.vegaprotocol.io/vega/libs/num"
    25  
    26  	"github.com/ethereum/go-ethereum/accounts/abi"
    27  	ethcmn "github.com/ethereum/go-ethereum/common"
    28  	"github.com/ethereum/go-ethereum/crypto"
    29  )
    30  
    31  var prefix = []byte{0x19}
    32  
    33  type Signer interface {
    34  	Sign([]byte) ([]byte, error)
    35  	Algo() string
    36  }
    37  
    38  type SignaturePayload struct {
    39  	Message   Bytes
    40  	Signature Bytes
    41  }
    42  
    43  type Bytes []byte
    44  
    45  func (b Bytes) Bytes() []byte {
    46  	return b
    47  }
    48  
    49  func (b Bytes) Hex() string {
    50  	return hex.EncodeToString(b)
    51  }
    52  
    53  func packScheme(
    54  	buf []byte, submitter, chainID string, v1 bool,
    55  ) ([]byte, error) {
    56  	if v1 {
    57  		return packSchemeV1(buf, submitter)
    58  	}
    59  	return packSchemeV2(buf, submitter, chainID)
    60  }
    61  
    62  // packSchemeV1 returns the payload to be hashed and signed where
    63  // payload = abi.encode(message, msg.sender).
    64  func packSchemeV1(
    65  	buf []byte, submitter string,
    66  ) ([]byte, error) {
    67  	typBytes, err := abi.NewType("bytes", "", nil)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  	typAddr, err := abi.NewType("address", "", nil)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  
    76  	submitterAddr := ethcmn.HexToAddress(submitter)
    77  	args2 := abi.Arguments([]abi.Argument{
    78  		{
    79  			Name: "bytes",
    80  			Type: typBytes,
    81  		},
    82  		{
    83  			Name: "address",
    84  			Type: typAddr,
    85  		},
    86  	})
    87  
    88  	return args2.Pack(buf, submitterAddr)
    89  }
    90  
    91  // packSchemeV2 returns the payload to be hashed and signed where
    92  // payload = abi.encodePacked(bytes1(0x19), block.chainid, abi.encode(message, msg.sender))
    93  // where abi.encodePacked is the concatenation of the individual byte slices.
    94  func packSchemeV2(
    95  	buf []byte, submitter, chainID string,
    96  ) ([]byte, error) {
    97  	typBytes, err := abi.NewType("bytes", "", nil)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	typAddr, err := abi.NewType("address", "", nil)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  
   106  	submitterAddr := ethcmn.HexToAddress(submitter)
   107  	args := abi.Arguments([]abi.Argument{
   108  		{
   109  			Name: "bytes",
   110  			Type: typBytes,
   111  		},
   112  		{
   113  			Name: "address",
   114  			Type: typAddr,
   115  		},
   116  	})
   117  
   118  	// abi.encode(message, msg.sender)
   119  	buf, err = args.Pack(buf, submitterAddr)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  
   124  	// concat(prefix, chain-id, abi.encode(message, msg.sender))
   125  	cid := num.MustUintFromString(chainID, 10).Bytes()
   126  	return bytes.Join([][]byte{prefix, cid[:], buf}, nil), nil
   127  }
   128  
   129  func sign(signer Signer, msg []byte) (*SignaturePayload, error) {
   130  	var sig []byte
   131  	var err error
   132  
   133  	if signer.Algo() == clef.ClefAlgoType {
   134  		sig, err = signer.Sign(msg)
   135  	} else {
   136  		// hash our message before signing it
   137  		hash := crypto.Keccak256(msg)
   138  		sig, err = signer.Sign(hash)
   139  	}
   140  
   141  	if err != nil {
   142  		return nil, fmt.Errorf("could not sign message with ethereum wallet: %w", err)
   143  	}
   144  	return &SignaturePayload{
   145  		Message:   msg,
   146  		Signature: sig,
   147  	}, nil
   148  }