Admin has gifted you 5e18 Btokens on your birthday. Using A,B,C,D,E token pairs on swap contracts, increase your BTokens. (See Foundry SetUp)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
import "forge-std/Test.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ISwapV2Router02} from "v2-periphery/interfaces/ISwapV2Router02.sol";
contract Token is ERC20 {
constructor(
string memory name,
string memory symbol,
uint initialMint
) ERC20(name, symbol) {
_mint(msg.sender, initialMint);
}
}
contract Arbitrage is Test {
address[] tokens;
Token Atoken;
Token Btoken;
Token Ctoken;
Token Dtoken;
Token Etoken;
Token Ftoken;
address owner = makeAddr("owner");
address arbitrageMan = makeAddr("arbitrageMan");
ISwapV2Router02 router =
ISwapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
function addL(address first, address second, uint aF, uint aS) internal {
router.addLiquidity(
address(first),
address(second),
aF,
aS,
aF,
aS,
owner,
block.timestamp
);
}
function setUp() public {
vm.createSelectFork("https://eth-mainnet.g.alchemy.com/v2/...");
vm.startPrank(owner);
Atoken = new Token("Atoken", "ATK", 100 ether);
tokens.push(address(Atoken));
Btoken = new Token("Btoken", "BTK", 100 ether);
tokens.push(address(Btoken));
Ctoken = new Token("Ctoken", "CTK", 100 ether);
tokens.push(address(Ctoken));
Dtoken = new Token("Dtoken", "DTK", 100 ether);
tokens.push(address(Dtoken));
Etoken = new Token("Etoken", "ETK", 100 ether);
tokens.push(address(Etoken));
Atoken.approve(address(router), 100 ether);
Btoken.approve(address(router), 100 ether);
Ctoken.approve(address(router), 100 ether);
Dtoken.approve(address(router), 100 ether);
Etoken.approve(address(router), 100 ether);
addL(address(Atoken), address(Btoken), 17 ether, 10 ether);
addL(address(Atoken), address(Ctoken), 11 ether, 7 ether);
addL(address(Atoken), address(Dtoken), 15 ether, 9 ether);
addL(address(Atoken), address(Etoken), 21 ether, 5 ether);
addL(address(Btoken), address(Ctoken), 36 ether, 4 ether);
addL(address(Btoken), address(Dtoken), 13 ether, 6 ether);
addL(address(Btoken), address(Etoken), 25 ether, 3 ether);
addL(address(Ctoken), address(Dtoken), 30 ether, 12 ether);
addL(address(Ctoken), address(Etoken), 10 ether, 8 ether);
addL(address(Dtoken), address(Etoken), 60 ether, 25 ether);
Btoken.transfer(arbitrageMan, 5 ether);
vm.stopPrank();
}
function testHack() public {
vm.startPrank(arbitrageMan);
uint tokensBefore = Btoken.balanceOf(arbitrageMan);
Btoken.approve(address(router), 5 ether);
// solution
uint tokensAfter = Btoken.balanceOf(arbitrageMan);
assertGt(tokensAfter, tokensBefore);
}
}
There are 5 tokens, our goal is to do arbitrage to earn more Btoken
We can list out the ratio of the tokens in each token pair, the tokens in the token pairs are not balanced so we can earn Btoken with arbitrage, and I will use these 4 pairs for arbitrage :
A:B 17:10 this
A:C 11:7
A:D 15:9 this
A:E 21:5
B:C 36:4 this
B:D 13:6
B:E 25:3
C:D 30:12 this
C:E 10:8
D:E 60:25
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
import "forge-std/Test.sol";
import {ERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol";
import {ISwapV2Router02} from "./v2-periphery/interfaces/ISwapV2Router02.sol";
contract Token is ERC20 {
constructor(
string memory name,
string memory symbol,
uint initialMint
) ERC20(name, symbol) {
_mint(msg.sender, initialMint);
}
}
contract Arbitrage is Test {
address[] tokens;
Token Atoken;
Token Btoken;
Token Ctoken;
Token Dtoken;
Token Etoken;
Token Ftoken;
address owner = makeAddr("owner");
address arbitrageMan = makeAddr("arbitrageMan");
ISwapV2Router02 router =
ISwapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
function addL(address first, address second, uint aF, uint aS) internal {
router.addLiquidity(
address(first),
address(second),
aF,
aS,
aF,
aS,
owner,
block.timestamp
);
}
function setUp() public {
vm.createSelectFork("https://eth.llamarpc.com");
vm.startPrank(owner);
Atoken = new Token("Atoken", "ATK", 100 ether);
tokens.push(address(Atoken));
Btoken = new Token("Btoken", "BTK", 100 ether);
tokens.push(address(Btoken));
Ctoken = new Token("Ctoken", "CTK", 100 ether);
tokens.push(address(Ctoken));
Dtoken = new Token("Dtoken", "DTK", 100 ether);
tokens.push(address(Dtoken));
Etoken = new Token("Etoken", "ETK", 100 ether);
tokens.push(address(Etoken));
Atoken.approve(address(router), 100 ether);
Btoken.approve(address(router), 100 ether);
Ctoken.approve(address(router), 100 ether);
Dtoken.approve(address(router), 100 ether);
Etoken.approve(address(router), 100 ether);
addL(address(Atoken), address(Btoken), 17 ether, 10 ether);
addL(address(Atoken), address(Ctoken), 11 ether, 7 ether);
addL(address(Atoken), address(Dtoken), 15 ether, 9 ether);
addL(address(Atoken), address(Etoken), 21 ether, 5 ether);
addL(address(Btoken), address(Ctoken), 36 ether, 4 ether);
addL(address(Btoken), address(Dtoken), 13 ether, 6 ether);
addL(address(Btoken), address(Etoken), 25 ether, 3 ether);
addL(address(Ctoken), address(Dtoken), 30 ether, 12 ether);
addL(address(Ctoken), address(Etoken), 10 ether, 8 ether);
addL(address(Dtoken), address(Etoken), 60 ether, 25 ether);
Btoken.transfer(arbitrageMan, 5 ether);
vm.stopPrank();
}
function testHack() public {
vm.startPrank(arbitrageMan);
uint tokensBefore = Btoken.balanceOf(arbitrageMan);
Btoken.approve(address(router), 5 ether);
// solution
console.log("Btoken balance before", tokensBefore);
address[] memory path = new address[](5);
path[0] = address(Btoken);
path[1] = address(Atoken);
path[2] = address(Dtoken);
path[3] = address(Ctoken);
path[4] = address(Btoken);
router.swapExactTokensForTokens(5 ether, 0, path, arbitrageMan, type(uint).max);
uint tokensAfter = Btoken.balanceOf(arbitrageMan);
console.log("Btoken balance after", tokensAfter);
assertGt(tokensAfter, tokensBefore);
}
}
# forge test --match-path test/arbitrage.t.sol -vv
[⠑] Compiling...
No files changed, compilation skipped
Running 1 test for test/arbitrage.t.sol:Arbitrage
[PASS] testHack() (gas: 224385)
Logs:
Btoken balance before 5000000000000000000
Btoken balance after 20129888944077446732
Test result: ok. 1 passed; 0 failed; finished in 13.05s