synapsecns/sanguine

View on GitHub
services/cctp-relayer/testutil/deployers.go

Summary

Maintainability
B
4 hrs
Test Coverage
package testutil

import (
    "context"
    "fmt"
    "testing"

    "github.com/synapsecns/sanguine/services/cctp-relayer/contracts/mockmintburntoken"
    "github.com/synapsecns/sanguine/services/cctp-relayer/contracts/mocktokenmessenger"
    "github.com/synapsecns/sanguine/services/cctp-relayer/contracts/mocktokenminter"

    "github.com/ethereum/go-ethereum/accounts/abi/bind"
    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/core/types"
    "github.com/synapsecns/sanguine/ethergo/backends"
    "github.com/synapsecns/sanguine/ethergo/contracts"
    "github.com/synapsecns/sanguine/ethergo/deployer"
    "github.com/synapsecns/sanguine/ethergo/manager"
    "github.com/synapsecns/sanguine/services/cctp-relayer/contracts/cctp"
    "github.com/synapsecns/sanguine/services/cctp-relayer/contracts/mockmessagetransmitter"
)

// ChainIDDomainMap maps chain IDs to domains.
// see: https://developers.circle.com/stablecoin/docs/cctp-technical-reference#domain
// TODO: make this eaiser to debug in the case of missing domains, etc.
var ChainIDDomainMap = map[uint32]uint32{
    1:     0,
    43114: 1,
}

// NewDeployManager creates a deploy manager.
func NewDeployManager(t *testing.T) *DeployManager {
    t.Helper()

    parentManager := manager.NewDeployerManager(t,
        NewMockMessageTransmitterDeployer, NewSynapseCCTPDeployer, NewMockTokenMessengerDeployer, NewMockMintBurnTokenDeployer, NewMockTokenMinterDeployer,
    )
    return &DeployManager{parentManager}
}

// DeployManager wraps DeployManager and allows typed contract handles to be returned.
type DeployManager struct {
    *manager.DeployerManager
}

// MockMessageTransmitterDeployer deploys the mockmessagetransmitter.
type MockMessageTransmitterDeployer struct {
    *deployer.BaseDeployer
}

// NewMockMessageTransmitterDeployer deploys the light inbox contract.
func NewMockMessageTransmitterDeployer(registry deployer.GetOnlyContractRegistry, backend backends.SimulatedTestBackend) deployer.ContractDeployer {
    return MockMessageTransmitterDeployer{deployer.NewSimpleDeployer(registry, backend, MockMessageTransmitterType)}
}

// Deploy deploys the light manager contract.
//
//nolint:dupword,dupl,cyclop
func (d MockMessageTransmitterDeployer) Deploy(ctx context.Context) (contracts.DeployedContract, error) {
    return d.DeploySimpleContract(ctx, func(transactOps *bind.TransactOpts, backend bind.ContractBackend) (address common.Address, tx *types.Transaction, data interface{}, err error) {
        // define the domain as the chain id!
        return mockmessagetransmitter.DeployMockMessageTransmitter(transactOps, backend, ChainIDDomainMap[uint32(d.Backend().GetChainID())])
    }, func(address common.Address, backend bind.ContractBackend) (interface{}, error) {
        // remember what I said about vm.ContractRef!
        return mockmessagetransmitter.NewMockMessageTransmitterRef(address, backend)
    })
}

// NewMockTokenMessengerDeployer deploys the mocktokenmessenger.
func NewMockTokenMessengerDeployer(registry deployer.GetOnlyContractRegistry, backend backends.SimulatedTestBackend) deployer.ContractDeployer {
    return MockTokenMessengerDeployer{deployer.NewSimpleDeployer(registry, backend, MockTokenMessengerType)}
}

// MockTokenMessengerDeployer deploys the mocktokenmessenger.
type MockTokenMessengerDeployer struct {
    *deployer.BaseDeployer
}

// Deploy deploys the mock token messenger contract.
//
//nolint:dupword,dupl,cyclop
func (m MockTokenMessengerDeployer) Deploy(ctx context.Context) (contracts.DeployedContract, error) {
    messageTransmitter := m.Registry().Get(ctx, MockMessageTransmitterType)

    return m.DeploySimpleContract(ctx, func(transactOps *bind.TransactOpts, backend bind.ContractBackend) (address common.Address, tx *types.Transaction, data interface{}, err error) {
        // define the domain as the chain id!
        return mocktokenmessenger.DeployMockTokenMessenger(transactOps, backend, messageTransmitter.Address())
    }, func(address common.Address, backend bind.ContractBackend) (interface{}, error) {
        // remember what I said about vm.ContractRef!
        return mocktokenmessenger.NewMockTokenMessengerRef(address, backend)
    })
}

// Dependencies returns the dependencies of the mocktokenmessenger.
func (m MockTokenMessengerDeployer) Dependencies() []contracts.ContractType {
    return []contracts.ContractType{MockMessageTransmitterType}
}

// NewMockMintBurnTokenDeployer deploys the mocktokenmessenger.
func NewMockMintBurnTokenDeployer(registry deployer.GetOnlyContractRegistry, backend backends.SimulatedTestBackend) deployer.ContractDeployer {
    return MockMintBurnTokenDeployer{deployer.NewSimpleDeployer(registry, backend, MockMintBurnTokenType)}
}

