services/cctp-relayer/relayer/util.go
package relayer
import (
"context"
"encoding/binary"
"errors"
"fmt"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/synapsecns/sanguine/ethergo/client"
tokenmessenger "github.com/synapsecns/sanguine/services/cctp-relayer/contracts/tokenmessenger"
)
// destinationDomainIndex is the index of the destination domain in the formatted CCTP message.
const destinationDomainIndex = 8
// ParseDestDomain parses the destination domain from a CCTP message.
func ParseDestDomain(message []byte) (uint32, error) {
return indexUint32(message, destinationDomainIndex, 4)
}
// indexUint32 parses an unsigned 32-bit integer from a byte slice starting at index with a specified length in bytes.
// Requires that the byte slice have enough bytes starting from the index.
func indexUint32(memView []byte, index int, bytes uint8) (uint32, error) {
if int(bytes)+index > len(memView) || bytes > 4 {
return 0, errors.New("invalid index or byte length")
}
// Ensure we are not trying to parse more than 4 bytes for a uint32.
if bytes > 4 {
return 0, errors.New("byte length too large for uint32")
}
// Pad the byte slice to 4 bytes if necessary.
padded := make([]byte, 4)
copy(padded[4-int(bytes):], memView[index:index+int(bytes)])
// Convert the bytes to uint32.
result := binary.BigEndian.Uint32(padded)
return result, nil
}
// AddressToBytes32 converts an Ethereum address to a bytes32 value.
func AddressToBytes32(addr common.Address) [32]byte {
var buf [32]byte
copy(buf[12:], addr.Bytes())
return buf
}
// Bytes32ToAddress converts a bytes32 value to an Ethereum address.
func Bytes32ToAddress(bytes32 [32]byte) common.Address {
return common.BytesToAddress(bytes32[12:])
}
// GetCircleRequestID returns a request ID from a source domain and nonce.
func GetCircleRequestID(sourceDomain uint32, nonce uint64) string {
return fmt.Sprintf("%d-%d", sourceDomain, nonce)
}
// GetMessageTransmitterAddress gets the message transmitter address from a token messenger contract.
func GetMessageTransmitterAddress(ctx context.Context, tokenMessengerAddr common.Address, ethClient client.EVM) (transmitterAddr common.Address, err error) {
messengerContract, err := tokenmessenger.NewTokenMessenger(tokenMessengerAddr, ethClient)
if err != nil {
return transmitterAddr, fmt.Errorf("could not get token messenger contract: %w", err)
}
transmitterAddr, err = messengerContract.LocalMessageTransmitter(&bind.CallOpts{Context: ctx})
if err != nil {
return transmitterAddr, fmt.Errorf("could not get local message transmitter: %w", err)
}
return transmitterAddr, nil
}