-
Notifications
You must be signed in to change notification settings - Fork 83
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* 1inch (OneSplit) DEX integration
- Loading branch information
1 parent
82659bc
commit f9f87c7
Showing
8 changed files
with
996 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,77 @@ | ||
pragma solidity 0.5.16; | ||
|
||
// Internal | ||
import { MassetHelpers } from "../masset/shared/MassetHelpers.sol"; | ||
|
||
// Library | ||
import { Ownable } from "@openzeppelin/contracts/ownership/Ownable.sol"; | ||
|
||
/** | ||
* @title AbstractBuyAndMint | ||
* @author Stability Labs Pty. Ltd. | ||
* @notice Abstract contract to allow buy bAsset tokens with ETH and mint mAssets tokens | ||
* from mStable. | ||
*/ | ||
contract AbstractBuyAndMint is Ownable { | ||
|
||
using MassetHelpers for address; | ||
|
||
event MassetAdded(address indexed mAsset); | ||
|
||
// mAsset address => exists | ||
mapping(address => bool) public mAssets; | ||
|
||
/** | ||
* @dev Abstarct constructor | ||
* @param _mAssets Array of valid mAsset addresses allowed to mint. | ||
*/ | ||
constructor(address[] memory _mAssets) internal { | ||
require(_mAssets.length > 0, "No mAssets provided"); | ||
for(uint256 i = 0; i < _mAssets.length; i++) { | ||
_addMasset(_mAssets[i]); | ||
} | ||
} | ||
|
||
/** | ||
* @dev Anyone can call and perform infinite approval for bAssets | ||
* @param _bAssets An array containing bAssets addresses | ||
*/ | ||
function infiniteApprove(address _mAsset, address[] calldata _bAssets) external { | ||
for(uint256 i = 0; i < _bAssets.length; i++) { | ||
_bAssets[i].safeInfiniteApprove(_mAsset); | ||
} | ||
} | ||
|
||
/** | ||
* @dev The Owner of the contract allowed to add a new supported mAsset. | ||
* @param _mAsset Address of the mAsset | ||
*/ | ||
function addMasset(address _mAsset) external onlyOwner { | ||
_addMasset(_mAsset); | ||
} | ||
|
||
/** | ||
* @dev Add a new mAsset to the supported mAssets list | ||
* @param _mAsset Address of the mAsset | ||
*/ | ||
function _addMasset(address _mAsset) internal { | ||
require(_mAsset != address(0), "mAsset address is zero"); | ||
require(!_massetExists(_mAsset), "mAsset already exists"); | ||
mAssets[_mAsset] = true; | ||
emit MassetAdded(_mAsset); | ||
} | ||
|
||
/** | ||
* @dev Validate that the given mAsset supported by this contract. | ||
* @notice Only validate mAsset address. As bAsset gets validated during minting process. | ||
* @param _mAsset mAsset address to validate | ||
*/ | ||
function _massetExists(address _mAsset) internal view returns (bool) { | ||
return mAssets[_mAsset]; | ||
} | ||
|
||
/** | ||
* @dev Abstract function to get the external DEX contract address | ||
*/ | ||
function _externalDexAddress() internal view returns(address); | ||
} |
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,23 @@ | ||
pragma solidity 0.5.16; | ||
|
||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
|
||
/** | ||
* @title IMintWith1Inch | ||
* @author Stability Labs Pty. Ltd. | ||
* @notice Interface to Buy bAssets and Mint the mAssets from the OneSplit (1inch exchange) | ||
*/ | ||
interface IMintWith1Inch { | ||
/** | ||
* @dev Buy the maximum bAsset tokens from DEX and mint mAsset tokens from mStable. | ||
* ETH sent to the function used to buy bAsset tokens from DEX. | ||
* @param _srcBasset Source bAsset token address | ||
* @param _destMasset mAsset token address to mint | ||
* @param _minBassetUnits Minimum amount of bAssets to purchase | ||
* @param _distribution Distribution for different DEXes to buy bAssets from | ||
* @return mAssetQtyMinted Returns the quantity of mAsset minted from mStable | ||
*/ | ||
function buyAndMint(IERC20 _srcBasset, address _destMasset, uint256 _minBassetUnits, uint256[] calldata _distribution) | ||
external payable returns (uint256 mAssetQtyMinted); | ||
|
||
} |
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,108 @@ | ||
pragma solidity 0.5.16; | ||
|
||
// External | ||
import { AbstractBuyAndMint } from "./AbstractBuyAndMint.sol"; | ||
import { IMintWith1Inch } from "./IMintWith1Inch.sol"; | ||
import { IMasset } from "../interfaces/IMasset.sol"; | ||
|
||
// Libs | ||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; | ||
|
||
/** | ||
* @dev OneSplit Exchange interface | ||
*/ | ||
contract IOneSplit { | ||
function swap( | ||
IERC20 fromToken, | ||
IERC20 toToken, | ||
uint256 amount, | ||
uint256 minReturn, | ||
uint256[] memory distribution, | ||
uint256 flags | ||
) public payable; | ||
} | ||
|
||
/** | ||
* @title MintWith1Inch | ||
* @author Stability Labs Pty. Ltd. | ||
* @notice Contract integrates with 1inch (a.k.a OneSplit) contract and allows anyone to buy | ||
* bAsset tokens using ETH from the 1inch and mint mAssets. | ||
*/ | ||
contract MintWith1Inch is AbstractBuyAndMint, IMintWith1Inch { | ||
|
||
using SafeMath for uint256; | ||
|
||
// 1inch Exchange 1Split contract address | ||
IOneSplit public oneSplit; | ||
|
||
IERC20 private constant ETH_ADDRESS = IERC20(0x0000000000000000000000000000000000000000); | ||
|
||
/** | ||
* @param _oneSplit OneSplit contract address | ||
* @param _mAssets Array of mAssets addresses | ||
*/ | ||
constructor(address _oneSplit, address[] memory _mAssets) | ||
public | ||
AbstractBuyAndMint(_mAssets) | ||
{ | ||
require(_oneSplit != address(0), "1inch address is zero"); | ||
|
||
oneSplit = IOneSplit(_oneSplit); | ||
} | ||
|
||
// @override | ||
function _externalDexAddress() internal view returns(address) { | ||
return address(oneSplit); | ||
} | ||
|
||
// NOTICE: Make the following function call off-chain to get the `distribution` and | ||
// pass to this function. This is to reduce gas consumption. | ||
|
||
// ============================================================================ | ||
// Offchain: To calculate the distribution to mint max mAssets with ETH amount | ||
// ============================================================================ | ||
/* | ||
// Parts = 20 (Suggested by 1inch to provide best rates) | ||
uint256 parts = 20; | ||
// Not disable any exchange | ||
uint256 disableFlags = 0; | ||
(,uint256[] memory distribution) = | ||
oneSplit.getExpectedReturn( | ||
ETH_ADDRESS, //fromToken | ||
IERC20(_srcBasset), //toToken | ||
msg.value, //fromAmount | ||
parts, //parts | ||
disableFlags //disableFlags | ||
); | ||
*/ | ||
|
||
// @override | ||
function buyAndMint( | ||
IERC20 _srcBasset, | ||
address _destMasset, | ||
uint256 _minBassetUnits, | ||
uint256[] calldata _distribution | ||
) | ||
external | ||
payable | ||
returns (uint256 mAssetQtyMinted) | ||
{ | ||
require(msg.value > 0, "ETH not sent"); | ||
require(_massetExists(_destMasset), "Not a valid mAsset"); | ||
|
||
// 1. Buy bAsset of worth `msg.value` ETH from OneSplit | ||
oneSplit.swap.value(msg.value)( | ||
ETH_ADDRESS, | ||
_srcBasset, | ||
msg.value, | ||
_minBassetUnits, | ||
_distribution, | ||
0 | ||
); | ||
|
||
uint256 balance = _srcBasset.balanceOf(address(this)); | ||
// 2. Mint mAsset with all bAsset | ||
mAssetQtyMinted = IMasset(_destMasset).mintTo(address(_srcBasset), balance, _msgSender()); | ||
} | ||
} |
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,43 @@ | ||
pragma solidity 0.5.16; | ||
|
||
/** | ||
* @title IBuyAndMint | ||
* @author Stability Labs Pty. Ltd. | ||
* @notice Interface to Buy bAssets and Mint the mAssets from the DEXes | ||
*/ | ||
interface IBuyAndMint { | ||
/** | ||
* @dev Buy the maximum bAsset tokens from DEX and mint mAsset tokens from mStable. | ||
* ETH sent to the function used to buy bAsset tokens from DEX. | ||
* @param _srcBasset Source bAsset token address | ||
* @param _destMasset mAsset token address to mint | ||
* @return mAssetQtyMinted Returns the quantity of mAsset minted from mStable | ||
*/ | ||
function buyAndMintMaxMasset(address _srcBasset, address _destMasset) | ||
external payable returns (uint256 mAssetQtyMinted); | ||
|
||
/** | ||
* @dev Buy the required bAsset tokens from the DEX and Mint the specific amount of | ||
* mAssets from mStable. ETH sent to the function used to buy bAsset tokens from DEX. | ||
* @param _srcBasset Source bAsset token address | ||
* @param _destMasset mAsset token address to mint | ||
* @param _amountOfBassets Expected amount of bAssets to mint from DEX and mint 1:1 from mStable | ||
* @return mAssetQtyMinted Returns the quantity of mAsset minted from mStable | ||
*/ | ||
function buyAndMintGivenMasset(address _srcBasset, address _destMasset, uint256 _amountOfBassets) | ||
external payable returns (uint256 mAssetQtyMinted); | ||
|
||
/** | ||
* @dev Buy the required bAssets tokens from the DEX and Mint mAssets from mStable. | ||
* ETH sent to the function used to buy bAsset tokens from DEX. | ||
* @param _srcBassets Array of source bAssets token address | ||
* @param _ethAmount Array of ETH amount to buy corresponding bAsset from DEX | ||
* @param _destMAsset mAsset token address to mint | ||
* @return mAssetQtyMinted Returns the quantity of mAsset minted from mStable | ||
*/ | ||
function buyAndMintMulti( | ||
address[] calldata _srcBassets, | ||
uint256[] calldata _ethAmount, | ||
address _destMAsset | ||
) external payable returns (uint256 mAssetQtyMinted); | ||
} |
Oops, something went wrong.