Skip to content

Instantly share code, notes, and snippets.

@muellerberndt
Created March 4, 2020 18:31
Show Gist options
  • Save muellerberndt/9a06067124a57bc78679401bf69f40d6 to your computer and use it in GitHub Desktop.
Save muellerberndt/9a06067124a57bc78679401bf69f40d6 to your computer and use it in GitHub Desktop.
pragma solidity ^0.5.0;
import "./SafeMath.sol";
// A liquidity pool that also does collateralized loans!!
contract zBx {
using SafeMath for uint256;
mapping (address => uint256) public token_balances;
mapping (address => uint256) public ether_balances;
struct ConstantProductPool {
uint256 eth_reserve;
uint256 token_reserve;
}
ConstantProductPool public exchange;
constructor() public payable {
exchange = ConstantProductPool(msg.value, 1000000000000000000);
}
function getInputPrice(uint256 input_amount, uint256 input_reserve, uint256 output_reserve) internal pure returns (uint256) {
require(input_reserve > 0 && output_reserve > 0);
uint256 input_amount_with_fee = input_amount.mul(997);
uint256 numerator = input_amount_with_fee.mul(output_reserve);
uint256 denominator = (input_reserve.mul(1000)).add(input_amount_with_fee);
return numerator / denominator;
}
function getOutputPrice(uint256 output_amount, uint256 input_reserve, uint256 output_reserve) internal pure returns (uint256) {
require(input_reserve > 0 && output_reserve > 0);
uint256 numerator = input_reserve.mul(output_amount).mul(1000);
uint256 denominator = (output_reserve.sub(output_amount)).mul(997);
return numerator.div(denominator);
}
function tokenToEth(uint256 eth_bought) public returns (uint256) {
require(eth_bought > 0);
uint256 tokens_sold = getOutputPrice(eth_bought, exchange.token_reserve, exchange.eth_reserve);
// tokens sold is always > 0
token_balances[msg.sender] = token_balances[msg.sender].sub(tokens_sold);
msg.sender.transfer(eth_bought);
exchange.token_reserve = exchange.token_reserve.add(tokens_sold);
exchange.eth_reserve = exchange.eth_reserve.sub(eth_bought);
return tokens_sold;
}
function ethToToken() public payable returns (uint256) {
uint256 eth_sold = msg.value;
require(eth_sold > 0);
uint256 tokens_bought = getInputPrice(eth_sold, exchange.eth_reserve.sub(eth_sold), exchange.token_reserve);
token_balances[msg.sender] = token_balances[msg.sender].add(tokens_bought);
exchange.token_reserve = exchange.token_reserve.sub(tokens_bought);
exchange.eth_reserve = exchange.eth_reserve.add(msg.value);
return tokens_bought;
}
function() external payable {
ethToToken();
}
function getTokenToEthOutputPrice(uint256 eth_bought) public view returns (uint256) {
return getOutputPrice(eth_bought, exchange.token_reserve, exchange.eth_reserve);
}
function getEthToTokenInputPrice(uint256 eth_sold) public view returns (uint256) {
return getInputPrice(eth_sold, exchange.eth_reserve.sub(eth_sold), exchange.token_reserve);
}
function minCollateral(uint256 eth_borrow) internal view returns (uint256) {
// Minimum collateralization is 200%!
return getTokenToEthOutputPrice(eth_borrow).mul(2);
}
function hasEnoughCollateral(uint256 eth_borrow, address borrower) internal view returns (bool) {
return (token_balances[borrower] >= minCollateral(eth_borrow));
}
function takeLoanCollateralizedByToken(uint256 eth_borrow) public {
require(hasEnoughCollateral(eth_borrow, msg.sender));
msg.sender.transfer(eth_borrow);
}
}
contract FlashLoan {
constructor() payable public {
}
function getLoan(uint256 amount) public payable {
msg.sender.transfer(amount);
}
function() payable external {
}
}
contract SymbolicArbitrage {
event AssertionFailed(string message);
uint256 public starting_balance;
zBx public defi;
FlashLoan public flashloan;
constructor(address payable _loan, address payable _zBx) public payable {
starting_balance = address(this).balance;
defi = zBx(_zBx);
flashloan = FlashLoan(_loan);
}
function checkProfit() public view {
assert(address(this).balance <= starting_balance);
}
function getLoan(uint256 amount) public {
flashloan.getLoan(amount);
}
function tokenToEth(uint256 eth_bought) public {
defi.tokenToEth(eth_bought);
}
function ethToToken(uint256 eth_sold) public returns (uint256) {
address(defi).call.value(eth_sold)("");
}
function takeLoanCollateralizedByToken(uint256 eth_borrow) public {
defi.takeLoanCollateralizedByToken(eth_borrow);
}
function () payable external {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment