3 minutes
Smart contract development: coder un Swap sur Uniswap avec des data de prod
Dans cet article nous allons voir comment réaliser un échange d’USDC avec de l’USDT en codant un smart contract qui utiliser Uniswap.
Pour cet example, j’ai utilisé Node version:
nvm use v14.17.6
. J’ai aussi installé les modules NodeJSganache-cli
ettruffle
Création du Smart contract
Créer un fichier SimpleUniswapSwap.sol
dans le répertoire contracts
de votre repo git et ajouter le contenu suivant:
// SPDX-License-Identifier: MIT
pragma solidity ^0.7;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./interfaces/Uniswap.sol";
contract SimpleUniswapSwap {
address private constant UNISWAP_V2_ROUTER =
0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
function swap(
address _tokenIn,
address _tokenOut,
uint256 _amountIn,
uint256 _amountOutMin,
address _to
) external {
IERC20(_tokenIn).transferFrom(msg.sender, address(this), _amountIn); // Send money to this smart contract
IERC20(_tokenIn).approve(UNISWAP_V2_ROUTER, _amountIn); // Allow uniswap router to use/swap the money we just transfered
address[] memory path;
if (_tokenIn == WETH || _tokenOut == WETH) {
path = new address[](2);
path[0] = _tokenIn;
path[1] = _tokenOut;
} else {
path = new address[](3);
path[0] = _tokenIn;
path[1] = WETH;
path[2] = _tokenOut;
}
IUniswapV2Router(UNISWAP_V2_ROUTER).swapExactTokensForTokens(
_amountIn,
_amountOutMin,
path,
_to,
block.timestamp
);
}
}
L’interface Uniswap.sol
dans le répertoire ./contracts/interfaces
ressemble à ceci:
// SPDX-License-Identifier: MIT
pragma solidity ^0.7;
// https://uniswap.org/docs/v2/smart-contracts
interface IUniswapV2Router {
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
}
Création du TU permettant d’appeler notre Smart contract
Créer un fichier test/simple-uniswap-swap.js
et ajouter le contenu suivant:
const BN = require("bn.js"); // On charge le module Node Bignumber
const { USDC, USDT, USDC_WHALE } = require("./config"); // Adresses des tokens USC, USDT et wallet
const IERC20 = artifacts.require("IERC20"); // on load l'interface des contracts ERC20
const SimpleUniswapSwap = artifacts.require("SimpleUniswapSwap"); //on load le smart contract qu'on a créé pour swapper des tokens ERC20
contract("SimpleUniswapSwap", (accounts) => {
const WHALE = USDC_WHALE;
const AMOUNT_IN = 1000;
const AMOUNT_OUT_MIN = 980;
const TOKEN_IN = USDC;
const TOKEN_OUT = USDT;
const TO = accounts[0];
let simpleUniswapSwap;
let tokenIn;
let tokenOut;
beforeEach(async () => {
tokenIn = await IERC20.at(TOKEN_IN);
tokenOut = await IERC20.at(TOKEN_OUT);
simpleUniswapSwap = await SimpleUniswapSwap.new();
await tokenIn.approve(simpleUniswapSwap.address, AMOUNT_IN, { from: WHALE });
});
it("should pass", async () => {
await simpleUniswapSwap.swap(
tokenIn.address,
tokenOut.address,
AMOUNT_IN,
AMOUNT_OUT_MIN,
TO,
{
from: WHALE,
}
);
console.log(`in ${AMOUNT_IN}`);
console.log(`out ${await tokenOut.balanceOf(TO)}`);
});
});
Forker le mainnet Ethereum
Créer un fichier de config truffle-config.js
au niveau root de votre repo contenant l’alias vers l’environnement mainnet_fork
:
module.exports = {
networks: {
mainnet_fork: {
host: "127.0.0.1", // Localhost (default: none)
port: 8545, // Standard Ethereum port (default: none)
network_id: "999", // Any network (default: none)
},
},
// Set default mocha options here, use special reporters etc.
mocha: {
// timeout: 100000
},
// Configure your compilers
compilers: {
solc: {
version: "0.7.6", // Fetch exact version from solc-bin (default: truffle's version)
},
},
}
Repérer une whale possèdant de l’USDC via https://twitter.com/whale_alert, récupérer son wallet Ethereum via Etherscan et unlocker le dans votre fork Ethereum.
source .env
ganache-cli --fork https://mainnet.infura.io/v3/$TOKEN_INFURA --seed $YOUR_SEED -i --unlock $WHALE_ADDRESS --networkId 999
Exécution du swap
npx truffle test --network mainnet_fork test/simple-uniswap-swap.js
Voilà, si tout est bien configuré, vous devriez voir ceci à la fin du test:
Interagir avec Ganache
npx truffle console --network mainnet_fork
# npx truffle debug 0xbb18c245899e6e11da427cb951d88de7f072ca1021c98fbb1c7b65660c572f44