Commit 5a012383 authored by Ralph Pichler's avatar Ralph Pichler Committed by GitHub

feat: update default factory and add support for legacy factories (#1539)

parent 54b400eb
......@@ -20,49 +20,50 @@ import (
)
const (
optionNameDataDir = "data-dir"
optionNameDBCapacity = "db-capacity"
optionNameDBOpenFilesLimit = "db-open-files-limit"
optionNameDBBlockCacheCapacity = "db-block-cache-capacity"
optionNameDBWriteBufferSize = "db-write-buffer-size"
optionNameDBDisableSeeksCompaction = "db-disable-seeks-compaction"
optionNamePassword = "password"
optionNamePasswordFile = "password-file"
optionNameAPIAddr = "api-addr"
optionNameP2PAddr = "p2p-addr"
optionNameNATAddr = "nat-addr"
optionNameP2PWSEnable = "p2p-ws-enable"
optionNameP2PQUICEnable = "p2p-quic-enable"
optionNameDebugAPIEnable = "debug-api-enable"
optionNameDebugAPIAddr = "debug-api-addr"
optionNameBootnodes = "bootnode"
optionNameNetworkID = "network-id"
optionWelcomeMessage = "welcome-message"
optionCORSAllowedOrigins = "cors-allowed-origins"
optionNameStandalone = "standalone"
optionNameTracingEnabled = "tracing-enable"
optionNameTracingEndpoint = "tracing-endpoint"
optionNameTracingServiceName = "tracing-service-name"
optionNameVerbosity = "verbosity"
optionNameGlobalPinningEnabled = "global-pinning-enable"
optionNamePaymentThreshold = "payment-threshold"
optionNamePaymentTolerance = "payment-tolerance"
optionNamePaymentEarly = "payment-early"
optionNameResolverEndpoints = "resolver-options"
optionNameBootnodeMode = "bootnode-mode"
optionNameGatewayMode = "gateway-mode"
optionNameClefSignerEnable = "clef-signer-enable"
optionNameClefSignerEndpoint = "clef-signer-endpoint"
optionNameClefSignerEthereumAddress = "clef-signer-ethereum-address"
optionNameSwapEndpoint = "swap-endpoint"
optionNameSwapFactoryAddress = "swap-factory-address"
optionNameSwapInitialDeposit = "swap-initial-deposit"
optionNameSwapEnable = "swap-enable"
optionNameTransactionHash = "transaction"
optionNameFullNode = "full-node"
optionNamePostageContractAddress = "postage-stamp-address"
optionNamePriceOracleAddress = "price-oracle-address"
optionNameBlockTime = "block-time"
optionNameDataDir = "data-dir"
optionNameDBCapacity = "db-capacity"
optionNameDBOpenFilesLimit = "db-open-files-limit"
optionNameDBBlockCacheCapacity = "db-block-cache-capacity"
optionNameDBWriteBufferSize = "db-write-buffer-size"
optionNameDBDisableSeeksCompaction = "db-disable-seeks-compaction"
optionNamePassword = "password"
optionNamePasswordFile = "password-file"
optionNameAPIAddr = "api-addr"
optionNameP2PAddr = "p2p-addr"
optionNameNATAddr = "nat-addr"
optionNameP2PWSEnable = "p2p-ws-enable"
optionNameP2PQUICEnable = "p2p-quic-enable"
optionNameDebugAPIEnable = "debug-api-enable"
optionNameDebugAPIAddr = "debug-api-addr"
optionNameBootnodes = "bootnode"
optionNameNetworkID = "network-id"
optionWelcomeMessage = "welcome-message"
optionCORSAllowedOrigins = "cors-allowed-origins"
optionNameStandalone = "standalone"
optionNameTracingEnabled = "tracing-enable"
optionNameTracingEndpoint = "tracing-endpoint"
optionNameTracingServiceName = "tracing-service-name"
optionNameVerbosity = "verbosity"
optionNameGlobalPinningEnabled = "global-pinning-enable"
optionNamePaymentThreshold = "payment-threshold"
optionNamePaymentTolerance = "payment-tolerance"
optionNamePaymentEarly = "payment-early"
optionNameResolverEndpoints = "resolver-options"
optionNameBootnodeMode = "bootnode-mode"
optionNameGatewayMode = "gateway-mode"
optionNameClefSignerEnable = "clef-signer-enable"
optionNameClefSignerEndpoint = "clef-signer-endpoint"
optionNameClefSignerEthereumAddress = "clef-signer-ethereum-address"
optionNameSwapEndpoint = "swap-endpoint"
optionNameSwapFactoryAddress = "swap-factory-address"
optionNameSwapLegacyFactoryAddresses = "swap-legacy-factory-addresses"
optionNameSwapInitialDeposit = "swap-initial-deposit"
optionNameSwapEnable = "swap-enable"
optionNameTransactionHash = "transaction"
optionNameFullNode = "full-node"
optionNamePostageContractAddress = "postage-stamp-address"
optionNamePriceOracleAddress = "price-oracle-address"
optionNameBlockTime = "block-time"
)
func init() {
......@@ -226,7 +227,8 @@ func (c *command) setAllFlags(cmd *cobra.Command) {
cmd.Flags().String(optionNameClefSignerEndpoint, "", "clef signer endpoint")
cmd.Flags().String(optionNameClefSignerEthereumAddress, "", "ethereum address to use from clef signer")
cmd.Flags().String(optionNameSwapEndpoint, "http://localhost:8545", "swap ethereum blockchain endpoint")
cmd.Flags().String(optionNameSwapFactoryAddress, "", "swap factory address")
cmd.Flags().String(optionNameSwapFactoryAddress, "", "swap factory addresses")
cmd.Flags().StringSlice(optionNameSwapLegacyFactoryAddresses, nil, "legacy swap factory addresses")
cmd.Flags().String(optionNameSwapInitialDeposit, "100000000000000000", "initial deposit if deploying a new chequebook")
cmd.Flags().Bool(optionNameSwapEnable, true, "enable swap")
cmd.Flags().Bool(optionNameFullNode, false, "cause the node to start in full mode")
......
......@@ -74,6 +74,7 @@ func (c *command) initDeployCmd() error {
chainID,
transactionService,
factoryAddress,
nil,
)
if err != nil {
return err
......
......@@ -116,42 +116,43 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz
}
b, err := node.NewBee(c.config.GetString(optionNameP2PAddr), signerConfig.address, *signerConfig.publicKey, signerConfig.signer, c.config.GetUint64(optionNameNetworkID), logger, signerConfig.libp2pPrivateKey, signerConfig.pssPrivateKey, node.Options{
DataDir: c.config.GetString(optionNameDataDir),
DBCapacity: c.config.GetUint64(optionNameDBCapacity),
DBOpenFilesLimit: c.config.GetUint64(optionNameDBOpenFilesLimit),
DBBlockCacheCapacity: c.config.GetUint64(optionNameDBBlockCacheCapacity),
DBWriteBufferSize: c.config.GetUint64(optionNameDBWriteBufferSize),
DBDisableSeeksCompaction: c.config.GetBool(optionNameDBDisableSeeksCompaction),
APIAddr: c.config.GetString(optionNameAPIAddr),
DebugAPIAddr: debugAPIAddr,
Addr: c.config.GetString(optionNameP2PAddr),
NATAddr: c.config.GetString(optionNameNATAddr),
EnableWS: c.config.GetBool(optionNameP2PWSEnable),
EnableQUIC: c.config.GetBool(optionNameP2PQUICEnable),
WelcomeMessage: c.config.GetString(optionWelcomeMessage),
Bootnodes: c.config.GetStringSlice(optionNameBootnodes),
CORSAllowedOrigins: c.config.GetStringSlice(optionCORSAllowedOrigins),
Standalone: c.config.GetBool(optionNameStandalone),
TracingEnabled: c.config.GetBool(optionNameTracingEnabled),
TracingEndpoint: c.config.GetString(optionNameTracingEndpoint),
TracingServiceName: c.config.GetString(optionNameTracingServiceName),
Logger: logger,
GlobalPinningEnabled: c.config.GetBool(optionNameGlobalPinningEnabled),
PaymentThreshold: c.config.GetString(optionNamePaymentThreshold),
PaymentTolerance: c.config.GetString(optionNamePaymentTolerance),
PaymentEarly: c.config.GetString(optionNamePaymentEarly),
ResolverConnectionCfgs: resolverCfgs,
GatewayMode: c.config.GetBool(optionNameGatewayMode),
BootnodeMode: bootNode,
SwapEndpoint: c.config.GetString(optionNameSwapEndpoint),
SwapFactoryAddress: c.config.GetString(optionNameSwapFactoryAddress),
SwapInitialDeposit: c.config.GetString(optionNameSwapInitialDeposit),
SwapEnable: c.config.GetBool(optionNameSwapEnable),
FullNodeMode: fullNode,
Transaction: c.config.GetString(optionNameTransactionHash),
PostageContractAddress: c.config.GetString(optionNamePostageContractAddress),
PriceOracleAddress: c.config.GetString(optionNamePriceOracleAddress),
BlockTime: c.config.GetUint64(optionNameBlockTime),
DataDir: c.config.GetString(optionNameDataDir),
DBCapacity: c.config.GetUint64(optionNameDBCapacity),
DBOpenFilesLimit: c.config.GetUint64(optionNameDBOpenFilesLimit),
DBBlockCacheCapacity: c.config.GetUint64(optionNameDBBlockCacheCapacity),
DBWriteBufferSize: c.config.GetUint64(optionNameDBWriteBufferSize),
DBDisableSeeksCompaction: c.config.GetBool(optionNameDBDisableSeeksCompaction),
APIAddr: c.config.GetString(optionNameAPIAddr),
DebugAPIAddr: debugAPIAddr,
Addr: c.config.GetString(optionNameP2PAddr),
NATAddr: c.config.GetString(optionNameNATAddr),
EnableWS: c.config.GetBool(optionNameP2PWSEnable),
EnableQUIC: c.config.GetBool(optionNameP2PQUICEnable),
WelcomeMessage: c.config.GetString(optionWelcomeMessage),
Bootnodes: c.config.GetStringSlice(optionNameBootnodes),
CORSAllowedOrigins: c.config.GetStringSlice(optionCORSAllowedOrigins),
Standalone: c.config.GetBool(optionNameStandalone),
TracingEnabled: c.config.GetBool(optionNameTracingEnabled),
TracingEndpoint: c.config.GetString(optionNameTracingEndpoint),
TracingServiceName: c.config.GetString(optionNameTracingServiceName),
Logger: logger,
GlobalPinningEnabled: c.config.GetBool(optionNameGlobalPinningEnabled),
PaymentThreshold: c.config.GetString(optionNamePaymentThreshold),
PaymentTolerance: c.config.GetString(optionNamePaymentTolerance),
PaymentEarly: c.config.GetString(optionNamePaymentEarly),
ResolverConnectionCfgs: resolverCfgs,
GatewayMode: c.config.GetBool(optionNameGatewayMode),
BootnodeMode: bootNode,
SwapEndpoint: c.config.GetString(optionNameSwapEndpoint),
SwapFactoryAddress: c.config.GetString(optionNameSwapFactoryAddress),
SwapLegacyFactoryAddresses: c.config.GetStringSlice(optionNameSwapLegacyFactoryAddresses),
SwapInitialDeposit: c.config.GetString(optionNameSwapInitialDeposit),
SwapEnable: c.config.GetBool(optionNameSwapEnable),
FullNodeMode: fullNode,
Transaction: c.config.GetString(optionNameTransactionHash),
PostageContractAddress: c.config.GetString(optionNamePostageContractAddress),
PriceOracleAddress: c.config.GetString(optionNamePriceOracleAddress),
BlockTime: c.config.GetUint64(optionNameBlockTime),
})
if err != nil {
return err
......
......@@ -9,7 +9,7 @@ require (
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/ethereum/go-ethereum v1.9.23
github.com/ethersphere/go-storage-incentives-abi v0.1.0
github.com/ethersphere/go-sw3-abi v0.3.2
github.com/ethersphere/go-sw3-abi v0.4.0
github.com/ethersphere/langos v1.0.0
github.com/gogo/protobuf v1.3.1
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
......
......@@ -143,6 +143,7 @@ github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUn
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf h1:sh8rkQZavChcmakYiSlqu2425CHyFXLZZnvm7PDpU8M=
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
......@@ -161,8 +162,8 @@ github.com/ethereum/go-ethereum v1.9.23 h1:SIKhg/z4Q7AbvqcxuPYvMxf36che/Rq/Pp0Id
github.com/ethereum/go-ethereum v1.9.23/go.mod h1:JIfVb6esrqALTExdz9hRYvrP0xBDf6wCncIu1hNwHpM=
github.com/ethersphere/go-storage-incentives-abi v0.1.0 h1:yxNME3q5dha/pUtIYB07DALhhQjd3+uYhGLFqKMXVyg=
github.com/ethersphere/go-storage-incentives-abi v0.1.0/go.mod h1:SXvJVtM4sEsaSKD0jc1ClpDLw8ErPoROZDme4Wrc/Nc=
github.com/ethersphere/go-sw3-abi v0.3.2 h1:BVTuSZ9Ph/JJBglU9pCRSch3gDq4g5QEto6KzMYP/08=
github.com/ethersphere/go-sw3-abi v0.3.2/go.mod h1:BmpsvJ8idQZdYEtWnvxA8POYQ8Rl/NhyCdF0zLMOOJU=
github.com/ethersphere/go-sw3-abi v0.4.0 h1:T3ANY+ktWrPAwe2U0tZi+DILpkHzto5ym/XwV/Bbz8g=
github.com/ethersphere/go-sw3-abi v0.4.0/go.mod h1:BmpsvJ8idQZdYEtWnvxA8POYQ8Rl/NhyCdF0zLMOOJU=
github.com/ethersphere/langos v1.0.0 h1:NBtNKzXTTRSue95uOlzPN4py7Aofs0xWPzyj4AI1Vcc=
github.com/ethersphere/langos v1.0.0/go.mod h1:dlcN2j4O8sQ+BlCaxeBu43bgr4RQ+inJ+pHwLeZg5Tw=
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
......
......@@ -86,26 +86,43 @@ func InitChequebookFactory(
chainID int64,
transactionService transaction.Service,
factoryAddress string,
legacyFactoryAddresses []string,
) (chequebook.Factory, error) {
var addr common.Address
var currentFactory common.Address
var legacyFactories []common.Address
foundFactory, foundLegacyFactories, found := chequebook.DiscoverFactoryAddress(chainID)
if factoryAddress == "" {
var found bool
addr, found = chequebook.DiscoverFactoryAddress(chainID)
if !found {
return nil, errors.New("no known factory address for this network")
}
logger.Infof("using default factory address for chain id %d: %x", chainID, addr)
currentFactory = foundFactory
logger.Infof("using default factory address for chain id %d: %x", chainID, currentFactory)
} else if !common.IsHexAddress(factoryAddress) {
return nil, errors.New("malformed factory address")
} else {
addr = common.HexToAddress(factoryAddress)
logger.Infof("using custom factory address: %x", addr)
currentFactory = common.HexToAddress(factoryAddress)
logger.Infof("using custom factory address: %x", currentFactory)
}
if legacyFactoryAddresses == nil {
if found {
legacyFactories = foundLegacyFactories
}
} else {
for _, legacyAddress := range legacyFactoryAddresses {
if !common.IsHexAddress(legacyAddress) {
return nil, errors.New("malformed factory address")
}
legacyFactories = append(legacyFactories, common.HexToAddress(legacyAddress))
}
}
return chequebook.NewFactory(
backend,
transactionService,
addr,
currentFactory,
legacyFactories,
), nil
}
......
......@@ -97,42 +97,43 @@ type Bee struct {
}
type Options struct {
DataDir string
DBCapacity uint64
DBOpenFilesLimit uint64
DBWriteBufferSize uint64
DBBlockCacheCapacity uint64
DBDisableSeeksCompaction bool
APIAddr string
DebugAPIAddr string
Addr string
NATAddr string
EnableWS bool
EnableQUIC bool
WelcomeMessage string
Bootnodes []string
CORSAllowedOrigins []string
Logger logging.Logger
Standalone bool
TracingEnabled bool
TracingEndpoint string
TracingServiceName string
GlobalPinningEnabled bool
PaymentThreshold string
PaymentTolerance string
PaymentEarly string
ResolverConnectionCfgs []multiresolver.ConnectionConfig
GatewayMode bool
BootnodeMode bool
SwapEndpoint string
SwapFactoryAddress string
SwapInitialDeposit string
SwapEnable bool
FullNodeMode bool
Transaction string
PostageContractAddress string
PriceOracleAddress string
BlockTime uint64
DataDir string
DBCapacity uint64
DBOpenFilesLimit uint64
DBWriteBufferSize uint64
DBBlockCacheCapacity uint64
DBDisableSeeksCompaction bool
APIAddr string
DebugAPIAddr string
Addr string
NATAddr string
EnableWS bool
EnableQUIC bool
WelcomeMessage string
Bootnodes []string
CORSAllowedOrigins []string
Logger logging.Logger
Standalone bool
TracingEnabled bool
TracingEndpoint string
TracingServiceName string
GlobalPinningEnabled bool
PaymentThreshold string
PaymentTolerance string
PaymentEarly string
ResolverConnectionCfgs []multiresolver.ConnectionConfig
GatewayMode bool
BootnodeMode bool
SwapEndpoint string
SwapFactoryAddress string
SwapLegacyFactoryAddresses []string
SwapInitialDeposit string
SwapEnable bool
FullNodeMode bool
Transaction string
PostageContractAddress string
PriceOracleAddress string
BlockTime uint64
}
func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, signer crypto.Signer, networkID uint64, logger logging.Logger, libp2pPrivateKey, pssPrivateKey *ecdsa.PrivateKey, o Options) (b *Bee, err error) {
......@@ -241,6 +242,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
chainID,
transactionService,
o.SwapFactoryAddress,
o.SwapLegacyFactoryAddresses,
)
if err != nil {
return nil, err
......
......@@ -256,7 +256,7 @@ func TestCashoutStatusReverted(t *testing.T) {
),
transactionmock.New(
transactionmock.WithABISend(&chequebookABI, txHash, chequebookAddress, big.NewInt(0), "cashChequeBeneficiary", recipientAddress, cheque.CumulativePayout, cheque.Signature),
transactionmock.WithABICall(&chequebookABI, onChainPaidOut.FillBytes(make([]byte, 32)), "paidOut", beneficiary),
transactionmock.WithABICall(&chequebookABI, chequebookAddress, onChainPaidOut.FillBytes(make([]byte, 32)), "paidOut", beneficiary),
),
chequestoremock.NewChequeStore(
chequestoremock.WithLastChequeFunc(func(c common.Address) (*chequebook.SignedCheque, error) {
......
......@@ -46,7 +46,7 @@ func TestChequebookBalance(t *testing.T) {
balance := big.NewInt(10)
chequebookService, err := chequebook.New(
transactionmock.New(
transactionmock.WithABICall(&chequebookABI, balance.FillBytes(make([]byte, 32)), "balance"),
transactionmock.WithABICall(&chequebookABI, address, balance.FillBytes(make([]byte, 32)), "balance"),
),
address,
ownerAdress,
......@@ -191,12 +191,12 @@ func TestChequebookIssue(t *testing.T) {
chequebookService, err := chequebook.New(
transactionmock.New(
transactionmock.WithABICallSequence(
transactionmock.ABICall(&chequebookABI, big.NewInt(100).FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, big.NewInt(0).FillBytes(make([]byte, 32)), "totalPaidOut"),
transactionmock.ABICall(&chequebookABI, big.NewInt(100).FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, big.NewInt(0).FillBytes(make([]byte, 32)), "totalPaidOut"),
transactionmock.ABICall(&chequebookABI, big.NewInt(100).FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, big.NewInt(0).FillBytes(make([]byte, 32)), "totalPaidOut"),
transactionmock.ABICall(&chequebookABI, address, big.NewInt(100).FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, address, big.NewInt(0).FillBytes(make([]byte, 32)), "totalPaidOut"),
transactionmock.ABICall(&chequebookABI, address, big.NewInt(100).FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, address, big.NewInt(0).FillBytes(make([]byte, 32)), "totalPaidOut"),
transactionmock.ABICall(&chequebookABI, address, big.NewInt(100).FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, address, big.NewInt(0).FillBytes(make([]byte, 32)), "totalPaidOut"),
),
),
address,
......@@ -377,8 +377,8 @@ func TestChequebookIssueOutOfFunds(t *testing.T) {
chequebookService, err := chequebook.New(
transactionmock.New(
transactionmock.WithABICallSequence(
transactionmock.ABICall(&chequebookABI, big.NewInt(0).FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, big.NewInt(0).FillBytes(make([]byte, 32)), "totalPaidOut"),
transactionmock.ABICall(&chequebookABI, address, big.NewInt(0).FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, address, big.NewInt(0).FillBytes(make([]byte, 32)), "totalPaidOut"),
),
),
address,
......@@ -416,8 +416,8 @@ func TestChequebookWithdraw(t *testing.T) {
chequebookService, err := chequebook.New(
transactionmock.New(
transactionmock.WithABICallSequence(
transactionmock.ABICall(&chequebookABI, balance.FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, big.NewInt(0).FillBytes(make([]byte, 32)), "totalPaidOut"),
transactionmock.ABICall(&chequebookABI, address, balance.FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, address, big.NewInt(0).FillBytes(make([]byte, 32)), "totalPaidOut"),
),
transactionmock.WithABISend(&chequebookABI, txHash, address, big.NewInt(0), "withdraw", withdrawAmount),
),
......@@ -451,8 +451,8 @@ func TestChequebookWithdrawInsufficientFunds(t *testing.T) {
transactionmock.New(
transactionmock.WithABISend(&chequebookABI, txHash, address, big.NewInt(0), "withdraw", withdrawAmount),
transactionmock.WithABICallSequence(
transactionmock.ABICall(&chequebookABI, big.NewInt(0).FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, big.NewInt(0).FillBytes(make([]byte, 32)), "totalPaidOut"),
transactionmock.ABICall(&chequebookABI, address, big.NewInt(0).FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, address, big.NewInt(0).FillBytes(make([]byte, 32)), "totalPaidOut"),
),
),
address,
......
......@@ -53,12 +53,12 @@ func TestReceiveCheque(t *testing.T) {
beneficiary,
transactionmock.New(
transactionmock.WithABICallSequence(
transactionmock.ABICall(&chequebookABI, issuer.Hash().Bytes(), "issuer"),
transactionmock.ABICall(&chequebookABI, cumulativePayout2.FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, big.NewInt(0).FillBytes(make([]byte, 32)), "paidOut", beneficiary),
transactionmock.ABICall(&chequebookABI, issuer.Hash().Bytes(), "issuer"),
transactionmock.ABICall(&chequebookABI, cumulativePayout2.FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, big.NewInt(0).FillBytes(make([]byte, 32)), "paidOut", beneficiary),
transactionmock.ABICall(&chequebookABI, chequebookAddress, issuer.Hash().Bytes(), "issuer"),
transactionmock.ABICall(&chequebookABI, chequebookAddress, cumulativePayout2.FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, chequebookAddress, big.NewInt(0).FillBytes(make([]byte, 32)), "paidOut", beneficiary),
transactionmock.ABICall(&chequebookABI, chequebookAddress, issuer.Hash().Bytes(), "issuer"),
transactionmock.ABICall(&chequebookABI, chequebookAddress, cumulativePayout2.FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, chequebookAddress, big.NewInt(0).FillBytes(make([]byte, 32)), "paidOut", beneficiary),
),
),
func(c *chequebook.SignedCheque, cid int64) (common.Address, error) {
......@@ -175,9 +175,9 @@ func TestReceiveChequeInvalidAmount(t *testing.T) {
beneficiary,
transactionmock.New(
transactionmock.WithABICallSequence(
transactionmock.ABICall(&chequebookABI, issuer.Hash().Bytes(), "issuer"),
transactionmock.ABICall(&chequebookABI, cumulativePayout.FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, big.NewInt(0).FillBytes(make([]byte, 32)), "paidOut", beneficiary),
transactionmock.ABICall(&chequebookABI, chequebookAddress, issuer.Hash().Bytes(), "issuer"),
transactionmock.ABICall(&chequebookABI, chequebookAddress, cumulativePayout.FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, chequebookAddress, big.NewInt(0).FillBytes(make([]byte, 32)), "paidOut", beneficiary),
),
),
func(c *chequebook.SignedCheque, cid int64) (common.Address, error) {
......@@ -232,8 +232,8 @@ func TestReceiveChequeInvalidChequebook(t *testing.T) {
beneficiary,
transactionmock.New(
transactionmock.WithABICallSequence(
transactionmock.ABICall(&chequebookABI, issuer.Bytes(), "issuer"),
transactionmock.ABICall(&chequebookABI, cumulativePayout.FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, chequebookAddress, issuer.Bytes(), "issuer"),
transactionmock.ABICall(&chequebookABI, chequebookAddress, cumulativePayout.FillBytes(make([]byte, 32)), "balance"),
),
),
func(c *chequebook.SignedCheque, cid int64) (common.Address, error) {
......@@ -273,7 +273,7 @@ func TestReceiveChequeInvalidSignature(t *testing.T) {
beneficiary,
transactionmock.New(
transactionmock.WithABICallSequence(
transactionmock.ABICall(&chequebookABI, issuer.Hash().Bytes(), "issuer"),
transactionmock.ABICall(&chequebookABI, chequebookAddress, issuer.Hash().Bytes(), "issuer"),
),
),
func(c *chequebook.SignedCheque, cid int64) (common.Address, error) {
......@@ -313,9 +313,9 @@ func TestReceiveChequeInsufficientBalance(t *testing.T) {
beneficiary,
transactionmock.New(
transactionmock.WithABICallSequence(
transactionmock.ABICall(&chequebookABI, issuer.Hash().Bytes(), "issuer"),
transactionmock.ABICall(&chequebookABI, new(big.Int).Sub(cumulativePayout, big.NewInt(1)).FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, big.NewInt(0).FillBytes(make([]byte, 32)), "paidOut", beneficiary),
transactionmock.ABICall(&chequebookABI, chequebookAddress, issuer.Hash().Bytes(), "issuer"),
transactionmock.ABICall(&chequebookABI, chequebookAddress, new(big.Int).Sub(cumulativePayout, big.NewInt(1)).FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, chequebookAddress, big.NewInt(0).FillBytes(make([]byte, 32)), "paidOut", beneficiary),
),
),
func(c *chequebook.SignedCheque, cid int64) (common.Address, error) {
......@@ -355,9 +355,9 @@ func TestReceiveChequeSufficientBalancePaidOut(t *testing.T) {
beneficiary,
transactionmock.New(
transactionmock.WithABICallSequence(
transactionmock.ABICall(&chequebookABI, issuer.Hash().Bytes(), "issuer"),
transactionmock.ABICall(&chequebookABI, new(big.Int).Sub(cumulativePayout, big.NewInt(100)).FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, big.NewInt(0).FillBytes(make([]byte, 32)), "paidOut", beneficiary),
transactionmock.ABICall(&chequebookABI, chequebookAddress, issuer.Hash().Bytes(), "issuer"),
transactionmock.ABICall(&chequebookABI, chequebookAddress, new(big.Int).Sub(cumulativePayout, big.NewInt(100)).FillBytes(make([]byte, 32)), "balance"),
transactionmock.ABICall(&chequebookABI, chequebookAddress, big.NewInt(0).FillBytes(make([]byte, 32)), "paidOut", beneficiary),
),
),
func(c *chequebook.SignedCheque, cid int64) (common.Address, error) {
......
......@@ -22,7 +22,7 @@ func (m *chequeSignerMock) Sign(cheque *chequebook.Cheque) ([]byte, error) {
type factoryMock struct {
erc20Address func(ctx context.Context) (common.Address, error)
deploy func(ctx context.Context, issuer common.Address, defaultHardDepositTimeoutDuration *big.Int) (common.Hash, error)
deploy func(ctx context.Context, issuer common.Address, defaultHardDepositTimeoutDuration *big.Int, nonce common.Hash) (common.Hash, error)
waitDeployed func(ctx context.Context, txHash common.Hash) (common.Address, error)
verifyBytecode func(ctx context.Context) error
verifyChequebook func(ctx context.Context, chequebook common.Address) error
......@@ -33,8 +33,8 @@ func (m *factoryMock) ERC20Address(ctx context.Context) (common.Address, error)
return m.erc20Address(ctx)
}
func (m *factoryMock) Deploy(ctx context.Context, issuer common.Address, defaultHardDepositTimeoutDuration *big.Int) (common.Hash, error) {
return m.deploy(ctx, issuer, defaultHardDepositTimeoutDuration)
func (m *factoryMock) Deploy(ctx context.Context, issuer common.Address, defaultHardDepositTimeoutDuration *big.Int, nonce common.Hash) (common.Hash, error) {
return m.deploy(ctx, issuer, defaultHardDepositTimeoutDuration, nonce)
}
func (m *factoryMock) WaitDeployed(ctx context.Context, txHash common.Hash) (common.Address, error) {
......
......@@ -22,7 +22,7 @@ var (
ErrNotDeployedByFactory = errors.New("chequebook not deployed by factory")
errDecodeABI = errors.New("could not decode abi data")
factoryABI = transaction.ParseABIUnchecked(sw3abi.SimpleSwapFactoryABIv0_3_1)
factoryABI = transaction.ParseABIUnchecked(sw3abi.SimpleSwapFactoryABIv0_4_0)
simpleSwapDeployedEventType = factoryABI.Events["SimpleSwapDeployed"]
)
......@@ -31,7 +31,7 @@ type Factory interface {
// ERC20Address returns the token for which this factory deploys chequebooks.
ERC20Address(ctx context.Context) (common.Address, error)
// Deploy deploys a new chequebook and returns once the transaction has been submitted.
Deploy(ctx context.Context, issuer common.Address, defaultHardDepositTimeoutDuration *big.Int) (common.Hash, error)
Deploy(ctx context.Context, issuer common.Address, defaultHardDepositTimeoutDuration *big.Int, nonce common.Hash) (common.Hash, error)
// WaitDeployed waits for the deployment transaction to confirm and returns the chequebook address
WaitDeployed(ctx context.Context, txHash common.Hash) (common.Address, error)
// VerifyBytecode checks that the factory is valid.
......@@ -43,25 +43,36 @@ type Factory interface {
type factory struct {
backend transaction.Backend
transactionService transaction.Service
address common.Address
address common.Address // address of the factory to use for deployments
legacyAddresses []common.Address // addresses of old factories which were allowed for deployment
}
type simpleSwapDeployedEvent struct {
ContractAddress common.Address
}
// the bytecode of factories which can be used for deployment
var currentDeployVersion []byte = common.FromHex(sw3abi.SimpleSwapFactoryDeployedBinv0_4_0)
// the bytecode of factories from which we accept chequebooks
var supportedVersions = [][]byte{
currentDeployVersion,
common.FromHex(sw3abi.SimpleSwapFactoryDeployedBinv0_3_1),
}
// NewFactory creates a new factory service for the provided factory contract.
func NewFactory(backend transaction.Backend, transactionService transaction.Service, address common.Address) Factory {
func NewFactory(backend transaction.Backend, transactionService transaction.Service, address common.Address, legacyAddresses []common.Address) Factory {
return &factory{
backend: backend,
transactionService: transactionService,
address: address,
legacyAddresses: legacyAddresses,
}
}
// Deploy deploys a new chequebook and returns once the transaction has been submitted.
func (c *factory) Deploy(ctx context.Context, issuer common.Address, defaultHardDepositTimeoutDuration *big.Int) (common.Hash, error) {
callData, err := factoryABI.Pack("deploySimpleSwap", issuer, big.NewInt(0).Set(defaultHardDepositTimeoutDuration))
func (c *factory) Deploy(ctx context.Context, issuer common.Address, defaultHardDepositTimeoutDuration *big.Int, nonce common.Hash) (common.Hash, error) {
callData, err := factoryABI.Pack("deploySimpleSwap", issuer, big.NewInt(0).Set(defaultHardDepositTimeoutDuration), nonce)
if err != nil {
return common.Hash{}, err
}
......@@ -105,45 +116,83 @@ func (c *factory) VerifyBytecode(ctx context.Context) (err error) {
return err
}
referenceCode := common.FromHex(sw3abi.SimpleSwapFactoryDeployedBinv0_3_1)
if !bytes.Equal(code, referenceCode) {
if !bytes.Equal(code, currentDeployVersion) {
return ErrInvalidFactory
}
LOOP:
for _, factoryAddress := range c.legacyAddresses {
code, err := c.backend.CodeAt(ctx, factoryAddress, nil)
if err != nil {
return err
}
for _, referenceCode := range supportedVersions {
if bytes.Equal(code, referenceCode) {
continue LOOP
}
}
return fmt.Errorf("failed to find matching bytecode for factory %x: %w", factoryAddress, ErrInvalidFactory)
}
return nil
}
// VerifyChequebook checks that the supplied chequebook has been deployed by this factory.
func (c *factory) VerifyChequebook(ctx context.Context, chequebook common.Address) error {
func (c *factory) verifyChequebookAgainstFactory(ctx context.Context, factory common.Address, chequebook common.Address) (bool, error) {
callData, err := factoryABI.Pack("deployedContracts", chequebook)
if err != nil {
return err
return false, err
}
output, err := c.transactionService.Call(ctx, &transaction.TxRequest{
To: &c.address,
To: &factory,
Data: callData,
})
if err != nil {
return err
return false, err
}
results, err := factoryABI.Unpack("deployedContracts", output)
if err != nil {
return err
return false, err
}
if len(results) != 1 {
return errDecodeABI
return false, errDecodeABI
}
deployed, ok := abi.ConvertType(results[0], new(bool)).(*bool)
if !ok || deployed == nil {
return errDecodeABI
return false, errDecodeABI
}
if !*deployed {
return ErrNotDeployedByFactory
return false, nil
}
return nil
return true, nil
}
// VerifyChequebook checks that the supplied chequebook has been deployed by a supported factory.
func (c *factory) VerifyChequebook(ctx context.Context, chequebook common.Address) error {
deployed, err := c.verifyChequebookAgainstFactory(ctx, c.address, chequebook)
if err != nil {
return err
}
if deployed {
return nil
}
for _, factoryAddress := range c.legacyAddresses {
deployed, err := c.verifyChequebookAgainstFactory(ctx, factoryAddress, chequebook)
if err != nil {
return err
}
if deployed {
return nil
}
}
return ErrNotDeployedByFactory
}
// ERC20Address returns the token for which this factory deploys chequebooks.
......@@ -178,10 +227,12 @@ func (c *factory) ERC20Address(ctx context.Context) (common.Address, error) {
}
// DiscoverFactoryAddress returns the canonical factory for this chainID
func DiscoverFactoryAddress(chainID int64) (common.Address, bool) {
func DiscoverFactoryAddress(chainID int64) (currentFactory common.Address, legacyFactories []common.Address, found bool) {
if chainID == 5 {
// goerli
return common.HexToAddress("0xf0277caffea72734853b834afc9892461ea18474"), true
return common.HexToAddress("0x73c412512E1cA0be3b89b77aB3466dA6A1B9d273"), []common.Address{
common.HexToAddress("0xf0277caffea72734853b834afc9892461ea18474"),
}, true
}
return common.Address{}, false
return common.Address{}, nil, false
}
......@@ -7,6 +7,7 @@ package chequebook_test
import (
"context"
"errors"
"fmt"
"math/big"
"testing"
......@@ -20,7 +21,7 @@ import (
)
var (
factoryABI = transaction.ParseABIUnchecked(sw3abi.SimpleSwapFactoryABIv0_3_1)
factoryABI = transaction.ParseABIUnchecked(sw3abi.SimpleSwapFactoryABIv0_4_0)
simpleSwapDeployedEvent = factoryABI.Events["SimpleSwapDeployed"]
)
......@@ -32,11 +33,13 @@ func TestFactoryERC20Address(t *testing.T) {
transactionmock.New(
transactionmock.WithABICall(
&factoryABI,
factoryAddress,
erc20Address.Hash().Bytes(),
"ERC20Address",
),
),
factoryAddress,
nil,
)
addr, err := factory.ERC20Address(context.Background())
......@@ -49,101 +52,188 @@ func TestFactoryERC20Address(t *testing.T) {
}
}
func backendWithCodeAt(codeMap map[common.Address]string) transaction.Backend {
return backendmock.New(
backendmock.WithCodeAtFunc(func(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) {
code, ok := codeMap[contract]
if !ok {
return nil, fmt.Errorf("called with wrong address. wanted one of %v, got %x", codeMap, contract)
}
if blockNumber != nil {
return nil, errors.New("not called for latest block")
}
return common.FromHex(code), nil
}),
)
}
func TestFactoryVerifySelf(t *testing.T) {
factoryAddress := common.HexToAddress("0xabcd")
factory := chequebook.NewFactory(
backendmock.New(
backendmock.WithCodeAtFunc(func(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) {
if contract != factoryAddress {
t.Fatalf("called with wrong address. wanted %x, got %x", factoryAddress, contract)
}
if blockNumber != nil {
t.Fatal("not called for latest block")
}
return common.FromHex(sw3abi.SimpleSwapFactoryDeployedBinv0_3_1), nil
legacyFactory1 := common.HexToAddress("0xbbbb")
legacyFactory2 := common.HexToAddress("0xcccc")
t.Run("valid", func(t *testing.T) {
factory := chequebook.NewFactory(
backendWithCodeAt(map[common.Address]string{
factoryAddress: sw3abi.SimpleSwapFactoryDeployedBinv0_4_0,
legacyFactory1: sw3abi.SimpleSwapFactoryDeployedBinv0_3_1,
legacyFactory2: sw3abi.SimpleSwapFactoryDeployedBinv0_3_1,
}),
),
transactionmock.New(),
factoryAddress,
)
transactionmock.New(),
factoryAddress,
[]common.Address{legacyFactory1, legacyFactory2},
)
err := factory.VerifyBytecode(context.Background())
if err != nil {
t.Fatal(err)
}
}
err := factory.VerifyBytecode(context.Background())
if err != nil {
t.Fatal(err)
}
})
func TestFactoryVerifySelfInvalidCode(t *testing.T) {
factoryAddress := common.HexToAddress("0xabcd")
factory := chequebook.NewFactory(
backendmock.New(
backendmock.WithCodeAtFunc(func(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) {
if contract != factoryAddress {
t.Fatalf("called with wrong address. wanted %x, got %x", factoryAddress, contract)
}
if blockNumber != nil {
t.Fatal("not called for latest block")
}
return common.FromHex("abcd"), nil
t.Run("invalid deploy factory", func(t *testing.T) {
factory := chequebook.NewFactory(
backendWithCodeAt(map[common.Address]string{
factoryAddress: "abcd",
}),
),
transactionmock.New(),
factoryAddress,
)
transactionmock.New(),
factoryAddress,
nil,
)
err := factory.VerifyBytecode(context.Background())
if err == nil {
t.Fatal("verified invalid factory")
}
if !errors.Is(err, chequebook.ErrInvalidFactory) {
t.Fatalf("wrong error. wanted %v, got %v", chequebook.ErrInvalidFactory, err)
}
err := factory.VerifyBytecode(context.Background())
if err == nil {
t.Fatal("verified invalid factory")
}
if !errors.Is(err, chequebook.ErrInvalidFactory) {
t.Fatalf("wrong error. wanted %v, got %v", chequebook.ErrInvalidFactory, err)
}
})
t.Run("invalid legacy factories", func(t *testing.T) {
factory := chequebook.NewFactory(
backendWithCodeAt(map[common.Address]string{
factoryAddress: sw3abi.SimpleSwapFactoryDeployedBinv0_4_0,
legacyFactory1: sw3abi.SimpleSwapFactoryDeployedBinv0_3_1,
legacyFactory2: "abcd",
}),
transactionmock.New(),
factoryAddress,
[]common.Address{legacyFactory1, legacyFactory2},
)
err := factory.VerifyBytecode(context.Background())
if err == nil {
t.Fatal("verified invalid factory")
}
if !errors.Is(err, chequebook.ErrInvalidFactory) {
t.Fatalf("wrong error. wanted %v, got %v", chequebook.ErrInvalidFactory, err)
}
})
}
func TestFactoryVerifyChequebook(t *testing.T) {
factoryAddress := common.HexToAddress("0xabcd")
chequebookAddress := common.HexToAddress("0xefff")
factory := chequebook.NewFactory(
backendmock.New(),
transactionmock.New(
transactionmock.WithABICall(
&factoryABI,
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001"),
"deployedContracts",
chequebookAddress,
),
),
factoryAddress,
)
err := factory.VerifyChequebook(context.Background(), chequebookAddress)
if err != nil {
t.Fatal(err)
}
}
legacyFactory1 := common.HexToAddress("0xbbbb")
legacyFactory2 := common.HexToAddress("0xcccc")
func TestFactoryVerifyChequebookInvalid(t *testing.T) {
factoryAddress := common.HexToAddress("0xabcd")
chequebookAddress := common.HexToAddress("0xefff")
factory := chequebook.NewFactory(
backendmock.New(),
transactionmock.New(
transactionmock.WithABICall(
&factoryABI,
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"),
"deployedContracts",
chequebookAddress,
t.Run("valid", func(t *testing.T) {
factory := chequebook.NewFactory(
backendmock.New(),
transactionmock.New(
transactionmock.WithABICall(
&factoryABI,
factoryAddress,
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001"),
"deployedContracts",
chequebookAddress,
),
),
),
factoryAddress,
)
factoryAddress,
[]common.Address{legacyFactory1, legacyFactory2},
)
err := factory.VerifyChequebook(context.Background(), chequebookAddress)
if err != nil {
t.Fatal(err)
}
})
err := factory.VerifyChequebook(context.Background(), chequebookAddress)
if err == nil {
t.Fatal("verified invalid chequebook")
}
if !errors.Is(err, chequebook.ErrNotDeployedByFactory) {
t.Fatalf("wrong error. wanted %v, got %v", chequebook.ErrNotDeployedByFactory, err)
}
t.Run("valid legacy", func(t *testing.T) {
factory := chequebook.NewFactory(
backendmock.New(),
transactionmock.New(
transactionmock.WithABICallSequence(
transactionmock.ABICall(
&factoryABI,
factoryAddress,
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"),
"deployedContracts",
chequebookAddress,
),
transactionmock.ABICall(
&factoryABI,
legacyFactory1,
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"),
"deployedContracts",
chequebookAddress,
),
transactionmock.ABICall(
&factoryABI,
legacyFactory2,
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000001"),
"deployedContracts",
chequebookAddress,
),
)),
factoryAddress,
[]common.Address{legacyFactory1, legacyFactory2},
)
err := factory.VerifyChequebook(context.Background(), chequebookAddress)
if err != nil {
t.Fatal(err)
}
})
t.Run("invalid", func(t *testing.T) {
factory := chequebook.NewFactory(
backendmock.New(),
transactionmock.New(
transactionmock.WithABICallSequence(
transactionmock.ABICall(
&factoryABI,
factoryAddress,
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"),
"deployedContracts",
chequebookAddress,
),
transactionmock.ABICall(
&factoryABI,
legacyFactory1,
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"),
"deployedContracts",
chequebookAddress,
),
transactionmock.ABICall(
&factoryABI,
legacyFactory2,
common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000"),
"deployedContracts",
chequebookAddress,
),
)),
factoryAddress,
[]common.Address{legacyFactory1, legacyFactory2},
)
err := factory.VerifyChequebook(context.Background(), chequebookAddress)
if err == nil {
t.Fatal("verified invalid chequebook")
}
if !errors.Is(err, chequebook.ErrNotDeployedByFactory) {
t.Fatalf("wrong error. wanted %v, got %v", chequebook.ErrNotDeployedByFactory, err)
}
})
}
func TestFactoryDeploy(t *testing.T) {
......@@ -152,10 +242,12 @@ func TestFactoryDeploy(t *testing.T) {
defaultTimeout := big.NewInt(1)
deployTransactionHash := common.HexToHash("0xffff")
deployAddress := common.HexToAddress("0xdddd")
nonce := common.HexToHash("eeff")
factory := chequebook.NewFactory(
backendmock.New(),
transactionmock.New(
transactionmock.WithABISend(&factoryABI, deployTransactionHash, factoryAddress, big.NewInt(0), "deploySimpleSwap", issuerAddress, defaultTimeout),
transactionmock.WithABISend(&factoryABI, deployTransactionHash, factoryAddress, big.NewInt(0), "deploySimpleSwap", issuerAddress, defaultTimeout, nonce),
transactionmock.WithWaitForReceiptFunc(func(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) {
if txHash != deployTransactionHash {
t.Fatalf("waiting for wrong transaction. wanted %x, got %x", deployTransactionHash, txHash)
......@@ -180,9 +272,10 @@ func TestFactoryDeploy(t *testing.T) {
},
)),
factoryAddress,
nil,
)
txHash, err := factory.Deploy(context.Background(), issuerAddress, defaultTimeout)
txHash, err := factory.Deploy(context.Background(), issuerAddress, defaultTimeout, nonce)
if err != nil {
t.Fatal(err)
}
......@@ -217,6 +310,7 @@ func TestFactoryDeployReverted(t *testing.T) {
}),
),
factoryAddress,
nil,
)
_, err := factory.WaitDeployed(context.Background(), deployTransactionHash)
......
......@@ -6,6 +6,7 @@ package chequebook
import (
"context"
"crypto/rand"
"fmt"
"math/big"
"time"
......@@ -137,8 +138,14 @@ func Init(
}
}
nonce := make([]byte, 32)
_, err = rand.Read(nonce)
if err != nil {
return nil, err
}
// if we don't yet have a chequebook, deploy a new one
txHash, err = chequebookFactory.Deploy(ctx, overlayEthAddress, big.NewInt(0))
txHash, err = chequebookFactory.Deploy(ctx, overlayEthAddress, big.NewInt(0), common.BytesToHash(nonce))
if err != nil {
return nil, err
}
......
......@@ -31,6 +31,7 @@ func TestBalanceOf(t *testing.T) {
transactionmock.New(
transactionmock.WithABICall(
&erc20ABI,
erc20Address,
expectedBalance.FillBytes(make([]byte, 32)),
"balanceOf",
account,
......
......@@ -89,13 +89,15 @@ func New(opts ...Option) transaction.Service {
type Call struct {
abi *abi.ABI
to common.Address
result []byte
method string
params []interface{}
}
func ABICall(abi *abi.ABI, result []byte, method string, params ...interface{}) Call {
func ABICall(abi *abi.ABI, to common.Address, result []byte, method string, params ...interface{}) Call {
return Call{
to: to,
abi: abi,
result: result,
method: method,
......@@ -121,6 +123,13 @@ func WithABICallSequence(calls ...Call) Option {
return nil, fmt.Errorf("wrong data. wanted %x, got %x", data, request.Data)
}
if request.To == nil {
return nil, errors.New("call with no recipient")
}
if *request.To != call.to {
return nil, fmt.Errorf("wrong recipient. wanted %x, got %x", call.to, *request.To)
}
calls = calls[1:]
return call.result, nil
......@@ -128,8 +137,8 @@ func WithABICallSequence(calls ...Call) Option {
})
}
func WithABICall(abi *abi.ABI, result []byte, method string, params ...interface{}) Option {
return WithABICallSequence(ABICall(abi, result, method, params...))
func WithABICall(abi *abi.ABI, to common.Address, result []byte, method string, params ...interface{}) Option {
return WithABICallSequence(ABICall(abi, to, result, method, params...))
}
func WithABISend(abi *abi.ABI, txHash common.Hash, expectedAddress common.Address, expectedValue *big.Int, method string, params ...interface{}) Option {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment