Skip to content

Commit

Permalink
USDT compatibility (#484)
Browse files Browse the repository at this point in the history
  • Loading branch information
dimalinux authored Jun 17, 2023
1 parent 9e3ef7b commit 8941163
Show file tree
Hide file tree
Showing 38 changed files with 1,158 additions and 424 deletions.
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ lint-shell:

.PHONY: lint-solidity
lint-solidity:
"$$(npm config get prefix)/bin/solhint" $$(find ethereum -name '*.sol')
"$$(npm config get prefix)/bin/solhint" $$(find ethereum -name '*.sol' -not -path '**/@openzeppelin/**')

.PHONY: lint
lint: lint-go lint-shell lint-solidity
Expand All @@ -30,7 +30,8 @@ format-shell:

.PHONY: format-solidity
format-solidity:
"$$(npm config get prefix)/bin/prettier" --print-width 100 --write $$(find ethereum -name '*.sol')
"$$(npm config get prefix)/bin/prettier" --print-width 100 --write \
$$(find ethereum -name '*.sol' -not -path '**/@openzeppelin/**')

.PHONY: format
format: format-go format-shell format-solidity
Expand Down
4 changes: 2 additions & 2 deletions cmd/swapcli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -1139,8 +1139,8 @@ func runGetContractSwapInfo(ctx *cli.Context) error {
fmt.Printf("Swap struct as stored in the contract:\n")
fmt.Printf("\tOwner: %s\n", resp.Swap.Owner)
fmt.Printf("\tClaimer: %s\n", resp.Swap.Claimer)
fmt.Printf("\tPubKeyClaim: %x\n", resp.Swap.PubKeyClaim)
fmt.Printf("\tPubKeyRefund: %x\n", resp.Swap.PubKeyRefund)
fmt.Printf("\tClaimCommitment: %x\n", resp.Swap.ClaimCommitment)
fmt.Printf("\tRefundCommitment: %x\n", resp.Swap.RefundCommitment)
fmt.Printf("\tTimeout1: %s\n", resp.Swap.Timeout1)
fmt.Printf("\tTimeout2: %s\n", resp.Swap.Timeout2)
fmt.Printf("\tAsset: %s\n", resp.Swap.Asset)
Expand Down
4 changes: 2 additions & 2 deletions common/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func MainnetConfig() *Config {
Port: DefaultMoneroDaemonMainnetPort,
},
},
SwapCreatorAddr: ethcommon.HexToAddress("0xa55aa5557ec22e85804729bc6935029bb84cf16a"),
SwapCreatorAddr: ethcommon.HexToAddress("0x377ed3a60007048DF00135637521170628De89E5"),
Bootnodes: []string{
"/ip4/67.205.131.11/tcp/9909/p2p/12D3KooWGpCLC4y42rf6aR3cguVFJAruzFXT6mUEyp7C32jTsyJd",
"/ip4/143.198.123.27/tcp/9909/p2p/12D3KooWDCE2ukB1Sw88hmLFk5BZRRViyYLeuAKPuu59nYyFWAec",
Expand Down Expand Up @@ -99,7 +99,7 @@ func StagenetConfig() *Config {
Port: 38081,
},
},
SwapCreatorAddr: ethcommon.HexToAddress("0xbf2B7a6dCE5598Cf002B3507a8D62cf2C35cE5c6"),
SwapCreatorAddr: ethcommon.HexToAddress("0x377ed3a60007048DF00135637521170628De89E5"),
Bootnodes: []string{
"/ip4/134.122.115.208/tcp/9900/p2p/12D3KooWHZ2G9XscjDGvG7p8uPBoYerDc9kWYnc8oJFGfFxS6gfq",
"/ip4/143.198.123.27/tcp/9900/p2p/12D3KooWGzExs5zqebnDvqkUAKaiUuxF3DNbrfJ4prbfkxjXb366",
Expand Down
75 changes: 53 additions & 22 deletions daemon/swap_daemon_erc20_test.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package daemon

import (
"context"
"sync"
"testing"
"time"

"github.com/cockroachdb/apd/v3"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/athanorlabs/atomic-swap/coins"
"github.com/athanorlabs/atomic-swap/common/rpctypes"
"github.com/athanorlabs/atomic-swap/common/types"
contracts "github.com/athanorlabs/atomic-swap/ethereum"
"github.com/athanorlabs/atomic-swap/ethereum/extethclient"
"github.com/athanorlabs/atomic-swap/monero"
"github.com/athanorlabs/atomic-swap/rpcclient"
"github.com/athanorlabs/atomic-swap/tests"
Expand All @@ -21,26 +24,52 @@ import (
// Tests the scenario where Bob has XMR and enough ETH to pay gas fees for the token claim. He
// exchanges 2 XMR for 3 of Alice's ERC20 tokens.
func TestRunSwapDaemon_ExchangesXMRForERC20Tokens(t *testing.T) {
minXMR := coins.StrToDecimal("1")
maxXMR := coins.StrToDecimal("2")
exRate := coins.StrToExchangeRate("1.5")
fundingEC := extethclient.CreateTestClient(t, tests.GetTakerTestKey(t))
tokenAsset := getMockTetherAsset(t, fundingEC)
tokenAddr := tokenAsset.Address()
token, err := fundingEC.ERC20Info(context.Background(), tokenAddr)
require.NoError(t, err)

minXMR := coins.StrToDecimal("0.1")
maxXMR := coins.StrToDecimal("0.25")
exRate := coins.StrToExchangeRate("140")
providesAmt := coins.NewEthAssetAmount(coins.StrToDecimal("33.999994"), token) // 33.999994 USDT / 140 = 0.2428571 XMR
gasMoney := coins.EtherToWei(coins.StrToDecimal("0.1"))

bobConf := CreateTestConf(t, tests.GetMakerTestKey(t))
bobEthKey, err := crypto.GenerateKey()
require.NoError(t, err)
bobConf := CreateTestConf(t, bobEthKey)
monero.MineMinXMRBalance(t, bobConf.MoneroClient, coins.MoneroToPiconero(maxXMR))

aliceConf := CreateTestConf(t, tests.GetTakerTestKey(t))
// Ensure that Alice has no tokens and definitely no pre-approval to spend
// any of those tokens by giving her a brand-new ETH key.
aliceEthKey, err := crypto.GenerateKey()
require.NoError(t, err)
aliceConf := CreateTestConf(t, aliceEthKey)
timeout := 7 * time.Minute

tokenAsset := getMockTetherAsset(t, aliceConf.EthereumClient)
// Fund Alice and Bob with a little ether for gas. Bob needs gas to claim,
// as ERC20 token swaps cannot use a relayer.
_, err = fundingEC.Transfer(context.Background(), aliceConf.EthereumClient.Address(), gasMoney, nil)
require.NoError(t, err)
_, err = fundingEC.Transfer(context.Background(), bobConf.EthereumClient.Address(), gasMoney, nil)
require.NoError(t, err)

// Fund Alice with the exact amount of token that she'll provide in the swap
// with Bob. After the swap is over, her token balance should be exactly
// zero.
erc20Iface, err := contracts.NewIERC20(tokenAddr, fundingEC.Raw())
require.NoError(t, err)
txOpts, err := fundingEC.TxOpts(context.Background())
require.NoError(t, err)
_, err = erc20Iface.Transfer(txOpts, aliceConf.EthereumClient.Address(), providesAmt.BigInt())
require.NoError(t, err)

timeout := 7 * time.Minute
ctx, _ := LaunchDaemons(t, timeout, aliceConf, bobConf)

bc := rpcclient.NewClient(ctx, bobConf.RPCPort)
ac := rpcclient.NewClient(ctx, aliceConf.RPCPort)

bobStartTokenBal, err := bobConf.EthereumClient.ERC20Balance(ctx, tokenAsset.Address())
require.NoError(t, err)

_, bobStatusCh, err := bc.MakeOfferAndSubscribe(minXMR, maxXMR, exRate, tokenAsset, false)
require.NoError(t, err)
time.Sleep(250 * time.Millisecond) // offer propagation time
Expand All @@ -52,12 +81,9 @@ func TestRunSwapDaemon_ExchangesXMRForERC20Tokens(t *testing.T) {
require.Len(t, peersWithOffers[0].Offers, 1)
peerID := peersWithOffers[0].PeerID
offer := peersWithOffers[0].Offers[0]
tokenInfo, err := ac.TokenInfo(offer.EthAsset.Address())
require.NoError(t, err)
providesAmt, err := exRate.ToERC20Amount(offer.MaxAmount, tokenInfo)
require.NoError(t, err)
require.Equal(t, tokenAddr.String(), offer.EthAsset.Address().String())

aliceStatusCh, err := ac.TakeOfferAndSubscribe(peerID, offer.ID, providesAmt)
aliceStatusCh, err := ac.TakeOfferAndSubscribe(peerID, offer.ID, providesAmt.AsStd())
require.NoError(t, err)

var statusWG sync.WaitGroup
Expand Down Expand Up @@ -105,14 +131,19 @@ func TestRunSwapDaemon_ExchangesXMRForERC20Tokens(t *testing.T) {
}

//
// Check Bob's token balance via RPC method instead of doing it directly
// Check final token balances via RPC method instead of doing it directly on
// the eth client. Bob should have exactly the provided amount and Alice's
// token balance should now be zero.
//
endBalances, err := bc.Balances(&rpctypes.BalancesRequest{TokenAddrs: []ethcommon.Address{tokenAsset.Address()}})
balReq := &rpctypes.BalancesRequest{TokenAddrs: []ethcommon.Address{tokenAddr}}

bobBal, err := bc.Balances(balReq)
require.NoError(t, err)
require.NotEmpty(t, endBalances.TokenBalances)
require.NotEmpty(t, bobBal.TokenBalances)
require.Equal(t, providesAmt.AsStdString(), bobBal.TokenBalances[0].AsStdString())

delta := new(apd.Decimal)
_, err = coins.DecimalCtx().Sub(delta, endBalances.TokenBalances[0].Amount, bobStartTokenBal.Amount)
aliceBal, err := ac.Balances(balReq)
require.NoError(t, err)
require.Equal(t, providesAmt.Text('f'), delta.Text('f'))
require.NotEmpty(t, aliceBal.TokenBalances)
require.Equal(t, "0", aliceBal.TokenBalances[0].AsStdString())
}
40 changes: 20 additions & 20 deletions db/recovery_db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ func TestRecoveryDB_ContractSwapInfo(t *testing.T) {
StartNumber: big.NewInt(12345),
SwapID: types.Hash{1, 2, 3, 4},
Swap: &contracts.SwapCreatorSwap{
Owner: ethcommon.HexToAddress("0xda9dfa130df4de4673b89022ee50ff26f6ea73cf"),
Claimer: ethcommon.HexToAddress("0xbe0eb53f46cd790cd13851d5eff43d12404d33e8"),
PubKeyClaim: ethcommon.HexToHash("0x5ab9467e70d4e98567991f0179d1f82a3096ed7973f7aff9ea50f649cafa88b9"),
PubKeyRefund: ethcommon.HexToHash("0x4897bc3b9e02c2a8cd6353b9b29377157bf2694daaf52b59c0b42daa39877f14"),
Timeout1: big.NewInt(1672531200),
Timeout2: big.NewInt(1672545600),
Asset: types.EthAssetETH.Address(),
Value: big.NewInt(9876),
Nonce: big.NewInt(1234),
Owner: ethcommon.HexToAddress("0xda9dfa130df4de4673b89022ee50ff26f6ea73cf"),
Claimer: ethcommon.HexToAddress("0xbe0eb53f46cd790cd13851d5eff43d12404d33e8"),
ClaimCommitment: ethcommon.HexToHash("0x5ab9467e70d4e98567991f0179d1f82a3096ed7973f7aff9ea50f649cafa88b9"),
RefundCommitment: ethcommon.HexToHash("0x4897bc3b9e02c2a8cd6353b9b29377157bf2694daaf52b59c0b42daa39877f14"),
Timeout1: big.NewInt(1672531200),
Timeout2: big.NewInt(1672545600),
Asset: types.EthAssetETH.Address(),
Value: big.NewInt(9876),
Nonce: big.NewInt(1234),
},
SwapCreatorAddr: ethcommon.HexToAddress("0xd2b5d6252d0645e4cf4bb547e82a485f527befb7"),
}
Expand All @@ -57,8 +57,8 @@ func TestRecoveryDB_ContractSwapInfo(t *testing.T) {
"swap": {
"owner": "0xda9dfa130df4de4673b89022ee50ff26f6ea73cf",
"claimer": "0xbe0eb53f46cd790cd13851d5eff43d12404d33e8",
"pubKeyClaim": "0x5ab9467e70d4e98567991f0179d1f82a3096ed7973f7aff9ea50f649cafa88b9",
"pubKeyRefund": "0x4897bc3b9e02c2a8cd6353b9b29377157bf2694daaf52b59c0b42daa39877f14",
"claimCommitment": "0x5ab9467e70d4e98567991f0179d1f82a3096ed7973f7aff9ea50f649cafa88b9",
"refundCommitment": "0x4897bc3b9e02c2a8cd6353b9b29377157bf2694daaf52b59c0b42daa39877f14",
"timeout1": 1672531200,
"timeout2": 1672545600,
"asset": "0x0000000000000000000000000000000000000000",
Expand Down Expand Up @@ -150,15 +150,15 @@ func TestRecoveryDB_DeleteSwap(t *testing.T) {
StartNumber: big.NewInt(12345),
SwapID: types.Hash{1, 2, 3, 4},
Swap: &contracts.SwapCreatorSwap{
Owner: ethcommon.HexToAddress("0xda9dfa130df4de4673b89022ee50ff26f6ea73cf"),
Claimer: ethcommon.HexToAddress("0xbe0eb53f46cd790cd13851d5eff43d12404d33e8"),
PubKeyClaim: ethcommon.HexToHash("0x5ab9467e70d4e98567991f0179d1f82a3096ed7973f7aff9ea50f649cafa88b9"),
PubKeyRefund: ethcommon.HexToHash("0x4897bc3b9e02c2a8cd6353b9b29377157bf2694daaf52b59c0b42daa39877f14"),
Timeout1: big.NewInt(1672531200),
Timeout2: big.NewInt(1672545600),
Asset: types.EthAssetETH.Address(),
Value: big.NewInt(9876),
Nonce: big.NewInt(1234),
Owner: ethcommon.HexToAddress("0xda9dfa130df4de4673b89022ee50ff26f6ea73cf"),
Claimer: ethcommon.HexToAddress("0xbe0eb53f46cd790cd13851d5eff43d12404d33e8"),
ClaimCommitment: ethcommon.HexToHash("0x5ab9467e70d4e98567991f0179d1f82a3096ed7973f7aff9ea50f649cafa88b9"),
RefundCommitment: ethcommon.HexToHash("0x4897bc3b9e02c2a8cd6353b9b29377157bf2694daaf52b59c0b42daa39877f14"),
Timeout1: big.NewInt(1672531200),
Timeout2: big.NewInt(1672545600),
Asset: types.EthAssetETH.Address(),
Value: big.NewInt(9876),
Nonce: big.NewInt(1234),
},
SwapCreatorAddr: ethcommon.HexToAddress("0xd2b5d6252d0645e4cf4bb547e82a485f527befb7"),
}
Expand Down
2 changes: 1 addition & 1 deletion ethereum/block/ut_contract_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8941163

Please sign in to comment.