import "module-alias/register" ; import { BigNumber } from "ethers" ; import { Address , Bytes } from "@utils/types" ; import { Account } from "@utils/test/types" ; import { EMPTY_BYTES , ZERO } from "@utils/constants" ; import { SynthetixExchangeAdapter , SynthMock , SynthetixExchangerMock , } from "@utils/contracts" ; import DeployHelper from "@utils/deploys" ; import { ether , } from "@utils/index" ; import { cacheBeforeEach , getAccounts , getSystemFixture , getWaffleExpect , } from "@utils/test/index" ; import { SystemFixture } from "@utils/fixtures" ; const expect = getWaffleExpect ( ) ; describe ( "SynthetixExchangeAdapter" , ( ) => { let owner ; let mockSetToken ; let deployer ; let setup ; let rates ; let currencyKeys ; let sUsd ; let sEth ; let sBtc ; let exchanger ; let synthetixExchangeAdapter ; cacheBeforeEach ( async ( ) => { [ owner , mockSetToken , ] = await getAccounts ( ) ; deployer = new DeployHelper ( owner . wallet ) ; setup = getSystemFixture ( owner . address ) ; await setup . initialize ( ) ; rates = { usd : { eth : ether ( 0.1 ) , btc : ether ( 0.01 ) , } , eth : { usd : ether ( 10 ) , } , btc : { usd : ether ( 100 ) , } , } ; currencyKeys = { sUsd : "0x1111111100000000000000000000000000000000000000000000000000000000" , sEth : "0x2222222200000000000000000000000000000000000000000000000000000000" , sBtc : "0x3333333300000000000000000000000000000000000000000000000000000000" , invalid : "0x4444444400000000000000000000000000000000000000000000000000000000" , } ; sUsd = await deployer . mocks . deploySynthMock ( owner . address , currencyKeys . sUsd ) ; sEth = await deployer . mocks . deploySynthMock ( owner . address , currencyKeys . sEth ) ; sBtc = await deployer . mocks . deploySynthMock ( owner . address , currencyKeys . sBtc ) ; exchanger = await deployer . mocks . deploySynthetixExchangerMock ( sUsd . address , sEth . address , sBtc . address , currencyKeys , rates ) ; synthetixExchangeAdapter = await deployer . adapters . deploySynthetixExchangeAdapter ( exchanger . address ) ; } ) ; describe ( "constructor" , async ( ) => { let subjectExchanger ; beforeEach ( async ( ) => { subjectExchanger = exchanger . address ; } ) ; async function subject ( ) { return await deployer . adapters . deploySynthetixExchangeAdapter ( subjectExchanger ) ; } it ( "should have the correct SynthetixExchanger address" , async ( ) => { const adapter = await subject ( ) ; const actualExchangerAddress = await adapter . synthetixExchangerAddress ( ) ; expect ( actualExchangerAddress ) . to . eq ( exchanger . address ) ; } ) ; } ) ; describe ( "getAmountReceivedForExchange" , async ( ) => { const btcQuantity = 1 ; let subjectSourceToken ; let subjectDestinationToken ; let subjectSourceQuantity ; beforeEach ( async ( ) => { subjectSourceToken = sBtc . address ; subjectDestinationToken = sEth . address ; subjectSourceQuantity = ether ( btcQuantity ) ; } ) ; async function subject ( ) { return await synthetixExchangeAdapter . getAmountReceivedForExchange ( subjectSourceToken , subjectDestinationToken , subjectSourceQuantity ) ; } it ( "should return the correct amount received" , async ( ) => { const actualAmountReceived = await subject ( ) ; const conversionRate = rates . btc . usd . div ( rates . eth . usd ) ; const expectedAmountReceived = ether ( conversionRate . mul ( btcQuantity ) ) ; expect ( actualAmountReceived ) . to . eq ( expectedAmountReceived ) ; } ) ; describe ( "when source token does not implement currencyKey" , ( ) => { beforeEach ( async ( ) => { const standardToken = await deployer . mocks . deployTokenMock ( owner . address ) ; subjectSourceToken = standardToken . address ; } ) ; it ( "it should revert" , async ( ) => { await expect ( subject ( ) ) . to . be . revertedWith ( "Invalid Synth token address" ) ; } ) ; } ) ; describe ( "when destination token does not implement currencyKey" , ( ) => { beforeEach ( async ( ) => { const standardToken = await deployer . mocks . deployTokenMock ( owner . address ) ; subjectDestinationToken = standardToken . address ; } ) ; it ( "it should revert" , async ( ) => { await expect ( subject ( ) ) . to . be . revertedWith ( "Invalid Synth token address" ) ; } ) ; } ) ; } ) ; describe ( "getSpender" , async ( ) => { async function subject ( ) { return await synthetixExchangeAdapter . getSpender ( ) ; } it ( "should return the correct spender address" , async ( ) => { const spender = await subject ( ) ; expect ( spender ) . to . eq ( exchanger . address ) ; } ) ; } ) ; describe ( "getTradeCalldata" , async ( ) => { let sourceAddress ; let destinationAddress ; let sourceQuantity ; let sourceCurrencyKey ; let destinationCurrencyKey ; let subjectMockSetToken ; let subjectSourceToken ; let subjectDestinationToken ; let subjectSourceQuantity ; let subjectMinDestinationQuantity ; let subjectData ; beforeEach ( async ( ) => { sourceAddress = sEth . address , destinationAddress = sBtc . address , sourceCurrencyKey = currencyKeys . sEth ; destinationCurrencyKey = currencyKeys . sBtc ; sourceQuantity = ether ( 10 ) ; subjectSourceToken = sourceAddress ; subjectDestinationToken = destinationAddress ; subjectMockSetToken = mockSetToken . address ; subjectSourceQuantity = sourceQuantity ; subjectMinDestinationQuantity = ZERO ; subjectData = EMPTY_BYTES ; } ) ; async function subject ( ) { return await synthetixExchangeAdapter . getTradeCalldata ( subjectSourceToken , subjectDestinationToken , subjectMockSetToken , subjectSourceQuantity , subjectMinDestinationQuantity , subjectData ) ; } it ( "should return the correct trade calldata" , async ( ) => { const calldata = await subject ( ) ; const expectedCallData = exchanger . interface . encodeFunctionData ( "exchange" , [ mockSetToken . address , sourceCurrencyKey , sourceQuantity , destinationCurrencyKey , mockSetToken . address , ] ) ; expect ( JSON . stringify ( calldata ) ) . to . eq ( JSON . stringify ( [ exchanger . address , ZERO , expectedCallData ] ) ) ; } ) ; describe ( "when source token and destination token addresses are the same" , ( ) => { beforeEach ( ( ) => { subjectSourceToken = sEth . address ; subjectDestinationToken = sEth . address ; } ) ; it ( "it should revert" , async ( ) => { await expect ( subject ( ) ) . to . be . revertedWith ( "Source token cannot be same as destination token" ) ; } ) ; } ) ; describe ( "when source token does not implement currencyKey" , ( ) => { beforeEach ( async ( ) => { const standardToken = await deployer . mocks . deployTokenMock ( owner . address ) ; subjectSourceToken = standardToken . address ; } ) ; it ( "it should revert" , async ( ) => { await expect ( subject ( ) ) . to . be . revertedWith ( "Invalid Synth token address" ) ; } ) ; } ) ; describe ( "when destination token does not implement currencyKey" , ( ) => { beforeEach ( async ( ) => { const standardToken = await deployer . mocks . deployTokenMock ( owner . address ) ; subjectDestinationToken = standardToken . address ; } ) ; it ( "it should revert" , async ( ) => { await expect ( subject ( ) ) . to . be . revertedWith ( "Invalid Synth token address" ) ; } ) ; } ) ; } ) ; } ) ;