// MockTokenMinterDeployer deploys the mocktokenminter.
type MockTokenMinterDeployer struct {
    *deployer.BaseDeployer
}

// NewMockTokenMinterDeployer deploys the mocktokenminter.
func NewMockTokenMinterDeployer(registry deployer.GetOnlyContractRegistry, backend backends.SimulatedTestBackend) deployer.ContractDeployer {
    return MockTokenMinterDeployer{deployer.NewSimpleDeployer(registry, backend, MockTokenMinterType)}
}

// Deploy deploys the mock token minter contract.
//
//nolint:dupword,dupl,cyclop
func (m MockTokenMinterDeployer) Deploy(ctx context.Context) (contracts.DeployedContract, error) {
    tokenMessenger := m.Registry().Get(ctx, MockTokenMessengerType)

    return m.DeploySimpleContract(ctx, func(transactOps *bind.TransactOpts, backend bind.ContractBackend) (address common.Address, tx *types.Transaction, data interface{}, err error) {
        // define the domain as the chain id!
        address, tx, handle, err := mocktokenminter.DeployMockTokenMinter(transactOps, backend, tokenMessenger.Address())
        if err != nil {
            return address, tx, handle, fmt.Errorf("could not deploy mock token minter: %w", err)
        }

        messengerOpts := m.Backend().GetTxContext(ctx, tokenMessenger.OwnerPtr())
        messengerHandle, ok := tokenMessenger.ContractHandle().(*mocktokenmessenger.MockTokenMessengerRef)
        if !ok {
            return address, tx, handle, fmt.Errorf("could not case %T to %T", tokenMessenger.ContractHandle(), messengerHandle)
        }

        setTx, err := messengerHandle.SetLocalMinter(messengerOpts.TransactOpts, address)
        if err != nil {
            return address, tx, handle, fmt.Errorf("could not set local minter: %w", err)
        }
        m.Backend().WaitForConfirmation(ctx, setTx)

        return address, tx, handle, nil
    }, func(address common.Address, backend bind.ContractBackend) (interface{}, error) {
        // remember what I said about vm.ContractRef!
        return mocktokenminter.NewMockTokenMinterRef(address, backend)
    })
}

// Dependencies returns the dependencies of the mock token minter.
func (m MockTokenMinterDeployer) Dependencies() []contracts.ContractType {
    return m.RecursiveDependencies([]contracts.ContractType{MockTokenMessengerType})
}

// MockMintBurnTokenDeployer deploys the mocktokenminter.
type MockMintBurnTokenDeployer struct {
    *deployer.BaseDeployer
}

// Deploy deploys the mock mint burn token contract.
//
//nolint:dupword,dupl,cyclop
func (m MockMintBurnTokenDeployer) Deploy(ctx context.Context) (contracts.DeployedContract, error) {
    messageTransmitter := m.Registry().Get(ctx, MockMessageTransmitterType)

    return m.DeploySimpleContract(ctx, func(transactOps *bind.TransactOpts, backend bind.ContractBackend) (address common.Address, tx *types.Transaction, data interface{}, err error) {
        // define the domain as the chain id!
        return mockmintburntoken.DeployMockMintBurnToken(transactOps, backend, messageTransmitter.Address())
    }, func(address common.Address, backend bind.ContractBackend) (interface{}, error) {
        // remember what I said about vm.ContractRef!
        return mockmintburntoken.NewMockMintBurnTokenRef(address, backend)
    })
}

// Dependencies returns the dependencies of the mock mint burn token.
func (m MockMintBurnTokenDeployer) Dependencies() []contracts.ContractType {
    return []contracts.ContractType{MockMessageTransmitterType}
}

// SynapseCCTPDeployer deploys the synapse cctp contract.
type SynapseCCTPDeployer struct {
    *deployer.BaseDeployer
}

// NewSynapseCCTPDeployer deploys the synapse cctp contract.
func NewSynapseCCTPDeployer(registry deployer.GetOnlyContractRegistry, backend backends.SimulatedTestBackend) deployer.ContractDeployer {
    return SynapseCCTPDeployer{deployer.NewSimpleDeployer(registry, backend, SynapseCCTPType)}
}

// Deploy deploys the light manager contract.
//
//nolint:dupword,dupl,cyclop
func (d SynapseCCTPDeployer) Deploy(ctx context.Context) (contracts.DeployedContract, error) {
    return d.DeploySimpleContract(ctx, func(transactOps *bind.TransactOpts, backend bind.ContractBackend) (address common.Address, tx *types.Transaction, data interface{}, err error) {
        tokenMessenger := d.Registry().Get(ctx, MockTokenMessengerType)

        // make this a dependency so it self registers the remote domains
        _ = d.Registry().Get(ctx, MockTokenMinterType)

        // define the domain as the chain id!
        return cctp.DeploySynapseCCTP(transactOps, backend, tokenMessenger.Address(), transactOps.From)
    }, func(address common.Address, backend bind.ContractBackend) (interface{}, error) {
        // remember what I said about vm.ContractRef!
        return cctp.NewSynapseCCTPRef(address, backend)
    })
}

// Dependencies returns the dependencies of the SynapseCCTP contract.
func (d SynapseCCTPDeployer) Dependencies() []contracts.ContractType {
    return d.RecursiveDependencies([]contracts.ContractType{MockTokenMessengerType, MockTokenMinterType})
}