synapsecns/sanguine

View on GitHub
ethergo/deployer/base.go

Summary

Maintainability
A
0 mins
Test Coverage
package deployer

import (
    "context"
    "fmt"
    "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"
)

// BaseDeployer is a basic deployment contract. It contains several utility functions including:
// - RecursiveDependencies: can be used to return dependents of dependents (since Dependencies should return all dependents: direct and indirect)
// - DeploySimpleContract: can be used to deploy contracts that don't have to be initialized.
type BaseDeployer struct {
    // registry is the contract registry
    registry GetOnlyContractRegistry
    // backend is the registry
    backend      backends.SimulatedTestBackend
    contractType contracts.ContractType
}

// NewSimpleDeployer creates a new base deployer.
func NewSimpleDeployer(registry GetOnlyContractRegistry, backend backends.SimulatedTestBackend, contractType contracts.ContractType) *BaseDeployer {
    return &BaseDeployer{
        registry:     registry,
        backend:      backend,
        contractType: contractType,
    }
}

// Deploy is a placeholder to ensure function inheritance. Calling this directly will panic.
func (n BaseDeployer) Deploy(ctx context.Context) (contracts.DeployedContract, error) {
    panic("deploy not implemented in base deployer")
}

// Backend gets the backend of the current deployer instance.
func (n BaseDeployer) Backend() backends.SimulatedTestBackend {
    return n.backend
}

// Registry gets the registry.
func (n BaseDeployer) Registry() GetOnlyContractRegistry {
    return n.registry
}

// ContractType returns the contract type.
func (n BaseDeployer) ContractType() contracts.ContractType {
    return n.contractType
}

// Dependencies returns dependencies for the contract - this should be overridden by base classes if there are dependencies.
func (n BaseDeployer) Dependencies() []contracts.ContractType {
    return []contracts.ContractType{}
}

// RecursiveDependencies recursively get dependencies.
func (n BaseDeployer) RecursiveDependencies(dependencies []contracts.ContractType) (res []contracts.ContractType) {
    // check if dependency is already in result
    resultHasDependency := func(dep contracts.ContractType) bool {
        for _, dependency := range res {
            if dep.ID() == dependency.ID() {
                return true
            }
        }
        return false
    }
    // TODO handle cyclicality
    for _, dependency := range dependencies {
        codependencies := append(n.registry.GetRegisteredDeployer(dependency).Dependencies(), dependency)
        for _, dependency := range codependencies {
            if !resultHasDependency(dependency) {
                res = append(res, dependency)
            }
        }
    }
    return res
}

// DeployFunc is the deploy function.
type DeployFunc func(transactOps *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, interface{}, error)

// HandleFunc gets the ref function.
type HandleFunc func(address common.Address, backend bind.ContractBackend) (interface{}, error)

// DeploySimpleContract handles no dependency contract deployments.
// All others must be handled in inheriting structs.
func (n BaseDeployer) DeploySimpleContract(ctx context.Context, deployFunction DeployFunc, handleFunction HandleFunc) (contracts.DeployedContract, error) {
    auth := n.backend.GetTxContext(ctx, nil)
    tmpAddress, tx, _, err := deployFunction(auth.TransactOpts, n.backend)
    if err != nil {
        return nil, fmt.Errorf("could not deploy contract of type %s: %w", n.contractType.ContractName(), err)
    }

    handle, err := handleFunction(tmpAddress, n.backend)
    if err != nil {
        return nil, fmt.Errorf("could not get handke: %w", err)
    }

    return &DeployedContract{
        address:        tmpAddress,
        contractHandle: handle,
        owner:          auth.From,
        chainID:        n.backend.GetBigChainID(),
        deployTx:       tx,
    }, nil
}