mirror of
https://github.com/AthanorLabs/atomic-swap.git
synced 2026-01-09 14:18:03 -05:00
186 lines
5.2 KiB
Go
186 lines
5.2 KiB
Go
// Copyright 2023 The AthanorLabs/atomic-swap Authors
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
//go:build !prod
|
|
|
|
package contracts
|
|
|
|
import (
|
|
"context"
|
|
"crypto/ecdsa"
|
|
"math/big"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
|
ethcommon "github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/ethclient"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/athanorlabs/atomic-swap/coins"
|
|
"github.com/athanorlabs/atomic-swap/common"
|
|
"github.com/athanorlabs/atomic-swap/ethereum/block"
|
|
)
|
|
|
|
//
|
|
// FUNCTIONS ONLY FOR UNIT TESTS
|
|
//
|
|
|
|
// these variables should only be accessed by DevDeploySwapCreator
|
|
var _swapCreator *SwapCreator
|
|
var _swapCreatorAddr *ethcommon.Address
|
|
var _swapCreatorAddrMu sync.Mutex
|
|
|
|
// DevDeploySwapCreator deploys and returns the swapCreator address and contract
|
|
// binding for unit tests, returning a cached result if available.
|
|
func DevDeploySwapCreator(t *testing.T, ec *ethclient.Client, pk *ecdsa.PrivateKey) (ethcommon.Address, *SwapCreator) {
|
|
ctx := context.Background()
|
|
_swapCreatorAddrMu.Lock()
|
|
defer _swapCreatorAddrMu.Unlock()
|
|
|
|
if _swapCreatorAddr == nil {
|
|
txOpts, err := newTXOpts(ctx, ec, pk)
|
|
require.NoError(t, err)
|
|
|
|
swapCreatorAddr, tx, swapCreator, err := DeploySwapCreator(txOpts, ec)
|
|
require.NoError(t, err)
|
|
|
|
receipt, err := block.WaitForReceipt(ctx, ec, tx.Hash())
|
|
require.NoError(t, err)
|
|
|
|
t.Logf("gas cost to deploy SwapCreator.sol: %d (delta %d)",
|
|
receipt.GasUsed, maxSwapCreatorDeployGas-int(receipt.GasUsed))
|
|
require.GreaterOrEqual(t, maxSwapCreatorDeployGas, int(receipt.GasUsed), "deploy SwapCreator")
|
|
|
|
_swapCreatorAddr = &swapCreatorAddr
|
|
_swapCreator = swapCreator
|
|
}
|
|
|
|
return *_swapCreatorAddr, _swapCreator
|
|
}
|
|
|
|
// variables should only be accessed by GetMockTether
|
|
var _mockTether *coins.ERC20TokenInfo
|
|
var _mockTetherMu sync.Mutex
|
|
|
|
// GetMockTether returns the ERC20TokenInfo of a dev token configured with
|
|
// similar parameters to Tether.
|
|
func GetMockTether(t *testing.T, ec *ethclient.Client, pk *ecdsa.PrivateKey) *coins.ERC20TokenInfo {
|
|
const (
|
|
name = "Tether USD"
|
|
symbol = "USDT"
|
|
numDecimals = 6
|
|
)
|
|
|
|
_mockTetherMu.Lock()
|
|
defer _mockTetherMu.Unlock()
|
|
|
|
if _mockTether != nil {
|
|
mintTokens(t, ec, pk, _mockTether)
|
|
return _mockTether
|
|
}
|
|
|
|
ownerAddress := common.EthereumPrivateKeyToAddress(pk)
|
|
|
|
ctx := context.Background()
|
|
txOpts, err := newTXOpts(ctx, ec, pk)
|
|
require.NoError(t, err)
|
|
|
|
supply := calcTokenUnits(1000, numDecimals)
|
|
addr, tx, _, err := DeployTestERC20(txOpts, ec, name, symbol, numDecimals, ownerAddress, supply)
|
|
require.NoError(t, err)
|
|
_, err = block.WaitForReceipt(context.Background(), ec, tx.Hash())
|
|
require.NoError(t, err)
|
|
|
|
_mockTether = &coins.ERC20TokenInfo{
|
|
Address: addr,
|
|
NumDecimals: numDecimals,
|
|
Name: name,
|
|
Symbol: symbol,
|
|
}
|
|
|
|
return _mockTether
|
|
}
|
|
|
|
// variables should only be accessed by GetMockDAI
|
|
var _mockDAI *coins.ERC20TokenInfo
|
|
var _mockDAIMu sync.Mutex
|
|
|
|
// GetMockDAI returns the ERC20TokenInfo of a dev token configured with
|
|
// similar parameters to the DAI stablecoin.
|
|
func GetMockDAI(t *testing.T, ec *ethclient.Client, pk *ecdsa.PrivateKey) *coins.ERC20TokenInfo {
|
|
const (
|
|
name = "Dai Stablecoin"
|
|
symbol = "DAI"
|
|
numDecimals = 18
|
|
)
|
|
|
|
_mockDAIMu.Lock()
|
|
defer _mockDAIMu.Unlock()
|
|
|
|
if _mockDAI != nil {
|
|
mintTokens(t, ec, pk, _mockDAI)
|
|
return _mockDAI
|
|
}
|
|
|
|
ownerAddress := common.EthereumPrivateKeyToAddress(pk)
|
|
|
|
ctx := context.Background()
|
|
txOpts, err := newTXOpts(ctx, ec, pk)
|
|
require.NoError(t, err)
|
|
|
|
supply := calcTokenUnits(1000, numDecimals)
|
|
addr, tx, _, err := DeployTestERC20(txOpts, ec, name, symbol, numDecimals, ownerAddress, supply)
|
|
require.NoError(t, err)
|
|
_, err = block.WaitForReceipt(context.Background(), ec, tx.Hash())
|
|
require.NoError(t, err)
|
|
|
|
_mockDAI = &coins.ERC20TokenInfo{
|
|
Address: addr,
|
|
NumDecimals: numDecimals,
|
|
Name: name,
|
|
Symbol: symbol,
|
|
}
|
|
|
|
return _mockDAI
|
|
}
|
|
|
|
// calcTokenUnits converts the token's standard units into its internal,
|
|
// smallest non-divisible units.
|
|
func calcTokenUnits(numStdUnits int64, decimals uint8) *big.Int {
|
|
powerOf10 := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(decimals)), nil)
|
|
return new(big.Int).Mul(big.NewInt(numStdUnits), powerOf10)
|
|
}
|
|
|
|
// mintTokens ensures that the account associated with `pk` has at least 1000 tokens
|
|
func mintTokens(t *testing.T, ec *ethclient.Client, pk *ecdsa.PrivateKey, token *coins.ERC20TokenInfo) {
|
|
ctx := context.Background()
|
|
bindOpts := &bind.CallOpts{Context: ctx}
|
|
|
|
tokenContract, err := NewTestERC20(token.Address, ec)
|
|
require.NoError(t, err)
|
|
|
|
decimals, err := tokenContract.Decimals(bindOpts)
|
|
require.NoError(t, err)
|
|
|
|
symbol, err := tokenContract.Symbol(bindOpts)
|
|
require.NoError(t, err)
|
|
require.Equal(t, token.Symbol, symbol)
|
|
|
|
ownerAddress := common.EthereumPrivateKeyToAddress(pk)
|
|
|
|
desiredAmt := calcTokenUnits(1000, decimals)
|
|
currentAmt, err := tokenContract.BalanceOf(bindOpts, ownerAddress)
|
|
require.NoError(t, err)
|
|
|
|
if currentAmt.Cmp(desiredAmt) < 0 {
|
|
txOpts, err := newTXOpts(context.Background(), ec, pk)
|
|
require.NoError(t, err)
|
|
mintAmt := new(big.Int).Sub(desiredAmt, currentAmt)
|
|
tx, err := tokenContract.Mint(txOpts, ownerAddress, mintAmt)
|
|
require.NoError(t, err)
|
|
_, err = block.WaitForReceipt(ctx, ec, tx.Hash())
|
|
require.NoError(t, err)
|
|
}
|
|
}
|