# Broker-2
This time you don't have access to the magic function. Apply the concept of price manipulation to beat this level and bring down the funds of the Broker.
In order to interact with the Uniswapv2Pair, we have provided a UniswapRouter at address
0xA0Cbc6dF8A36998567583Ef7a85C4346DD1B1909
.
Here is a helpful link to read more about how to use the router. https://docs.uniswap.org/contracts/v2/reference/smart-contracts/router-02
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.6;
interface IUniswapV2Pair {
function mint(address to) external returns (uint liquidity);
function getReserves()
external
view
returns (
uint112 _reserve0,
uint112 _reserve1,
uint32 _blockTimestampLast
);
function swap(
uint amount0Out,
uint amount1Out,
address to,
bytes calldata data
) external;
}
interface ERC20Like {
function transfer(address dst, uint qty) external returns (bool);
function transferFrom(
address src,
address dst,
uint qty
) external returns (bool);
function approve(address dst, uint qty) external returns (bool);
function balanceOf(address who) external view returns (uint);
}
interface WETH9 is ERC20Like {
function deposit() external payable;
}
// a simple overcollateralized loan bank which accepts WETH as collateral and a
// token for borrowing. 0% APRs
contract PartTwoBroker {
IUniswapV2Pair public pair;
ERC20Like public constant weth =
WETH9(0x5e5184Ab4ecFcb75342dda1Ae3d655c8EbAf113e);
ERC20Like public token;
mapping(address => uint256) public deposited;
mapping(address => uint256) public debt;
constructor(IUniswapV2Pair _pair, ERC20Like _token) public {
pair = _pair;
token = _token;
}
function rate() public view returns (uint256) {
uint112 _weth;
uint112 _tok;
if (token < weth) {
(_tok, _weth, ) = pair.getReserves();
} else {
(_weth, _tok, ) = pair.getReserves();
}
uint256 _rate = uint256(_tok / _weth);
return _rate;
}
function safeDebt(address user) public view returns (uint256) {
return (deposited[user] * rate() * 2) / 3;
}
// borrow some tokens
function borrow(uint256 amount) public {
debt[msg.sender] += amount;
require(
safeDebt(msg.sender) >= debt[msg.sender],
"err: undercollateralized"
);
token.transfer(msg.sender, amount);
}
// repay your loan
function repay(uint256 amount) public {
debt[msg.sender] -= amount;
token.transferFrom(msg.sender, address(this), amount);
}
// repay a user's loan and get back their collateral. no discounts.
function liquidate(address user, uint256 amount) public returns (uint256) {
require(safeDebt(user) <= debt[user], "err: overcollateralized");
debt[user] -= amount;
token.transferFrom(msg.sender, address(this), amount);
uint256 collateralValueRepaid = amount / rate();
weth.transfer(msg.sender, collateralValueRepaid);
return collateralValueRepaid;
}
// top up your collateral
function deposit(uint256 amount) public {
deposited[msg.sender] += amount;
weth.transferFrom(msg.sender, address(this), amount);
}
// remove collateral
function withdraw(uint256 amount) public {
deposited[msg.sender] -= amount;
require(
safeDebt(msg.sender) >= debt[msg.sender],
"err: undercollateralized"
);
weth.transfer(msg.sender, amount);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.6;
import "./PartTwoBroker.sol";
contract PartTwoToken {
mapping(address => uint256) public balanceOf;
mapping(address => bool) public dropped;
mapping(address => mapping(address => uint256)) public allowance;
uint256 public totalSupply = 1_000_000 gwei;
constructor() public {
balanceOf[msg.sender] = totalSupply;
require(balanceOf[msg.sender] == 1_000_000 gwei);
}
function approve(address to, uint256 amount) public returns (bool) {
allowance[msg.sender][to] = amount;
return true;
}
function transfer(address to, uint256 amount) public returns (bool) {
return transferFrom(msg.sender, to, amount);
}
function transferFrom(
address from,
address to,
uint256 amount
) public returns (bool) {
if (from != msg.sender) {
allowance[from][to] -= amount;
}
balanceOf[from] -= amount;
balanceOf[to] += amount;
return true;
}
}
interface IUniswapV2Factory {
function createPair(
address tokenA,
address tokenB
) external returns (address pair);
}
contract SetupPartTwo {
WETH9 public constant weth =
WETH9(0x5e5184Ab4ecFcb75342dda1Ae3d655c8EbAf113e);
IUniswapV2Factory public constant factory =
IUniswapV2Factory(0x98b0C32857bbf24Fc070d75CA65B428a3fc8FF49);
PartTwoToken public token;
IUniswapV2Pair public pair;
PartTwoBroker public broker;
uint256 constant DECIMALS = 1 gwei;
uint256 totalBefore;
// create and bootstrap the token/weth pool for borrowing against WETH
constructor() public payable {
require(msg.value == 50 gwei);
weth.deposit{value: msg.value}();
token = new PartTwoToken();
pair = IUniswapV2Pair(
factory.createPair(address(weth), address(token))
);
broker = new PartTwoBroker(pair, ERC20Like(address(token)));
token.transfer(address(broker), 500_000 * DECIMALS);
weth.transfer(address(pair), 25 gwei);
token.transfer(address(pair), 500_000 * DECIMALS);
pair.mint(address(this));
weth.approve(address(broker), type(uint256).max);
broker.deposit(25 gwei);
broker.borrow(250_000 * DECIMALS);
totalBefore =
weth.balanceOf(address(broker)) +
token.balanceOf(address(broker)) /
broker.rate();
}
function isSolved() public view returns (bool) {
return weth.balanceOf(address(broker)) < 5 gwei;
}
}