Some checks failed
V2 CI/CD Pipeline / Pre-Flight Checks (push) Has been cancelled
V2 CI/CD Pipeline / Build & Dependencies (push) Has been cancelled
V2 CI/CD Pipeline / Code Quality & Linting (push) Has been cancelled
V2 CI/CD Pipeline / Unit Tests (100% Coverage Required) (push) Has been cancelled
V2 CI/CD Pipeline / Integration Tests (push) Has been cancelled
V2 CI/CD Pipeline / Performance Benchmarks (push) Has been cancelled
V2 CI/CD Pipeline / Decimal Precision Validation (push) Has been cancelled
V2 CI/CD Pipeline / Modularity Validation (push) Has been cancelled
V2 CI/CD Pipeline / Final Validation Summary (push) Has been cancelled
Add comprehensive unit tests for all execution engine components: Component Test Coverage: - UniswapV2 encoder: 15 test cases + benchmarks - UniswapV3 encoder: 20 test cases + benchmarks - Curve encoder: 16 test cases + benchmarks - Flashloan manager: 18 test cases + benchmarks - Transaction builder: 15 test cases + benchmarks - Risk manager: 25 test cases + benchmarks - Executor: 20 test cases + benchmarks Test Categories: - Happy path scenarios - Error handling and edge cases - Zero/invalid inputs - Boundary conditions (max amounts, limits) - Concurrent operations (nonce management) - Configuration validation - State management Key Test Features: - Protocol-specific encoding validation - ABI encoding correctness - Gas calculation accuracy - Slippage calculation - Nonce management thread safety - Circuit breaker behavior - Risk assessment rules - Transaction lifecycle Total: 129 test cases + performance benchmarks Target: 100% test coverage for execution engine Related to Phase 4 (Execution Engine) implementation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
483 lines
15 KiB
Go
483 lines
15 KiB
Go
package execution
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
"math/big"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/your-org/mev-bot/pkg/arbitrage"
|
|
)
|
|
|
|
func TestNewFlashloanManager(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
manager := NewFlashloanManager(nil, logger)
|
|
|
|
assert.NotNil(t, manager)
|
|
assert.NotNil(t, manager.config)
|
|
assert.NotNil(t, manager.aaveV3Encoder)
|
|
assert.NotNil(t, manager.uniswapV3Encoder)
|
|
assert.NotNil(t, manager.uniswapV2Encoder)
|
|
}
|
|
|
|
func TestDefaultFlashloanConfig(t *testing.T) {
|
|
config := DefaultFlashloanConfig()
|
|
|
|
assert.NotNil(t, config)
|
|
assert.Len(t, config.PreferredProviders, 3)
|
|
assert.Equal(t, FlashloanProviderAaveV3, config.PreferredProviders[0])
|
|
assert.Equal(t, uint16(9), config.AaveV3FeeBPS)
|
|
assert.Equal(t, uint16(0), config.UniswapV3FeeBPS)
|
|
assert.Equal(t, uint16(30), config.UniswapV2FeeBPS)
|
|
}
|
|
|
|
func TestFlashloanManager_BuildFlashloanTransaction_AaveV3(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
config := DefaultFlashloanConfig()
|
|
config.ExecutorContract = common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
|
|
manager := NewFlashloanManager(config, logger)
|
|
|
|
opp := &arbitrage.Opportunity{
|
|
InputToken: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
InputAmount: big.NewInt(1e18),
|
|
Path: []arbitrage.SwapStep{
|
|
{
|
|
TokenIn: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
TokenOut: common.HexToAddress("0xFF970a61A04b1cA14834A43f5dE4533eBDDB5CC8"),
|
|
PoolAddress: common.HexToAddress("0x0000000000000000000000000000000000000002"),
|
|
},
|
|
},
|
|
}
|
|
|
|
swapCalldata := []byte{0x01, 0x02, 0x03, 0x04}
|
|
|
|
tx, err := manager.BuildFlashloanTransaction(context.Background(), opp, swapCalldata)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, tx)
|
|
assert.Equal(t, FlashloanProviderAaveV3, tx.Provider)
|
|
assert.NotEmpty(t, tx.To)
|
|
assert.NotEmpty(t, tx.Data)
|
|
assert.NotNil(t, tx.Fee)
|
|
assert.True(t, tx.Fee.Cmp(big.NewInt(0)) > 0) // Fee should be > 0
|
|
}
|
|
|
|
func TestFlashloanManager_BuildFlashloanTransaction_UniswapV3(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
config := DefaultFlashloanConfig()
|
|
config.ExecutorContract = common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
config.PreferredProviders = []FlashloanProvider{FlashloanProviderUniswapV3}
|
|
|
|
manager := NewFlashloanManager(config, logger)
|
|
|
|
opp := &arbitrage.Opportunity{
|
|
InputToken: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
InputAmount: big.NewInt(1e18),
|
|
Path: []arbitrage.SwapStep{
|
|
{
|
|
TokenIn: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
TokenOut: common.HexToAddress("0xFF970a61A04b1cA14834A43f5dE4533eBDDB5CC8"),
|
|
PoolAddress: common.HexToAddress("0x0000000000000000000000000000000000000002"),
|
|
},
|
|
},
|
|
}
|
|
|
|
swapCalldata := []byte{0x01, 0x02, 0x03, 0x04}
|
|
|
|
tx, err := manager.BuildFlashloanTransaction(context.Background(), opp, swapCalldata)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, tx)
|
|
assert.Equal(t, FlashloanProviderUniswapV3, tx.Provider)
|
|
assert.NotEmpty(t, tx.To)
|
|
assert.NotEmpty(t, tx.Data)
|
|
assert.Equal(t, big.NewInt(0), tx.Fee) // UniswapV3 has no separate fee
|
|
}
|
|
|
|
func TestFlashloanManager_BuildFlashloanTransaction_UniswapV2(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
config := DefaultFlashloanConfig()
|
|
config.ExecutorContract = common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
config.PreferredProviders = []FlashloanProvider{FlashloanProviderUniswapV2}
|
|
|
|
manager := NewFlashloanManager(config, logger)
|
|
|
|
opp := &arbitrage.Opportunity{
|
|
InputToken: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
InputAmount: big.NewInt(1e18),
|
|
Path: []arbitrage.SwapStep{
|
|
{
|
|
TokenIn: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
TokenOut: common.HexToAddress("0xFF970a61A04b1cA14834A43f5dE4533eBDDB5CC8"),
|
|
PoolAddress: common.HexToAddress("0x0000000000000000000000000000000000000002"),
|
|
},
|
|
},
|
|
}
|
|
|
|
swapCalldata := []byte{0x01, 0x02, 0x03, 0x04}
|
|
|
|
tx, err := manager.BuildFlashloanTransaction(context.Background(), opp, swapCalldata)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, tx)
|
|
assert.Equal(t, FlashloanProviderUniswapV2, tx.Provider)
|
|
assert.NotEmpty(t, tx.To)
|
|
assert.NotEmpty(t, tx.Data)
|
|
assert.True(t, tx.Fee.Cmp(big.NewInt(0)) > 0) // Fee should be > 0
|
|
}
|
|
|
|
func TestFlashloanManager_selectProvider_NoProviders(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
config := &FlashloanConfig{
|
|
PreferredProviders: []FlashloanProvider{},
|
|
}
|
|
|
|
manager := NewFlashloanManager(config, logger)
|
|
|
|
token := common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1")
|
|
amount := big.NewInt(1e18)
|
|
|
|
_, err := manager.selectProvider(context.Background(), token, amount)
|
|
|
|
assert.Error(t, err)
|
|
assert.Contains(t, err.Error(), "no flashloan providers configured")
|
|
}
|
|
|
|
func TestFlashloanManager_calculateFee(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
manager := NewFlashloanManager(nil, logger)
|
|
|
|
tests := []struct {
|
|
name string
|
|
amount *big.Int
|
|
feeBPS uint16
|
|
expectedFee *big.Int
|
|
}{
|
|
{
|
|
name: "Aave V3 fee (9 bps)",
|
|
amount: big.NewInt(1e18),
|
|
feeBPS: 9,
|
|
expectedFee: big.NewInt(9e14), // 0.0009 * 1e18
|
|
},
|
|
{
|
|
name: "Uniswap V2 fee (30 bps)",
|
|
amount: big.NewInt(1e18),
|
|
feeBPS: 30,
|
|
expectedFee: big.NewInt(3e15), // 0.003 * 1e18
|
|
},
|
|
{
|
|
name: "Zero fee",
|
|
amount: big.NewInt(1e18),
|
|
feeBPS: 0,
|
|
expectedFee: big.NewInt(0),
|
|
},
|
|
{
|
|
name: "Small amount",
|
|
amount: big.NewInt(1000),
|
|
feeBPS: 9,
|
|
expectedFee: big.NewInt(0), // Rounds down to 0
|
|
},
|
|
{
|
|
name: "Large amount",
|
|
amount: big.NewInt(1000e18),
|
|
feeBPS: 9,
|
|
expectedFee: big.NewInt(9e20), // 0.0009 * 1000e18
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
fee := manager.calculateFee(tt.amount, tt.feeBPS)
|
|
assert.Equal(t, tt.expectedFee, fee)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestFlashloanManager_CalculateTotalCost(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
manager := NewFlashloanManager(nil, logger)
|
|
|
|
tests := []struct {
|
|
name string
|
|
amount *big.Int
|
|
feeBPS uint16
|
|
expectedTotal *big.Int
|
|
}{
|
|
{
|
|
name: "Aave V3 cost",
|
|
amount: big.NewInt(1e18),
|
|
feeBPS: 9,
|
|
expectedTotal: big.NewInt(1.0009e18),
|
|
},
|
|
{
|
|
name: "Uniswap V2 cost",
|
|
amount: big.NewInt(1e18),
|
|
feeBPS: 30,
|
|
expectedTotal: big.NewInt(1.003e18),
|
|
},
|
|
{
|
|
name: "Zero fee cost",
|
|
amount: big.NewInt(1e18),
|
|
feeBPS: 0,
|
|
expectedTotal: big.NewInt(1e18),
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
total := manager.CalculateTotalCost(tt.amount, tt.feeBPS)
|
|
assert.Equal(t, tt.expectedTotal, total)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAaveV3FlashloanEncoder_EncodeFlashloan(t *testing.T) {
|
|
encoder := NewAaveV3FlashloanEncoder()
|
|
|
|
assets := []common.Address{
|
|
common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
}
|
|
amounts := []*big.Int{
|
|
big.NewInt(1e18),
|
|
}
|
|
receiverAddress := common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
params := []byte{0x01, 0x02, 0x03, 0x04}
|
|
|
|
to, data, err := encoder.EncodeFlashloan(assets, amounts, receiverAddress, params)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, AaveV3PoolAddress, to)
|
|
assert.NotEmpty(t, data)
|
|
|
|
// Check method ID
|
|
// flashLoan(address,address[],uint256[],uint256[],address,bytes,uint16)
|
|
assert.GreaterOrEqual(t, len(data), 4)
|
|
}
|
|
|
|
func TestAaveV3FlashloanEncoder_EncodeFlashloan_MultipleAssets(t *testing.T) {
|
|
encoder := NewAaveV3FlashloanEncoder()
|
|
|
|
assets := []common.Address{
|
|
common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
common.HexToAddress("0xFF970a61A04b1cA14834A43f5dE4533eBDDB5CC8"),
|
|
}
|
|
amounts := []*big.Int{
|
|
big.NewInt(1e18),
|
|
big.NewInt(1500e6),
|
|
}
|
|
receiverAddress := common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
params := []byte{0x01, 0x02, 0x03, 0x04}
|
|
|
|
to, data, err := encoder.EncodeFlashloan(assets, amounts, receiverAddress, params)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, AaveV3PoolAddress, to)
|
|
assert.NotEmpty(t, data)
|
|
}
|
|
|
|
func TestAaveV3FlashloanEncoder_EncodeFlashloan_EmptyParams(t *testing.T) {
|
|
encoder := NewAaveV3FlashloanEncoder()
|
|
|
|
assets := []common.Address{
|
|
common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
}
|
|
amounts := []*big.Int{
|
|
big.NewInt(1e18),
|
|
}
|
|
receiverAddress := common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
params := []byte{}
|
|
|
|
to, data, err := encoder.EncodeFlashloan(assets, amounts, receiverAddress, params)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, to)
|
|
assert.NotEmpty(t, data)
|
|
}
|
|
|
|
func TestUniswapV3FlashloanEncoder_EncodeFlash(t *testing.T) {
|
|
encoder := NewUniswapV3FlashloanEncoder()
|
|
|
|
token := common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1")
|
|
amount := big.NewInt(1e18)
|
|
poolAddress := common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
recipient := common.HexToAddress("0x0000000000000000000000000000000000000002")
|
|
data := []byte{0x01, 0x02, 0x03, 0x04}
|
|
|
|
to, calldata, err := encoder.EncodeFlash(token, amount, poolAddress, recipient, data)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, poolAddress, to)
|
|
assert.NotEmpty(t, calldata)
|
|
|
|
// Check method ID
|
|
// flash(address,uint256,uint256,bytes)
|
|
assert.GreaterOrEqual(t, len(calldata), 4)
|
|
}
|
|
|
|
func TestUniswapV3FlashloanEncoder_EncodeFlash_EmptyData(t *testing.T) {
|
|
encoder := NewUniswapV3FlashloanEncoder()
|
|
|
|
token := common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1")
|
|
amount := big.NewInt(1e18)
|
|
poolAddress := common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
recipient := common.HexToAddress("0x0000000000000000000000000000000000000002")
|
|
data := []byte{}
|
|
|
|
to, calldata, err := encoder.EncodeFlash(token, amount, poolAddress, recipient, data)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, to)
|
|
assert.NotEmpty(t, calldata)
|
|
}
|
|
|
|
func TestUniswapV2FlashloanEncoder_EncodeFlash(t *testing.T) {
|
|
encoder := NewUniswapV2FlashloanEncoder()
|
|
|
|
token := common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1")
|
|
amount := big.NewInt(1e18)
|
|
poolAddress := common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
recipient := common.HexToAddress("0x0000000000000000000000000000000000000002")
|
|
data := []byte{0x01, 0x02, 0x03, 0x04}
|
|
|
|
to, calldata, err := encoder.EncodeFlash(token, amount, poolAddress, recipient, data)
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, poolAddress, to)
|
|
assert.NotEmpty(t, calldata)
|
|
|
|
// Check method ID
|
|
// swap(uint256,uint256,address,bytes)
|
|
assert.GreaterOrEqual(t, len(calldata), 4)
|
|
}
|
|
|
|
func TestUniswapV2FlashloanEncoder_EncodeFlash_EmptyData(t *testing.T) {
|
|
encoder := NewUniswapV2FlashloanEncoder()
|
|
|
|
token := common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1")
|
|
amount := big.NewInt(1e18)
|
|
poolAddress := common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
recipient := common.HexToAddress("0x0000000000000000000000000000000000000002")
|
|
data := []byte{}
|
|
|
|
to, calldata, err := encoder.EncodeFlash(token, amount, poolAddress, recipient, data)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotEmpty(t, to)
|
|
assert.NotEmpty(t, calldata)
|
|
}
|
|
|
|
func TestFlashloanManager_ZeroAmount(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
config := DefaultFlashloanConfig()
|
|
config.ExecutorContract = common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
|
|
manager := NewFlashloanManager(config, logger)
|
|
|
|
opp := &arbitrage.Opportunity{
|
|
InputToken: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
InputAmount: big.NewInt(0),
|
|
Path: []arbitrage.SwapStep{
|
|
{
|
|
TokenIn: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
TokenOut: common.HexToAddress("0xFF970a61A04b1cA14834A43f5dE4533eBDDB5CC8"),
|
|
PoolAddress: common.HexToAddress("0x0000000000000000000000000000000000000002"),
|
|
},
|
|
},
|
|
}
|
|
|
|
swapCalldata := []byte{0x01, 0x02, 0x03, 0x04}
|
|
|
|
tx, err := manager.BuildFlashloanTransaction(context.Background(), opp, swapCalldata)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, tx)
|
|
assert.Equal(t, big.NewInt(0), tx.Fee) // Fee should be 0 for 0 amount
|
|
}
|
|
|
|
func TestFlashloanManager_LargeAmount(t *testing.T) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
config := DefaultFlashloanConfig()
|
|
config.ExecutorContract = common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
|
|
manager := NewFlashloanManager(config, logger)
|
|
|
|
// 1000 ETH
|
|
largeAmount := new(big.Int).Mul(big.NewInt(1000), big.NewInt(1e18))
|
|
|
|
opp := &arbitrage.Opportunity{
|
|
InputToken: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
InputAmount: largeAmount,
|
|
Path: []arbitrage.SwapStep{
|
|
{
|
|
TokenIn: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
TokenOut: common.HexToAddress("0xFF970a61A04b1cA14834A43f5dE4533eBDDB5CC8"),
|
|
PoolAddress: common.HexToAddress("0x0000000000000000000000000000000000000002"),
|
|
},
|
|
},
|
|
}
|
|
|
|
swapCalldata := []byte{0x01, 0x02, 0x03, 0x04}
|
|
|
|
tx, err := manager.BuildFlashloanTransaction(context.Background(), opp, swapCalldata)
|
|
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, tx)
|
|
assert.True(t, tx.Fee.Cmp(big.NewInt(0)) > 0)
|
|
|
|
// Verify fee is reasonable (0.09% of 1000 ETH = 0.9 ETH)
|
|
expectedFee := new(big.Int).Mul(big.NewInt(9e17), big.NewInt(1)) // 0.9 ETH
|
|
assert.Equal(t, expectedFee, tx.Fee)
|
|
}
|
|
|
|
// Benchmark tests
|
|
func BenchmarkFlashloanManager_BuildFlashloanTransaction(b *testing.B) {
|
|
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
|
config := DefaultFlashloanConfig()
|
|
config.ExecutorContract = common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
|
|
manager := NewFlashloanManager(config, logger)
|
|
|
|
opp := &arbitrage.Opportunity{
|
|
InputToken: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
InputAmount: big.NewInt(1e18),
|
|
Path: []arbitrage.SwapStep{
|
|
{
|
|
TokenIn: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
TokenOut: common.HexToAddress("0xFF970a61A04b1cA14834A43f5dE4533eBDDB5CC8"),
|
|
PoolAddress: common.HexToAddress("0x0000000000000000000000000000000000000002"),
|
|
},
|
|
},
|
|
}
|
|
|
|
swapCalldata := []byte{0x01, 0x02, 0x03, 0x04}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, _ = manager.BuildFlashloanTransaction(context.Background(), opp, swapCalldata)
|
|
}
|
|
}
|
|
|
|
func BenchmarkAaveV3FlashloanEncoder_EncodeFlashloan(b *testing.B) {
|
|
encoder := NewAaveV3FlashloanEncoder()
|
|
|
|
assets := []common.Address{
|
|
common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
|
|
}
|
|
amounts := []*big.Int{
|
|
big.NewInt(1e18),
|
|
}
|
|
receiverAddress := common.HexToAddress("0x0000000000000000000000000000000000000001")
|
|
params := []byte{0x01, 0x02, 0x03, 0x04}
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, _, _ = encoder.EncodeFlashloan(assets, amounts, receiverAddress, params)
|
|
}
|
|
}
|