forked from ConcourseOpen/DPI_Arb_Bot_Example
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
arb_bot and arb smart contract
- Loading branch information
Showing
100 changed files
with
30,046 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
script/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
openethereum --chain kovan --jsonrpc-port=9999 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
node_modules | ||
build | ||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
1. Run `npm install` | ||
2. Create a `.env` file with the following contents: | ||
|
||
``` | ||
KOVAN_NODE_URL= | ||
PRIV_KEY_TEST= | ||
PRIV_KEY_DEPLOY= | ||
``` | ||
3. Run `npm start` to start a local Ganache chain with forked Mainnet state | ||
4. Run `npm run migrate` in order to compile and migrate the project's contracts to this local Ganache chain | ||
5. Run `npm test` in order to run the tests. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"erc20Mock": [{"inputs":[{"internalType":"address","name":"_initialAccount","type":"address"},{"internalType":"uint256","name":"_initialBalance","type":"uint256"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"greedIsGood","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}], | ||
"issueModule":[{"inputs":[{"internalType":"contract IController","name":"_controller","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_setToken","type":"address"},{"indexed":false,"internalType":"address","name":"_issuer","type":"address"},{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"address","name":"_hookContract","type":"address"},{"indexed":false,"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"SetTokenIssued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_setToken","type":"address"},{"indexed":false,"internalType":"address","name":"_redeemer","type":"address"},{"indexed":false,"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"SetTokenRedeemed","type":"event"},{"inputs":[],"name":"controller","outputs":[{"internalType":"contract IController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISetToken","name":"_setToken","type":"address"},{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"getRequiredComponentUnitsForIssue","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISetToken","name":"_setToken","type":"address"},{"internalType":"contract IManagerIssuanceHook","name":"_preIssueHook","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISetToken","name":"_setToken","type":"address"},{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"issue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISetToken","name":"_setToken","type":"address"},{"internalType":"uint256","name":"_quantity","type":"uint256"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"contract IDepositor","name":"_issueContract","type":"address"}],"name":"issueFromContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISetToken","name":"","type":"address"}],"name":"managerIssuanceHook","outputs":[{"internalType":"contract IManagerIssuanceHook","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ISetToken","name":"_setToken","type":"address"},{"internalType":"uint256","name":"_quantity","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"removeModule","outputs":[],"stateMutability":"nonpayable","type":"function"}] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"WETH": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", | ||
"Controller": "0xF1B12A7b1f0AF744ED21eEC7d3E891C48Fd3c329", | ||
"SetTokenCreator": "0x86a73e16D2dEce40b378B6aF645A93678214EF43", | ||
"BasicIssuanceModule": "0x508910aA6fF3D029Dc358dD0f775877A355BA35B", | ||
"StreamingFeeModule": "0x3D8d14b7eFb8e342189ee14c3d40dCe005EB901B", | ||
"ProtocolViewer": "0x17efe2A497C7B173be4eB5bb8481C2dc741509fE", | ||
"DPI": "0x9F295d05bAeE0E95F52aC1db0C2bDc26A226e4BB", | ||
"DPIUniswapPool": "0x8bd7244f23d583c7418a2be53461e4c45abb2e6f" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
let s; | ||
DefiPulseIndexTrade.deployed().then((k) => s = k) | ||
s.arbTokensForIndex("0xA6a801124c243a3507e8b9b503F154c02eAe48E9") | ||
|
243 changes: 243 additions & 0 deletions
243
DPI_Arb_Bot-master/smart-contract/contracts/DefiPulseIndexTrade.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,243 @@ | ||
pragma solidity >=0.6.6; | ||
pragma experimental ABIEncoderV2; | ||
|
||
import '@uniswap/lib/contracts/libraries/Babylonian.sol'; | ||
|
||
import "./aave/FlashLoanReceiverBase.sol"; | ||
import "./aave/ILendingPoolAddressesProvider.sol"; | ||
import "./aave/ILendingPool.sol"; | ||
|
||
import './libraries/UniswapV2Library.sol'; | ||
import './interfaces/IUniswapV2Router02.sol'; | ||
import './interfaces/IUniswapV2Factory.sol'; | ||
import './interfaces/IERC20.sol'; | ||
import './interfaces/IWETH.sol'; | ||
import './interfaces/IBasicIssuanceModule.sol'; | ||
import './interfaces/ISetToken.sol'; | ||
|
||
|
||
|
||
contract DefiPulseIndexTrade is FlashLoanReceiverBase { | ||
address immutable factory; | ||
address immutable setController; | ||
address immutable issueModule; | ||
address immutable WETH; | ||
IUniswapV2Router02 immutable router; | ||
uint256 MAX_INT = 2**256 - 1; | ||
|
||
|
||
constructor(address _factory, address _router, address _setController, address _issueModule, address _addressProvider) | ||
FlashLoanReceiverBase(_addressProvider) public { | ||
factory = _factory; // Uniswap Factory V02 | ||
router = IUniswapV2Router02(_router); // Uniswap Router | ||
setController = _setController; // Set Controller | ||
issueModule = _issueModule; // Set Token Issue Module | ||
WETH = IUniswapV2Router01(_router).WETH(); | ||
} | ||
|
||
|
||
function initiateArbitrage(address _indexToken, uint256 _targetPriceInEther) public payable { | ||
if(msg.value > 0) IWETH(WETH).deposit{value: msg.value}(); | ||
(bool aToB, uint256 indexAmount, address pairAddress) = getIndexAmountToBuyOrSell(_indexToken, _targetPriceInEther); | ||
if(aToB) { | ||
buyIndex(_indexToken, indexAmount, pairAddress); | ||
} else { | ||
require(indexAmount > 1 ether, "issue amount must be > 0"); | ||
sellIndex(_indexToken, indexAmount, pairAddress); | ||
} | ||
msg.sender.transfer(address(this).balance); | ||
} | ||
|
||
function approveToken(address _token) public { | ||
IERC20(_token).approve(address(router), MAX_INT); // Set Max Approval for neccessary tokens; | ||
IERC20(_token).approve(setController, MAX_INT); // Set Max Approval for neccessary tokens; | ||
IERC20(_token).approve(issueModule, MAX_INT); // Set Max Approval for neccessary tokens; | ||
} | ||
|
||
function approveSetToken(address _index) public { | ||
IERC20(_index).approve(address(router), MAX_INT); // Set Max Approval for neccessary tokens; | ||
ISetToken.Position[] memory positions = ISetToken(_index).getPositions(); | ||
|
||
for(uint256 i=0; i<positions.length; i++) { | ||
IERC20(positions[i].component).approve(setController, MAX_INT); // Set Max Approval for Set Contract; | ||
IERC20(positions[i].component).approve(issueModule, MAX_INT); // Set Max Approval for Set Contract; | ||
IERC20(positions[i].component).approve(address(router), MAX_INT); // Set Max Approval for neccessary tokens; | ||
} | ||
|
||
} | ||
|
||
function issueSetToken(address _index, uint256 _amount) private { | ||
IBasicIssuanceModule(issueModule).issue(ISetToken(_index), _amount, address(this)); | ||
} | ||
|
||
function redeemSetToken(address _index, uint256 _amount) private { | ||
IBasicIssuanceModule(issueModule).redeem(ISetToken(_index), _amount, address(this)); | ||
} | ||
|
||
function getIndexAmountToBuyOrSell(address _index, uint256 _targetPriceInEther) public view returns (bool isBuy, uint256 amountIn, address pairAddress_) { | ||
address pairAddress = IUniswapV2Factory(factory).getPair(WETH, _index); | ||
|
||
(uint256 reserveA, uint256 reserveB) = UniswapV2Library.getReserves(factory, WETH, _index); | ||
(bool aToB, uint256 _amount) = computeProfitMaximizingTrade(_targetPriceInEther, 1000000000, reserveA, reserveB); | ||
|
||
uint256 maxAmount = _amount < reserveB ? _amount : reserveB; | ||
|
||
return (aToB, maxAmount, pairAddress); | ||
} | ||
|
||
// Loan WETH and trade for individual parts, then redeem and sell Index (will trigger executeOperation); | ||
function sellIndex(address _index, uint256 amountIndexToSell, address pairAddress) internal { | ||
ISetToken.Position[] memory positions = ISetToken(_index).getPositions(); | ||
|
||
// Second calculate amount of ETH needed to get individual tokens | ||
uint256 totalEthNeeded = 0; | ||
uint256[] memory tokenAmounts = new uint256[](positions.length); | ||
address[] memory tokens = new address[](positions.length); | ||
|
||
{ | ||
for(uint256 i=0; i<positions.length; i++) { | ||
(uint256 tokenReserveA, uint256 tokenReserveB) = UniswapV2Library.getReserves(factory, WETH, positions[i].component); | ||
uint256 tokensNeeded = preciseMulCeil(uint256(positions[i].unit), amountIndexToSell); | ||
tokenAmounts[i] = tokensNeeded; | ||
tokens[i] = positions[i].component; | ||
|
||
uint256 ethNeeded = router.getAmountIn(tokensNeeded, tokenReserveA, tokenReserveB); | ||
totalEthNeeded = totalEthNeeded.add(ethNeeded).mul(1000) / 950; | ||
} | ||
} | ||
bytes memory data = abi.encode(_index, amountIndexToSell, tokenAmounts, tokens); | ||
|
||
// Third get Flash Loan, and execute rest once funds are received from aave (executeOperation) | ||
ILendingPool lendingPool = ILendingPool(addressesProvider.getLendingPool()); | ||
lendingPool.flashLoan(address(this), 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE, totalEthNeeded, data); | ||
} | ||
|
||
function executeOperation(address _reserve, uint256 _amount, uint256 _fee, bytes calldata _params) | ||
external override { | ||
require(_amount <= getBalanceInternal(address(this), _reserve), "Invalid balance, was the flashLoan successful?"); | ||
uint totalDebt = _amount.add(_fee); | ||
|
||
// Wrap Ether | ||
IWETH(WETH).deposit{value: address(this).balance}(); | ||
|
||
(address _index, uint256 _indexAmount, uint256[] memory tokenAmounts, address[] memory tokens) = abi.decode(_params, (address, uint256, uint256[], address[])); | ||
|
||
|
||
acquireTokensOfSet(tokens, tokenAmounts); | ||
|
||
// issue Set Token | ||
issueSetToken(_index, _indexAmount * (1 ether)); | ||
|
||
|
||
address[] memory path = new address[](2); | ||
path[0] = _index; | ||
path[1] = WETH; | ||
|
||
router.swapExactTokensForTokens(_indexAmount * (1 ether), 0, path, address(this), block.timestamp); | ||
|
||
|
||
IWETH(WETH).withdraw(IERC20(WETH).balanceOf(address(this))); | ||
|
||
transferFundsBackToPoolInternal(_reserve, totalDebt); | ||
|
||
} | ||
|
||
|
||
|
||
|
||
// Loan Index and Sell for Individual Parts | ||
function buyIndex(address _index, uint256 amountIndexToBuy, address pairAddress) internal returns (address t0, address t1, uint256 a0, uint256 a1) { | ||
|
||
bytes memory data = abi.encode(_index, amountIndexToBuy, pairAddress); | ||
|
||
address token0 = IUniswapV2Pair(pairAddress).token0(); | ||
address token1 = IUniswapV2Pair(pairAddress).token1(); | ||
uint amount0Out = _index == token0 ? amountIndexToBuy : 0; | ||
uint amount1Out = _index == token1 ? amountIndexToBuy : 0; | ||
|
||
IUniswapV2Pair(pairAddress).swap(amount0Out, amount1Out, address(this), data); | ||
|
||
return (token0, token1, amount0Out, amount1Out); | ||
} | ||
|
||
function completeBuyIndex(address _index, uint256 _amountIndexToBuy) private { | ||
redeemSetToken(_index, _amountIndexToBuy); | ||
|
||
liquidateSetPositions(_index); | ||
} | ||
|
||
function uniswapV2Call(address _sender, uint _amount0, uint _amount1, bytes calldata _data) external { | ||
address token0 = IUniswapV2Pair(msg.sender).token0(); // fetch the address of token0 | ||
address token1 = IUniswapV2Pair(msg.sender).token1(); // fetch the address of token1 | ||
assert(msg.sender == IUniswapV2Factory(factory).getPair(token0, token1)); | ||
|
||
(address _index, uint256 _indexAmount) = abi.decode(_data, (address, uint256)); | ||
|
||
completeBuyIndex(_index, _indexAmount); | ||
|
||
uint256 amount = token0 == address(WETH) ? _amount1 : _amount0; | ||
|
||
|
||
address[] memory path = new address[](2); | ||
path[0] = _amount0 == 0 ? token0 : token1; | ||
path[1] = _amount0 == 0 ? token1 : token0; | ||
|
||
IERC20(WETH).transfer(msg.sender, amount); | ||
IWETH(WETH).withdraw(IERC20(WETH).balanceOf(address(this))); | ||
} | ||
|
||
function acquireTokensOfSet(address[] memory tokens, uint256[] memory tokenAmounts) private { | ||
|
||
for(uint256 i=0; i<tokens.length; i++) { | ||
address[] memory path = new address[](2); | ||
path[0] = WETH; | ||
path[1] = tokens[i]; | ||
router.swapTokensForExactTokens(tokenAmounts[i], MAX_INT, path, address(this), block.timestamp); | ||
} | ||
|
||
} | ||
|
||
function liquidateSetPositions(address _index) private { | ||
ISetToken.Position[] memory positions = ISetToken(_index).getPositions(); | ||
|
||
for(uint256 i=0; i<positions.length; i++) { | ||
uint256 tokenBalance = IERC20(positions[i].component).balanceOf(address(this)); | ||
address[] memory path = new address[](2); | ||
path[0] = positions[i].component; | ||
path[1] = WETH; | ||
router.swapExactTokensForTokens(IERC20(positions[i].component).balanceOf(address(this)), 0, path, address(this), block.timestamp); | ||
} | ||
} | ||
|
||
// computes the direction and magnitude of the profit-maximizing trade | ||
// https://github.com/Uniswap/uniswap-v2-periphery/blob/master/contracts/examples/ExampleSwapToPrice.sol | ||
function computeProfitMaximizingTrade( | ||
uint256 truePriceTokenA, | ||
uint256 truePriceTokenB, | ||
uint256 reserveA, | ||
uint256 reserveB | ||
) private pure returns (bool aToB, uint256 amountIn) { | ||
aToB = reserveA.mul(truePriceTokenB) / reserveB < truePriceTokenA; | ||
|
||
uint256 invariant = reserveA.mul(reserveB); | ||
|
||
uint256 leftSide = Babylonian.sqrt( | ||
invariant.mul(aToB ? truePriceTokenA : truePriceTokenB).mul(1000) / | ||
uint256(aToB ? truePriceTokenB : truePriceTokenA).mul(997) | ||
); | ||
uint256 rightSide = (aToB ? reserveA.mul(1000) : reserveB.mul(1000)) / 997; | ||
|
||
// compute the amount that must be sent to move the price to the profit-maximizing price | ||
amountIn = leftSide.sub(rightSide); | ||
} | ||
|
||
|
||
// From Precise Unit SafeMath | ||
function preciseMulCeil(uint256 a, uint256 b) internal pure returns (uint256) { | ||
if (a == 0 || b == 0) { | ||
return 0; | ||
} | ||
return a.mul(b).sub(1).div(10 ** 18).add(1); | ||
} | ||
|
||
} |
25 changes: 25 additions & 0 deletions
25
DPI_Arb_Bot-master/smart-contract/contracts/GSN/Context.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
|
||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.6.0; | ||
|
||
/* | ||
* @dev Provides information about the current execution context, including the | ||
* sender of the transaction and its data. While these are generally available | ||
* via msg.sender and msg.data, they should not be accessed in such a direct | ||
* manner, since when dealing with GSN meta-transactions the account sending and | ||
* paying for execution may not be the actual sender (as far as an application | ||
* is concerned). | ||
* | ||
* This contract is only required for intermediate, library-like contracts. | ||
*/ | ||
abstract contract Context { | ||
function _msgSender() internal view virtual returns (address payable) { | ||
return msg.sender; | ||
} | ||
|
||
function _msgData() internal view virtual returns (bytes memory) { | ||
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | ||
return msg.data; | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
DPI_Arb_Bot-master/smart-contract/contracts/Migrations.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.6.6; | ||
|
||
contract Migrations { | ||
address public owner; | ||
uint public last_completed_migration; | ||
|
||
constructor() public { | ||
owner = msg.sender; | ||
} | ||
|
||
modifier restricted() { | ||
if (msg.sender == owner) _; | ||
} | ||
|
||
function setCompleted(uint completed) public restricted { | ||
last_completed_migration = completed; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.4.21 <0.7.0; | ||
|
||
import "./interfaces/IERC20.sol"; | ||
import "./UniswapLiteBase.sol"; | ||
|
||
contract MyDapp is UniswapLiteBase { | ||
address constant daiAddress = 0x6B175474E89094C44Da98b954EedeAC495271d0F; | ||
|
||
function getEthPriceInDai() public view returns (uint256 tokenAmount) { | ||
return _getEthToTokenInput(daiAddress, 1 ether); | ||
} | ||
|
||
function swapEthToDai() external payable returns (uint256 tokensBought) { | ||
uint256 amount = _ethToToken(daiAddress, msg.value); | ||
IERC20(daiAddress).transfer(msg.sender, amount); | ||
return amount; | ||
} | ||
} |
Oops, something went wrong.