feat: Implemented swap()
This commit is contained in:
@@ -30,6 +30,7 @@ contract AngleAdapter is ISwapAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @inheritdoc ISwapAdapter
|
||||||
function swap(
|
function swap(
|
||||||
bytes32 poolId,
|
bytes32 poolId,
|
||||||
IERC20 sellToken,
|
IERC20 sellToken,
|
||||||
@@ -37,13 +38,28 @@ contract AngleAdapter is ISwapAdapter {
|
|||||||
OrderSide side,
|
OrderSide side,
|
||||||
uint256 specifiedAmount
|
uint256 specifiedAmount
|
||||||
) external returns (Trade memory trade) {
|
) external returns (Trade memory trade) {
|
||||||
revert NotImplemented("TemplateSwapAdapter.swap");
|
if (specifiedAmount == 0) {
|
||||||
|
return trade;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 gasBefore = gasleft();
|
||||||
|
if (side == OrderSide.Sell) {
|
||||||
|
trade.calculatedAmount =
|
||||||
|
sell(sellToken, buyToken, specifiedAmount);
|
||||||
|
trade.price = getPriceAt(specifiedAmount, address(sellToken), address(buyToken));
|
||||||
|
} else {
|
||||||
|
trade.calculatedAmount =
|
||||||
|
buy(sellToken, buyToken, specifiedAmount);
|
||||||
|
trade.price = getPriceAt(specifiedAmount, address(buyToken), address(sellToken));
|
||||||
|
}
|
||||||
|
trade.gasUsed = gasBefore - gasleft();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @inheritdoc ISwapAdapter
|
/// @inheritdoc ISwapAdapter
|
||||||
/// @dev mint may have no limits, but we underestimate them to make sure, with the same amount of sellToken.
|
/// @dev mint may have no limits, but we underestimate them to make sure, with the same amount of sellToken.
|
||||||
/// We use the quoteIn (incl. fee), because calculating fee requires a part of the implementation of
|
/// We use the quoteIn (incl. fee), because calculating fee requires a part of the implementation of
|
||||||
/// the Angle Diamond Storage, and therefore redundant functions and excessive contract size, with an high complexity.
|
/// the Angle Diamond Storage, and therefore redundant functions and excessive contract size, with an high complexity.
|
||||||
|
/// In addition, we underestimate to * 0.9 to ensure swaps with OrderSide.Buy won't fail anyway.
|
||||||
function getLimits(bytes32, IERC20 sellToken, IERC20 buyToken)
|
function getLimits(bytes32, IERC20 sellToken, IERC20 buyToken)
|
||||||
external
|
external
|
||||||
view
|
view
|
||||||
@@ -63,6 +79,7 @@ contract AngleAdapter is ISwapAdapter {
|
|||||||
else {
|
else {
|
||||||
limits[0] = sellToken.balanceOf(transmuterAddress);
|
limits[0] = sellToken.balanceOf(transmuterAddress);
|
||||||
}
|
}
|
||||||
|
limits[0] = limits[0] * 90 / 100;
|
||||||
limits[1] = transmuter.quoteIn(limits[0], sellTokenAddress, buyTokenAddress);
|
limits[1] = transmuter.quoteIn(limits[0], sellTokenAddress, buyTokenAddress);
|
||||||
}
|
}
|
||||||
else { // burn(sell agToken)
|
else { // burn(sell agToken)
|
||||||
@@ -74,6 +91,7 @@ contract AngleAdapter is ISwapAdapter {
|
|||||||
else {
|
else {
|
||||||
collatLimit = buyToken.balanceOf(transmuterAddress);
|
collatLimit = buyToken.balanceOf(transmuterAddress);
|
||||||
}
|
}
|
||||||
|
collatLimit = collatLimit * 90 / 100;
|
||||||
limits[0] = transmuter.quoteIn(collatLimit, buyTokenAddress, sellTokenAddress);
|
limits[0] = transmuter.quoteIn(collatLimit, buyTokenAddress, sellTokenAddress);
|
||||||
limits[1] = collatLimit;
|
limits[1] = collatLimit;
|
||||||
}
|
}
|
||||||
@@ -128,6 +146,48 @@ contract AngleAdapter is ISwapAdapter {
|
|||||||
amountIn
|
amountIn
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @notice Executes a sell order on the contract.
|
||||||
|
/// @param sellToken The token being sold.
|
||||||
|
/// @param buyToken The token being bought.
|
||||||
|
/// @param amount The amount to be traded.
|
||||||
|
/// @return calculatedAmount The amount of tokens received.
|
||||||
|
function sell(
|
||||||
|
IERC20 sellToken,
|
||||||
|
IERC20 buyToken,
|
||||||
|
uint256 amount
|
||||||
|
) internal returns (uint256 calculatedAmount) {
|
||||||
|
address sellTokenAddress = address(sellToken);
|
||||||
|
address buyTokenAddress = address(buyToken);
|
||||||
|
uint256 amountOut = transmuter.quoteIn(amount, sellTokenAddress, buyTokenAddress);
|
||||||
|
|
||||||
|
// TODO: use safeTransferFrom
|
||||||
|
sellToken.transferFrom(msg.sender, address(this), amount);
|
||||||
|
sellToken.approve(address(transmuter), amount);
|
||||||
|
transmuter.swapExactInput(amount, 0, sellTokenAddress, buyTokenAddress, msg.sender, 0);
|
||||||
|
return amountOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Executes a buy order on the contract.
|
||||||
|
/// @param sellToken The token being sold.
|
||||||
|
/// @param buyToken The token being bought.
|
||||||
|
/// @param amountOut The amount of buyToken to receive.
|
||||||
|
/// @return calculatedAmount The amount of tokens received.
|
||||||
|
function buy(
|
||||||
|
IERC20 sellToken,
|
||||||
|
IERC20 buyToken,
|
||||||
|
uint256 amountOut
|
||||||
|
) internal returns (uint256 calculatedAmount) {
|
||||||
|
address sellTokenAddress = address(sellToken);
|
||||||
|
address buyTokenAddress = address(buyToken);
|
||||||
|
uint256 amountIn = transmuter.quoteOut(amountOut, sellTokenAddress, buyTokenAddress);
|
||||||
|
|
||||||
|
// TODO: use safeTransferFrom
|
||||||
|
sellToken.transferFrom(msg.sender, address(this), amountIn);
|
||||||
|
sellToken.approve(address(transmuter), amountIn);
|
||||||
|
transmuter.swapExactOutput(amountOut, type(uint256).max, sellTokenAddress, buyTokenAddress, msg.sender, 0);
|
||||||
|
return amountIn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract contract ITransmuter {
|
abstract contract ITransmuter {
|
||||||
|
|||||||
Reference in New Issue
Block a user