diff --git a/README.md b/README.md index 21f891a..6e8ea59 100644 --- a/README.md +++ b/README.md @@ -62,9 +62,20 @@ anothersubnet = "http://localhost:9650/ext/bc/BASE58_BLOCKCHAIN_ID/rpc" ``` ## Code Examples -- [0-send-receive](src/0-send-receive/_INSTRUCTIONS.md) -- [1-send-roundtrip](src/2-invoking-functions/_INSTRUCTIONS.md) -- [2-invoking-functions](src/0-send-receive/_INSTRUCTIONS.md) -- [3-registry](src/3-registry/_INSTRUCTIONS.md) -- [4-creating-contracts](src/4-creating-contracts/_INSTRUCTIONS.md) -- [x-erc721-bridge](src/x-erc721-bridge/Readme.md) + +### Interchain Messaging +- [0a-send-receive](src/interchain-messaging/0a-send-receive/_INSTRUCTIONS.md) +- [0b-send-receive](src/interchain-messaging/0b-send-receive/_INSTRUCTIONS.md) +- [1-send-roundtrip](src/interchain-messaging/1-send-roundtrip/_INSTRUCTIONS.md) +- [2a-invoking-functions](src/interchain-messaging/2a-invoking-functions/_INSTRUCTIONS.md) +- [2b-invoking-functions](src/interchain-messaging/2b-invoking-functions/_INSTRUCTIONS.md) +- [2c-invoking-functions](src/interchain-messaging/2c-invoking-functions/_INSTRUCTIONS.md) +- [3-registry](src/interchain-messaging/3-registry/_INSTRUCTIONS.md) +- [4-incentivize-relayer](src/interchain-messaging/4-incentivize-relayer/_INSTRUCTIONS.md) + +### Interchain Token Transfer +- [0-native-to-erc20-interchain-token-transfer](src/interchain-token-transfer/0-native-to-erc20-interchain-token-transfer/_INSTRUCTIONS.md) +- [1-erc20-to-native-interchain-token-transfer](src/interchain-token-transfer/1-erc20-to-native-interchain-token-transfer/_INSTRUCTIONS.md) +- [2-native-to-native-interchain-token-transfer](src/interchain-token-transfer/2-native-to-native-interchain-token-transfer/_INSTRUCTIONS.md) +- [3-erc20-to-erc20-interchain-token-transfer](src/interchain-token-transfer/3-erc20-to-erc20-interchain-token-transfer/_INSTRUCTIONS.md) +- [4-send-and-call](src/interchain-token-transfer/4-send-and-call/_INSTRUCTIONS.md) diff --git a/src/4-creating-contracts/BridgeActions.sol b/src/archieve/0-creating-contracts/BridgeActions.sol similarity index 100% rename from src/4-creating-contracts/BridgeActions.sol rename to src/archieve/0-creating-contracts/BridgeActions.sol diff --git a/src/4-creating-contracts/BridgeReceiverOnSubnet.sol b/src/archieve/0-creating-contracts/BridgeReceiverOnSubnet.sol similarity index 100% rename from src/4-creating-contracts/BridgeReceiverOnSubnet.sol rename to src/archieve/0-creating-contracts/BridgeReceiverOnSubnet.sol diff --git a/src/4-creating-contracts/BridgeSenderOnCChain.sol b/src/archieve/0-creating-contracts/BridgeSenderOnCChain.sol similarity index 100% rename from src/4-creating-contracts/BridgeSenderOnCChain.sol rename to src/archieve/0-creating-contracts/BridgeSenderOnCChain.sol diff --git a/src/4-creating-contracts/MyERC20Token.sol b/src/archieve/0-creating-contracts/MyERC20Token.sol similarity index 100% rename from src/4-creating-contracts/MyERC20Token.sol rename to src/archieve/0-creating-contracts/MyERC20Token.sol diff --git a/src/3-registry/_INSTRUCTIONS.md b/src/archieve/0-creating-contracts/_INSTRUCTIONS.md similarity index 100% rename from src/3-registry/_INSTRUCTIONS.md rename to src/archieve/0-creating-contracts/_INSTRUCTIONS.md diff --git a/src/x-erc721-bridge/BridgeNFT.sol b/src/archieve/1-erc721-bridge/BridgeNFT.sol similarity index 100% rename from src/x-erc721-bridge/BridgeNFT.sol rename to src/archieve/1-erc721-bridge/BridgeNFT.sol diff --git a/src/x-erc721-bridge/ERC721Bridge.sol b/src/archieve/1-erc721-bridge/ERC721Bridge.sol similarity index 100% rename from src/x-erc721-bridge/ERC721Bridge.sol rename to src/archieve/1-erc721-bridge/ERC721Bridge.sol diff --git a/src/x-erc721-bridge/ERC721BridgeTests.t.sol b/src/archieve/1-erc721-bridge/ERC721BridgeTests.t.sol similarity index 100% rename from src/x-erc721-bridge/ERC721BridgeTests.t.sol rename to src/archieve/1-erc721-bridge/ERC721BridgeTests.t.sol diff --git a/src/x-erc721-bridge/ExampleERC721.sol b/src/archieve/1-erc721-bridge/ExampleERC721.sol similarity index 100% rename from src/x-erc721-bridge/ExampleERC721.sol rename to src/archieve/1-erc721-bridge/ExampleERC721.sol diff --git a/src/x-erc721-bridge/IERC721Bridge.sol b/src/archieve/1-erc721-bridge/IERC721Bridge.sol similarity index 100% rename from src/x-erc721-bridge/IERC721Bridge.sol rename to src/archieve/1-erc721-bridge/IERC721Bridge.sol diff --git a/src/x-erc721-bridge/Readme.md b/src/archieve/1-erc721-bridge/Readme.md similarity index 100% rename from src/x-erc721-bridge/Readme.md rename to src/archieve/1-erc721-bridge/Readme.md diff --git a/src/0-send-receive/_INSTRUCTIONS.md b/src/interchain-messaging/0a-send-receive/_INSTRUCTIONS.md similarity index 100% rename from src/0-send-receive/_INSTRUCTIONS.md rename to src/interchain-messaging/0a-send-receive/_INSTRUCTIONS.md diff --git a/src/0-send-receive/receiverOnSubnet.sol b/src/interchain-messaging/0a-send-receive/receiverOnSubnet.sol similarity index 100% rename from src/0-send-receive/receiverOnSubnet.sol rename to src/interchain-messaging/0a-send-receive/receiverOnSubnet.sol diff --git a/src/0-send-receive/senderOnCChain.sol b/src/interchain-messaging/0a-send-receive/senderOnCChain.sol similarity index 100% rename from src/0-send-receive/senderOnCChain.sol rename to src/interchain-messaging/0a-send-receive/senderOnCChain.sol diff --git a/src/0b-send-receive copy/_INSTRUCTIONS.md b/src/interchain-messaging/0b-send-receive/_INSTRUCTIONS.md similarity index 100% rename from src/0b-send-receive copy/_INSTRUCTIONS.md rename to src/interchain-messaging/0b-send-receive/_INSTRUCTIONS.md diff --git a/src/0b-send-receive copy/extendedReceiverOnSubnet.sol b/src/interchain-messaging/0b-send-receive/extendedReceiverOnSubnet.sol similarity index 100% rename from src/0b-send-receive copy/extendedReceiverOnSubnet.sol rename to src/interchain-messaging/0b-send-receive/extendedReceiverOnSubnet.sol diff --git a/src/0b-send-receive copy/extendedSenderOnCChain.sol b/src/interchain-messaging/0b-send-receive/extendedSenderOnCChain.sol similarity index 100% rename from src/0b-send-receive copy/extendedSenderOnCChain.sol rename to src/interchain-messaging/0b-send-receive/extendedSenderOnCChain.sol diff --git a/src/1-send-roundtrip/_INSTRUCTIONS.md b/src/interchain-messaging/1-send-roundtrip/_INSTRUCTIONS.md similarity index 100% rename from src/1-send-roundtrip/_INSTRUCTIONS.md rename to src/interchain-messaging/1-send-roundtrip/_INSTRUCTIONS.md diff --git a/src/1-send-roundtrip/receiverOnSubnet.sol b/src/interchain-messaging/1-send-roundtrip/receiverOnSubnet.sol similarity index 100% rename from src/1-send-roundtrip/receiverOnSubnet.sol rename to src/interchain-messaging/1-send-roundtrip/receiverOnSubnet.sol diff --git a/src/1-send-roundtrip/senderOnCChain.sol b/src/interchain-messaging/1-send-roundtrip/senderOnCChain.sol similarity index 100% rename from src/1-send-roundtrip/senderOnCChain.sol rename to src/interchain-messaging/1-send-roundtrip/senderOnCChain.sol diff --git a/src/2a-invoking-functions/SimpleCalculatorReceiverOnSubnet.sol b/src/interchain-messaging/2a-invoking-functions/SimpleCalculatorReceiverOnSubnet.sol similarity index 100% rename from src/2a-invoking-functions/SimpleCalculatorReceiverOnSubnet.sol rename to src/interchain-messaging/2a-invoking-functions/SimpleCalculatorReceiverOnSubnet.sol diff --git a/src/2a-invoking-functions/SimpleCalculatorSenderOnCChain.sol b/src/interchain-messaging/2a-invoking-functions/SimpleCalculatorSenderOnCChain.sol similarity index 100% rename from src/2a-invoking-functions/SimpleCalculatorSenderOnCChain.sol rename to src/interchain-messaging/2a-invoking-functions/SimpleCalculatorSenderOnCChain.sol diff --git a/src/2a-invoking-functions/_INSTRUCTIONS.md b/src/interchain-messaging/2a-invoking-functions/_INSTRUCTIONS.md similarity index 100% rename from src/2a-invoking-functions/_INSTRUCTIONS.md rename to src/interchain-messaging/2a-invoking-functions/_INSTRUCTIONS.md diff --git a/src/2b-invoking-functions/CalculatorActions.sol b/src/interchain-messaging/2b-invoking-functions/CalculatorActions.sol similarity index 100% rename from src/2b-invoking-functions/CalculatorActions.sol rename to src/interchain-messaging/2b-invoking-functions/CalculatorActions.sol diff --git a/src/2b-invoking-functions/CalculatorReceiverOnSubnet.sol b/src/interchain-messaging/2b-invoking-functions/CalculatorReceiverOnSubnet.sol similarity index 100% rename from src/2b-invoking-functions/CalculatorReceiverOnSubnet.sol rename to src/interchain-messaging/2b-invoking-functions/CalculatorReceiverOnSubnet.sol diff --git a/src/2b-invoking-functions/CalculatorSenderOnCChain.sol b/src/interchain-messaging/2b-invoking-functions/CalculatorSenderOnCChain.sol similarity index 100% rename from src/2b-invoking-functions/CalculatorSenderOnCChain.sol rename to src/interchain-messaging/2b-invoking-functions/CalculatorSenderOnCChain.sol diff --git a/src/2b-invoking-functions/_INSTRUCTIONS.md b/src/interchain-messaging/2b-invoking-functions/_INSTRUCTIONS.md similarity index 100% rename from src/2b-invoking-functions/_INSTRUCTIONS.md rename to src/interchain-messaging/2b-invoking-functions/_INSTRUCTIONS.md diff --git a/src/2c-invoking-functions/ExtendedCalculatorActions.sol b/src/interchain-messaging/2c-invoking-functions/ExtendedCalculatorActions.sol similarity index 100% rename from src/2c-invoking-functions/ExtendedCalculatorActions.sol rename to src/interchain-messaging/2c-invoking-functions/ExtendedCalculatorActions.sol diff --git a/src/2c-invoking-functions/ExtendedCalculatorReceiverOnSubnet.sol b/src/interchain-messaging/2c-invoking-functions/ExtendedCalculatorReceiverOnSubnet.sol similarity index 100% rename from src/2c-invoking-functions/ExtendedCalculatorReceiverOnSubnet.sol rename to src/interchain-messaging/2c-invoking-functions/ExtendedCalculatorReceiverOnSubnet.sol diff --git a/src/2c-invoking-functions/ExtendedCalculatorSenderOnCChain.sol b/src/interchain-messaging/2c-invoking-functions/ExtendedCalculatorSenderOnCChain.sol similarity index 100% rename from src/2c-invoking-functions/ExtendedCalculatorSenderOnCChain.sol rename to src/interchain-messaging/2c-invoking-functions/ExtendedCalculatorSenderOnCChain.sol diff --git a/src/2c-invoking-functions/_INSTRUCTIONS.md b/src/interchain-messaging/2c-invoking-functions/_INSTRUCTIONS.md similarity index 100% rename from src/2c-invoking-functions/_INSTRUCTIONS.md rename to src/interchain-messaging/2c-invoking-functions/_INSTRUCTIONS.md diff --git a/src/3-registry/ReceiverOnSubnetWithRegistry.sol b/src/interchain-messaging/3-registry/ReceiverOnSubnetWithRegistry.sol similarity index 100% rename from src/3-registry/ReceiverOnSubnetWithRegistry.sol rename to src/interchain-messaging/3-registry/ReceiverOnSubnetWithRegistry.sol diff --git a/src/3-registry/SenderOnCChainWithRegistry.sol b/src/interchain-messaging/3-registry/SenderOnCChainWithRegistry.sol similarity index 100% rename from src/3-registry/SenderOnCChainWithRegistry.sol rename to src/interchain-messaging/3-registry/SenderOnCChainWithRegistry.sol diff --git a/src/4-creating-contracts/_INSTRUCTIONS.md b/src/interchain-messaging/3-registry/_INSTRUCTIONS.md similarity index 100% rename from src/4-creating-contracts/_INSTRUCTIONS.md rename to src/interchain-messaging/3-registry/_INSTRUCTIONS.md diff --git a/src/9-incentivize-relayer/_INSTRUCTIONS.md b/src/interchain-messaging/4-incentivize-relayer/_INSTRUCTIONS.md similarity index 100% rename from src/9-incentivize-relayer/_INSTRUCTIONS.md rename to src/interchain-messaging/4-incentivize-relayer/_INSTRUCTIONS.md diff --git a/src/9-incentivize-relayer/receiverWithFees.sol b/src/interchain-messaging/4-incentivize-relayer/receiverWithFees.sol similarity index 100% rename from src/9-incentivize-relayer/receiverWithFees.sol rename to src/interchain-messaging/4-incentivize-relayer/receiverWithFees.sol diff --git a/src/9-incentivize-relayer/senderWithFees.sol b/src/interchain-messaging/4-incentivize-relayer/senderWithFees.sol similarity index 100% rename from src/9-incentivize-relayer/senderWithFees.sol rename to src/interchain-messaging/4-incentivize-relayer/senderWithFees.sol diff --git a/src/5-native-to-erc20-interchain-token-transfer/ExampleWNATV.sol b/src/interchain-token-transfer/0-native-to-erc20-interchain-token-transfer/ExampleWNATV.sol similarity index 100% rename from src/5-native-to-erc20-interchain-token-transfer/ExampleWNATV.sol rename to src/interchain-token-transfer/0-native-to-erc20-interchain-token-transfer/ExampleWNATV.sol diff --git a/src/5-native-to-erc20-interchain-token-transfer/_INSTRUCTIONS.md b/src/interchain-token-transfer/0-native-to-erc20-interchain-token-transfer/_INSTRUCTIONS.md similarity index 100% rename from src/5-native-to-erc20-interchain-token-transfer/_INSTRUCTIONS.md rename to src/interchain-token-transfer/0-native-to-erc20-interchain-token-transfer/_INSTRUCTIONS.md diff --git a/src/6-erc20-to-native-interchain-token-transfer/ERC20.sol b/src/interchain-token-transfer/1-erc20-to-native-interchain-token-transfer/ERC20.sol similarity index 100% rename from src/6-erc20-to-native-interchain-token-transfer/ERC20.sol rename to src/interchain-token-transfer/1-erc20-to-native-interchain-token-transfer/ERC20.sol diff --git a/src/6-erc20-to-native-interchain-token-transfer/_INSTRUCTIONS.md b/src/interchain-token-transfer/1-erc20-to-native-interchain-token-transfer/_INSTRUCTIONS.md similarity index 100% rename from src/6-erc20-to-native-interchain-token-transfer/_INSTRUCTIONS.md rename to src/interchain-token-transfer/1-erc20-to-native-interchain-token-transfer/_INSTRUCTIONS.md diff --git a/src/7-native-to-native-interchain-token-transfer/ExampleWNATV.sol b/src/interchain-token-transfer/2-native-to-native-interchain-token-transfer/ExampleWNATV.sol similarity index 100% rename from src/7-native-to-native-interchain-token-transfer/ExampleWNATV.sol rename to src/interchain-token-transfer/2-native-to-native-interchain-token-transfer/ExampleWNATV.sol diff --git a/src/7-native-to-native-interchain-token-transfer/_INSTRUCTIONS.md b/src/interchain-token-transfer/2-native-to-native-interchain-token-transfer/_INSTRUCTIONS.md similarity index 100% rename from src/7-native-to-native-interchain-token-transfer/_INSTRUCTIONS.md rename to src/interchain-token-transfer/2-native-to-native-interchain-token-transfer/_INSTRUCTIONS.md diff --git a/src/8-erc20-to-erc20-interchain-token-transfer/ERC20.sol b/src/interchain-token-transfer/3-erc20-to-erc20-interchain-token-transfer/ERC20.sol similarity index 100% rename from src/8-erc20-to-erc20-interchain-token-transfer/ERC20.sol rename to src/interchain-token-transfer/3-erc20-to-erc20-interchain-token-transfer/ERC20.sol diff --git a/src/8-erc20-to-erc20-interchain-token-transfer/_INSTRUCTIONS.md b/src/interchain-token-transfer/3-erc20-to-erc20-interchain-token-transfer/_INSTRUCTIONS.md similarity index 100% rename from src/8-erc20-to-erc20-interchain-token-transfer/_INSTRUCTIONS.md rename to src/interchain-token-transfer/3-erc20-to-erc20-interchain-token-transfer/_INSTRUCTIONS.md diff --git a/src/interchain-token-transfer/4-send-and-call/DexERC20Wrapper.sol b/src/interchain-token-transfer/4-send-and-call/DexERC20Wrapper.sol new file mode 100644 index 0000000..f8977e9 --- /dev/null +++ b/src/interchain-token-transfer/4-send-and-call/DexERC20Wrapper.sol @@ -0,0 +1,141 @@ +// (c) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// SPDX-License-Identifier: Ecosystem + +pragma solidity 0.8.18; + +import {IERC20SendAndCallReceiver} from "@avalanche-interchain-token-transfer/interfaces/IERC20SendAndCallReceiver.sol"; +import {SafeERC20TransferFrom} from "@avalanche-interchain-token-transfer/utils/SafeERC20TransferFrom.sol"; + +import {SafeERC20} from "@openzeppelin/contracts@4.8.1/token/ERC20/utils/SafeERC20.sol"; +import {IERC20} from "@openzeppelin/contracts@4.8.1/token/ERC20/IERC20.sol"; +import {Context} from "@openzeppelin/contracts@4.8.1/utils/Context.sol"; + +import {IWAVAX} from "./interfaces/IWAVAX.sol"; +import {IUniswapFactory} from "./interfaces/IUniswapFactory.sol"; +import {IUniswapPair} from "./interfaces/IUniswapPair.sol"; + +/** + * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. + * DO NOT USE THIS CODE IN PRODUCTION. + */ + +contract DexERC20Wrapper is Context, IERC20SendAndCallReceiver { + using SafeERC20 for IERC20; + + address public immutable WNATIVE; + address public immutable factory; + + struct SwapOptions { + address tokenOut; + uint256 minAmountOut; + } + + constructor( + address wrappedNativeAddress, + address dexFactoryAddress + ) { + WNATIVE = wrappedNativeAddress; + factory = dexFactoryAddress; + } + + event TokensReceived( + bytes32 indexed sourceBlockchainID, + address indexed originTokenTransferrerAddress, + address indexed originSenderAddress, + address token, + uint256 amount, + bytes payload + ); + + // To receive native when another contract called. + receive() external payable {} + + function getAmountOut( + uint256 amountIn, + uint256 reserveIn, + uint256 reserveOut + ) internal pure returns (uint256 amountOut) { + uint256 amountInWithFee = amountIn * 997; + uint256 numerator = amountInWithFee * reserveOut; + uint256 denominator = reserveIn * 1e3 + amountInWithFee; + amountOut = numerator / denominator; + } + + function query( + uint256 amountIn, + address tokenIn, + address tokenOut + ) internal view returns (uint256 amountOut) { + if (tokenIn == tokenOut || amountIn == 0) { + return 0; + } + address pair = IUniswapFactory(factory).getPair(tokenIn, tokenOut); + if (pair == address(0)) { + return 0; + } + (uint256 r0, uint256 r1, ) = IUniswapPair(pair).getReserves(); + (uint256 reserveIn, uint256 reserveOut) = tokenIn < tokenOut ? (r0, r1) : (r1, r0); + if (reserveIn > 0 && reserveOut > 0) { + amountOut = getAmountOut(amountIn, reserveIn, reserveOut); + } + } + + function swap( + uint256 amountIn, + uint256 amountOut, + address tokenIn, + address tokenOut, + address to + ) internal { + address pair = IUniswapFactory(factory).getPair(tokenIn, tokenOut); + (uint256 amount0Out, uint256 amount1Out) = (tokenIn < tokenOut) + ? (uint256(0), amountOut) : (amountOut, uint256(0)); + IERC20(tokenIn).safeTransfer(pair, amountIn); + IUniswapPair(pair).swap(amount0Out, amount1Out, to, new bytes(0)); + } + + function receiveTokens( + bytes32 sourceBlockchainID, + address originTokenTransferrerAddress, + address originSenderAddress, + address token, + uint256 amount, + bytes calldata payload + ) external { + emit TokensReceived({ + sourceBlockchainID: sourceBlockchainID, + originTokenTransferrerAddress: originTokenTransferrerAddress, + originSenderAddress: originSenderAddress, + token: token, + amount: amount, + payload: payload + }); + + require(payload.length > 0, "DexERC20Wrapper: empty payload"); + + IERC20 _token = IERC20(token); + // Receives teleported assets to be used for different purposes. + SafeERC20TransferFrom.safeTransferFrom(_token, _msgSender(), amount); + + // Requests a quote from the Uniswap V2-like contract. + uint256 amountOut = query(amount, token, WNATIVE); + require(amountOut > 0, "DexERC20Wrapper: insufficient liquidity"); + + // Parses the payload of the message. + SwapOptions memory swapOptions = abi.decode(payload, (SwapOptions)); + // Checks if the target swap price is still valid. + require(amountOut >= swapOptions.minAmountOut, "DexERC20Wrapper: slippage exceeded"); + + // Verifies if the desired tokenOut is a native or wrapped asset. + if (swapOptions.tokenOut == address(0)) { + swap(amount, amountOut, token, WNATIVE, address(this)); + IWAVAX(WNATIVE).withdraw(amountOut); + payable(originSenderAddress).transfer(amountOut); + } else { + swap(amount, amountOut, token, WNATIVE, originSenderAddress); + } + } + +} diff --git a/src/interchain-token-transfer/4-send-and-call/_INSTRUCTIONS.md b/src/interchain-token-transfer/4-send-and-call/_INSTRUCTIONS.md new file mode 100644 index 0000000..420517e --- /dev/null +++ b/src/interchain-token-transfer/4-send-and-call/_INSTRUCTIONS.md @@ -0,0 +1,82 @@ +# DexERC20Wrapper - Avalanche Interchain Token Transfer (ICTT) sendAndCall Instructions + +This guide explains how to deploy and interact with the `DexERC20Wrapper` contract on the Avalanche network for interchain token transfers and swaps. It assumes that you have already deployed your source and destination tokens and that there is a Uniswap V2-like decentralized exchange on the destination chain. + +> **Note:** The source and destination chains involved in this process are Avalanche Layer 1s (L1s), previously referred to as subnets. Developers have the flexibility to deploy their own Avalanche L1s and easily transfer tokens and execute logic between these L1s. + +## Overview + +The process involves the following steps: +1. **Deploy Source and Destination Tokens**: Deploy tokens on both the source and destination Avalanche L1 chains. +2. **Wrap Uniswap V2-like Contracts**: The `DexERC20Wrapper` contract is deployed on the destination chain to interact with the existing Uniswap V2-like contract. +3. **Trigger `sendAndCall`**: Use the `sendAndCall` function on the source chain to transfer tokens to the destination chain. The `DexERC20Wrapper` contract will be triggered on the destination chain, executing the swap logic. + +## Prerequisites + +- **Source and Destination Tokens**: Ensure that your tokens are deployed on both the source and destination Avalanche L1 chains. +- **Uniswap V2-like Contracts**: The destination chain should have a Uniswap V2-like decentralized exchange with liquidity for the tokens you want to swap. + +## Deploying the DexERC20Wrapper Contract + +1. **Deploy the `DexERC20Wrapper` Contract** + + Deploy the contract on the destination chain by providing the addresses for the wrapped native token (e.g., WAVAX) and the Uniswap V2 factory. + + ```solidity + constructor( + address wrappedNativeAddress, + address dexFactoryAddress + ) + ``` + + Example deployment command: + + ```bash + forge create --rpc-url --private-key src/interchain-token-transfer/4-send-and-call/DexERC20Wrapper.sol:DexERC20Wrapper --constructor-args + ``` + +2. **Event Emissions** + + The contract emits the `TokensReceived` event when tokens are received from the source chain. This event helps in tracking the token transfers and swap execution. + + ```solidity + event TokensReceived( + bytes32 indexed sourceBlockchainID, + address indexed originTokenTransferrerAddress, + address indexed originSenderAddress, + address token, + uint256 amount, + bytes payload + ); + ``` + +## Using the Contract for Interchain Transfers + +### Step 1: Triggering `sendAndCall` + +On the source chain, trigger the `sendAndCall` function to initiate the token transfer. Once the tokens are successfully sent, the `DexERC20Wrapper` contract on the destination chain will automatically be triggered. + +The `receiveTokens` function in the `DexERC20Wrapper` contract will handle the received tokens, query the swap price, check for slippage, and execute the swap if conditions are met. + +### Step 2: Swap Logic Execution + +Upon receiving the tokens, the contract performs the following actions: + +1. **Query Swap Price**: The contract queries the swap price using the internal `query` function and ensures that the output amount meets the minimum specified in the `payload` (slippage protection). +2. **Execute Swap**: The swap is executed on the Uniswap V2-like contract. If the output token is a native token (e.g., AVAX), the contract unwraps it and transfers the native token to the original sender. +3. **Slippage Check**: Slippage is handled by checking that the output amount is greater than or equal to the `minAmountOut` specified in the payload. + +### Step 3: Handling Native Tokens + +If the output token is a native asset, such as AVAX, the contract unwraps it and sends it to the original sender: + +```solidity +IWAVAX(WNATIVE).withdraw(amountOut); +payable(originSenderAddress).transfer(amountOut); +``` + +For ERC20 tokens, the contract transfers the swapped tokens directly to the sender's address. + +## Conclusion + +The `DexERC20Wrapper` contract allows for seamless interchain token transfers and swaps on Avalanche L1s. By following the steps outlined in this guide, you can deploy and interact with the contract to transfer and swap tokens across Avalanche L1 chains, with slippage protection and support for both native and ERC20 tokens. diff --git a/src/interchain-token-transfer/4-send-and-call/interfaces/IUniswapFactory.sol b/src/interchain-token-transfer/4-send-and-call/interfaces/IUniswapFactory.sol new file mode 100644 index 0000000..887ad71 --- /dev/null +++ b/src/interchain-token-transfer/4-send-and-call/interfaces/IUniswapFactory.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.18; + +interface IUniswapFactory { + function getPair(address tokenA, address tokenB) external view returns (address pair); +} \ No newline at end of file diff --git a/src/interchain-token-transfer/4-send-and-call/interfaces/IUniswapPair.sol b/src/interchain-token-transfer/4-send-and-call/interfaces/IUniswapPair.sol new file mode 100644 index 0000000..f4477fc --- /dev/null +++ b/src/interchain-token-transfer/4-send-and-call/interfaces/IUniswapPair.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.18; + +interface IUniswapPair { + event Swap( + address indexed sender, + uint256 amount0In, + uint256 amount1In, + uint256 amount0Out, + uint256 amount1Out, + address indexed to + ); + + function factory() external view returns (address); + + function token0() external view returns (address); + + function token1() external view returns (address); + + function getReserves() + external + view + returns ( + uint112 reserve0, + uint112 reserve1, + uint32 blockTimestampLast + ); + + function swap( + uint256 amount0Out, + uint256 amount1Out, + address to, + bytes calldata data + ) external; +} \ No newline at end of file diff --git a/src/interchain-token-transfer/4-send-and-call/interfaces/IWAVAX.sol b/src/interchain-token-transfer/4-send-and-call/interfaces/IWAVAX.sol new file mode 100644 index 0000000..d09c254 --- /dev/null +++ b/src/interchain-token-transfer/4-send-and-call/interfaces/IWAVAX.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.18; + +interface IWAVAX { + function withdraw(uint256 amount) external; + + function deposit() external payable; +} \ No newline at end of file