Skip to content

Commit

Permalink
Merge pull request #34 from diwu1989/curveContracts
Browse files Browse the repository at this point in the history
Adding Curve support
  • Loading branch information
zviadm authored Jun 14, 2022
2 parents b27be86 + fb278c1 commit 4cb938a
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
29 changes: 29 additions & 0 deletions contracts/interfaces/curve/ICurve.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.8;

interface ICurve {
function A() external view returns (uint256);

function A_precise() external view returns (uint256);

function fee() external view returns (uint256);

function coins(uint256 i) external view returns (address);

function balances(uint256 i) external view returns (uint256);

function exchange(
int128 i,
int128 j,
uint256 dx,
uint256 min_dy
) external returns (uint256);

function get_dy(
int128 i,
int128 j,
uint256 dx
) external view returns (uint256);

function get_virtual_price() external view returns (uint256);
}
91 changes: 91 additions & 0 deletions contracts/swappa/PairCurve.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.8;

import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "../interfaces/curve/ICurve.sol";
import "./ISwappaPairV1.sol";

contract PairCurve is ISwappaPairV1 {
using SafeMath for uint256;

function swap(
address input,
address output,
address to,
bytes calldata data
) external override {
address swapPoolAddr = parseData(data);
uint256 inputAmount = ERC20(input).balanceOf(address(this));
require(
ERC20(input).approve(swapPoolAddr, inputAmount),
"PairCurve: approve failed!"
);
ICurve swapPool = ICurve(swapPoolAddr);
(int128 fromIdx, int128 toIdx) = getInputOutputIdx(
swapPool,
input,
output
);
uint256 outputAmount = swapPool.exchange(
fromIdx,
toIdx,
inputAmount,
0
);
require(
ERC20(output).transfer(to, outputAmount),
"PairCurve: transfer failed!"
);
}

function parseData(bytes memory data)
private
pure
returns (address swapPoolAddr)
{
require(data.length == 20, "PairCurve: invalid data!");
assembly {
swapPoolAddr := mload(add(data, 20))
}
}

function getOutputAmount(
address input,
address output,
uint256 amountIn,
bytes calldata data
) external view override returns (uint256 amountOut) {
address swapPoolAddr = parseData(data);
ICurve swapPool = ICurve(swapPoolAddr);
(int128 fromIdx, int128 toIdx) = getInputOutputIdx(
swapPool,
input,
output
);
return swapPool.get_dy(fromIdx, toIdx, amountIn);
}

function getInputOutputIdx(
ICurve swapPool,
address input,
address output
) private view returns (int128 fromIdx, int128 toIdx) {
uint8 idx;
fromIdx = toIdx = -1;
// curve pool contain at most 4 coins
for (idx = 0; idx < 4; idx++) {
if (fromIdx != -1 && toIdx != -1) {
// found coin indices
break;
}
address coin = swapPool.coins(idx);
if (coin == input) {
fromIdx = idx;
}
if (coin == output) {
toIdx = idx;
}
}
}
}

0 comments on commit 4cb938a

Please sign in to comment.