From 3154c74c738a36f09ec3f4b1763ca61b2fcdc926 Mon Sep 17 00:00:00 2001 From: Karl Kempe Date: Thu, 27 Jan 2022 18:28:36 +0000 Subject: [PATCH] Update contracts; fix evm approve and swap --- contracts/contracts/CrossChainSwapV2.sol | 65 +++++++++++++++--------- contracts/contracts/CrossChainSwapV3.sol | 65 +++++++++++++++--------- contracts/contracts/SwapHelper.sol | 6 +-- react/src/swapper/swapper.ts | 31 +++++------ 4 files changed, 103 insertions(+), 64 deletions(-) diff --git a/contracts/contracts/CrossChainSwapV2.sol b/contracts/contracts/CrossChainSwapV2.sol index 1d53e0c..0edd059 100644 --- a/contracts/contracts/CrossChainSwapV2.sol +++ b/contracts/contracts/CrossChainSwapV2.sol @@ -44,7 +44,8 @@ contract CrossChainSwapV2 { uint8 public immutable typeExactOut = 2; uint8 public immutable typeNativeSwap = 1; uint8 public immutable typeTokenSwap = 2; - uint16 public immutable expectedVaaLength = 262; + uint16 public immutable expectedVaaLength = 274; + uint8 public immutable terraChainId = 3; IUniswapV2Router02 public immutable swapRouter; address public immutable feeTokenAddress; address public immutable tokenBridgeAddress; @@ -385,17 +386,26 @@ contract CrossChainSwapV2 { swapParams.deadline ); - // encode payload for second swap - bytes memory payload = abi.encodePacked( - swapParams.targetAmountOutMinimum, - swapParams.targetChainRecipient, - path[2], - path[3], - swapParams.deadline, - swapParams.poolFee, - typeExactIn, - typeNativeSwap - ); + // create payload variable + bytes memory payload; + + // UST is native to Terra - no need for swap instructions + if (targetChainId == terraChainId) { + payload = abi.encodePacked( + swapParams.targetChainRecipient + ); + } else { + payload = abi.encodePacked( + swapParams.targetAmountOutMinimum, + swapParams.targetChainRecipient, + path[2], + path[3], + swapParams.deadline, + swapParams.poolFee, + typeExactIn, + typeNativeSwap + ); + } // approve token bridge to spend feeTokens (UST) TransferHelper.safeApprove( @@ -761,17 +771,26 @@ contract CrossChainSwapV2 { typeNativeSwap ); - // encode payload for second swap - bytes memory payload = abi.encodePacked( - swapParams.targetAmountOut, - swapParams.targetChainRecipient, - path[2], - path[3], - swapParams.deadline, - swapParams.poolFee, - typeExactOut, - typeNativeSwap - ); + // create payload variable + bytes memory payload; + + // UST is native to Terra - no need for swap instructions + if (targetChainId == terraChainId) { + payload = abi.encodePacked( + swapParams.targetChainRecipient + ); + } else { + payload = abi.encodePacked( + swapParams.targetAmountOut, + swapParams.targetChainRecipient, + path[2], + path[3], + swapParams.deadline, + swapParams.poolFee, + typeExactOut, + typeNativeSwap + ); + } // approve token bridge to spend feeTokens (UST) TransferHelper.safeApprove( diff --git a/contracts/contracts/CrossChainSwapV3.sol b/contracts/contracts/CrossChainSwapV3.sol index 98510aa..373e119 100644 --- a/contracts/contracts/CrossChainSwapV3.sol +++ b/contracts/contracts/CrossChainSwapV3.sol @@ -48,7 +48,8 @@ contract CrossChainSwapV3 { uint8 public immutable typeExactOut = 2; uint8 public immutable typeNativeSwap = 1; uint8 public immutable typeTokenSwap = 2; - uint16 public immutable expectedVaaLength = 262; + uint16 public immutable expectedVaaLength = 274; + uint8 public immutable terraChainId = 3; IUniswapRouter public immutable swapRouter; address public immutable feeTokenAddress; address public immutable tokenBridgeAddress; @@ -403,17 +404,26 @@ contract CrossChainSwapV3 { typeNativeSwap ); - // encode payload for second swap - bytes memory payload = abi.encodePacked( - swapParams.targetAmountOutMinimum, - swapParams.targetChainRecipient, - path[2], - path[3], - swapParams.deadline, - swapParams.poolFee, - typeExactIn, - typeNativeSwap - ); + // create payload variable + bytes memory payload; + + // UST is native to Terra - no need for swap instructions + if (targetChainId == terraChainId) { + payload = abi.encodePacked( + swapParams.targetChainRecipient + ); + } else { + payload = abi.encodePacked( + swapParams.targetAmountOutMinimum, + swapParams.targetChainRecipient, + path[2], + path[3], + swapParams.deadline, + swapParams.poolFee, + typeExactIn, + typeNativeSwap + ); + } // approve token bridge to spend feeTokens (UST) TransferHelper.safeApprove( @@ -788,17 +798,26 @@ contract CrossChainSwapV3 { typeNativeSwap ); - // encode payload for second swap - bytes memory payload = abi.encodePacked( - swapParams.targetAmountOut, - swapParams.targetChainRecipient, - path[2], - path[3], - swapParams.deadline, - swapParams.poolFee, - typeExactOut, - typeNativeSwap - ); + // create payload variable + bytes memory payload; + + // UST is native to Terra - no need for swap instructions + if (targetChainId == terraChainId) { + payload = abi.encodePacked( + swapParams.targetChainRecipient + ); + } else { + payload = abi.encodePacked( + swapParams.targetAmountOut, + swapParams.targetChainRecipient, + path[2], + path[3], + swapParams.deadline, + swapParams.poolFee, + typeExactOut, + typeNativeSwap + ); + } // approve token bridge to spend feeTokens (UST) TransferHelper.safeApprove( diff --git a/contracts/contracts/SwapHelper.sol b/contracts/contracts/SwapHelper.sol index 4b20654..c9e925c 100644 --- a/contracts/contracts/SwapHelper.sol +++ b/contracts/contracts/SwapHelper.sol @@ -18,7 +18,7 @@ library SwapHelper { uint256 amountIn; uint256 amountOutMinimum; uint256 targetAmountOutMinimum; - address targetChainRecipient; + bytes32 targetChainRecipient; uint256 deadline; uint24 poolFee; } @@ -28,7 +28,7 @@ library SwapHelper { uint256 amountOut; uint256 amountInMaximum; uint256 targetAmountOut; - address targetChainRecipient; + bytes32 targetChainRecipient; uint256 deadline; uint24 poolFee; } @@ -75,7 +75,7 @@ library SwapHelper { index += 32; decoded.estimatedAmount = encodedVm.payload.toUint256(index); - index += 32; + index += 44; decoded.recipientAddress = encodedVm.payload.toAddress(index); index += 20; diff --git a/react/src/swapper/swapper.ts b/react/src/swapper/swapper.ts index 3f1f870..6749c97 100644 --- a/react/src/swapper/swapper.ts +++ b/react/src/swapper/swapper.ts @@ -13,7 +13,6 @@ import { getSignedVAAWithRetry, } from "@certusone/wormhole-sdk"; import { grpc } from "@improbable-eng/grpc-web"; -import { UniEvmToken } from "../route/uniswap-core"; import { PROTOCOL_UNISWAP_V2, // PROTOCOL_UNISWAP_V3, @@ -120,11 +119,12 @@ function makeExecutionParameters(chainId: ChainId): ExecutionParameters { async function evmApproveContractTokenSpend( provider: ethers.providers.Provider, signer: ethers.Signer, - tokenContract: ethers.Contract, + tokenAddress: string, //ethers.Contract, swapContractAddress: string, amount: ethers.BigNumber ): Promise { // build transaction for token spending + const tokenContract = makeEvmToken(provider, tokenAddress).getContract(); const unsignedTx = await tokenContract.populateTransaction.approve( swapContractAddress, amount @@ -189,7 +189,7 @@ function addressToBytes32( async function evmApproveAndSwapExactIn( srcProvider: ethers.providers.Provider, srcWallet: ethers.Signer, - srcTokenIn: UniEvmToken, + tokenInAddress: string, quoteParams: ExactInCrossParameters, srcExecutionParams: ExecutionParameters, dstExecutionParams: ExecutionParameters, @@ -254,7 +254,7 @@ async function evmApproveAndSwapExactIn( await evmApproveContractTokenSpend( srcProvider, srcWallet, - srcTokenIn.getContract(), + tokenInAddress, swapContract.address, amountIn ); @@ -276,7 +276,7 @@ async function evmApproveAndSwapExactIn( async function evmApproveAndSwapExactOut( srcProvider: ethers.providers.Provider, srcWallet: ethers.Signer, - srcTokenIn: UniEvmToken, + tokenInAddress: string, quoteParams: ExactOutCrossParameters, srcExecutionParams: ExecutionParameters, dstExecutionParams: ExecutionParameters, @@ -341,7 +341,7 @@ async function evmApproveAndSwapExactOut( await evmApproveContractTokenSpend( srcProvider, srcWallet, - srcTokenIn.getContract(), + tokenInAddress, swapContract.address, maxAmountIn ); @@ -412,13 +412,6 @@ async function swapExactOutFromVaa( } } -interface CrossChainSwapTokens { - srcIn: UniEvmToken; - srcOut: UniEvmToken; - dstIn: UniEvmToken; - dstOut: UniEvmToken; -} - interface VaaSearchParams { sequence: string; emitterAddress: string; @@ -583,13 +576,21 @@ export class UniswapToUniswapExecutor { return this.quoter.getDstEvmProvider(); } + getTokenInAddress(): string { + return this.quoter.tokenInAddress; + } + + getTokenOutAddress(): string { + return this.quoter.tokenOutAddress; + } + async evmApproveAndSwapExactIn( wallet: ethers.Signer ): Promise { return evmApproveAndSwapExactIn( this.getSrcEvmProvider(), wallet, - this.tokens.srcIn, + this.getTokenInAddress(), this.cachedExactInParams, this.srcExecutionParams, this.dstExecutionParams, @@ -603,7 +604,7 @@ export class UniswapToUniswapExecutor { return evmApproveAndSwapExactOut( this.getSrcEvmProvider(), wallet, - this.tokens.srcIn, + this.getTokenInAddress(), this.cachedExactOutParams, this.srcExecutionParams, this.dstExecutionParams,