Curve Swap

Swap tokens on Curve

# pragma version ^0.4.0

from ethereum.ercs import IERC20

interface IStableSwap:
    def exchange(i: int128, j: int128, dx: uint256, min_dy: uint256): nonpayable

DAI: constant(address) = 0x6B175474E89094C44Da98b954EedeAC495271d0F
USDC: constant(address) = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
USDT: constant(address) = 0xdAC17F958D2ee523a2206206994597C13D831ec7

POOL: constant(address) = 0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7
COINS: constant(address[3]) = [DAI, USDC, USDT]

@internal
def _safe_transfer(coin: address, to: address, amount: uint256):
    res: Bytes[32] = raw_call(
        coin,
        concat(
            method_id("transfer(address,uint256)"),
            convert(to, bytes32),
            convert(amount, bytes32),
        ),
        max_outsize=32,
    )
    if len(res) > 0:
        assert convert(res, bool)

@internal
def _safe_transfer_from(coin: address, _from: address, to: address, amount: uint256):
    res: Bytes[32] = raw_call(
        coin,
        concat(
            method_id("transferFrom(address,address,uint256)"),
            convert(_from, bytes32),
            convert(to, bytes32),
            convert(amount, bytes32),
        ),
        max_outsize=32,
    )
    if len(res) > 0:
        assert convert(res, bool)

@internal
def _safe_approve(coin: address, to: address, amount: uint256):
    res: Bytes[32] = raw_call(
        coin,
        concat(
            method_id("approve(address,uint256)"),
            convert(to, bytes32),
            convert(amount, bytes32),
        ),
        max_outsize=32,
    )
    if len(res) > 0:
        assert convert(res, bool)

@external
def swap(i: int128, j: int128, dx: uint256, min_dy: uint256):
    self._safe_transfer_from(COINS[i], msg.sender, self, dx)
    self._safe_approve(COINS[i], POOL, dx)

    extcall IStableSwap(POOL).exchange(i, j, dx, min_dy)

    bal: uint256 = staticcall IERC20(COINS[j]).balanceOf(self)
    self._safe_transfer(COINS[j], msg.sender, bal)

Try on Smart Contract Engineer