Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/clober event #20

Merged
merged 5 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions contracts/BorrowControllerV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ contract BorrowControllerV2 is IBorrowControllerV2, ControllerV2, IPositionLocke
}

if (swapParams.inSubstitute == position.collateralToken) {
_swap(position.collateralToken, position.debtToken, swapParams.amount, swapParams.data);
_swap(positionId, position.collateralToken, position.debtToken, swapParams.amount, swapParams.data);
} else if (swapParams.inSubstitute == position.debtToken) {
_swap(position.debtToken, position.collateralToken, swapParams.amount, swapParams.data);
_swap(positionId, position.debtToken, position.collateralToken, swapParams.amount, swapParams.data);
}

_executeCouponTrade(user, position.debtToken, couponsToMint, couponsToBurn, interestThreshold);
_executeCouponTrade(user, positionId, position.debtToken, couponsToMint, couponsToBurn, interestThreshold);

if (collateralDelta > 0) {
_mintSubstituteAll(position.collateralToken, user, uint256(collateralDelta));
Expand Down Expand Up @@ -147,12 +147,16 @@ contract BorrowControllerV2 is IBorrowControllerV2, ControllerV2, IPositionLocke
_burnAllSubstitute(position.debtToken, msg.sender);
}

function _swap(address inSubstitute, address outSubstitute, uint256 inAmount, bytes memory swapParams)
internal
returns (uint256 outAmount)
{
function _swap(
uint256 positionId,
address inSubstitute,
address outSubstitute,
uint256 inAmount,
bytes memory swapParams
) internal returns (uint256 outAmount) {
address inToken = ISubstitute(inSubstitute).underlyingToken();
address outToken = ISubstitute(outSubstitute).underlyingToken();
uint256 beforeOutTokenBalance = IERC20(outToken).balanceOf(address(this));

ISubstitute(inSubstitute).burn(inAmount, address(this));
if (inToken == address(_weth)) _weth.deposit{value: inAmount}();
Expand All @@ -161,7 +165,10 @@ contract BorrowControllerV2 is IBorrowControllerV2, ControllerV2, IPositionLocke
if (!success) revert CollateralSwapFailed(string(result));
IERC20(inToken).approve(_router, 0);

outAmount = IERC20(outToken).balanceOf(address(this));
unchecked {
outAmount = IERC20(outToken).balanceOf(address(this)) - beforeOutTokenBalance;
}
emit SwapToken(positionId, inToken, outToken, inAmount, outAmount);

IERC20(outToken).approve(outSubstitute, outAmount);
ISubstitute(outSubstitute).mint(outAmount, address(this));
Expand Down
2 changes: 1 addition & 1 deletion contracts/DepositControllerV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ contract DepositControllerV2 is IDepositControllerV2, ControllerV2, IPositionLoc
_wrapCoupons(couponsToMint);
}

_executeCouponTrade(user, position.asset, couponsToMint, couponsToBurn, interestThreshold);
_executeCouponTrade(user, positionId, position.asset, couponsToMint, couponsToBurn, interestThreshold);

if (amountDelta > 0) {
_mintSubstituteAll(position.asset, user, uint256(amountDelta));
Expand Down
8 changes: 8 additions & 0 deletions contracts/interfaces/IBorrowControllerV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ import {ERC20PermitParams, PermitSignature} from "../libraries/PermitParams.sol"
import {Epoch} from "../libraries/Epoch.sol";

interface IBorrowControllerV2 is IControllerV2 {
event SwapToken(
uint256 indexed positionId,
address indexed inToken,
address indexed outToken,
uint256 inAmount,
uint256 outAmount
);

struct SwapParams {
address inSubstitute;
uint256 amount;
Expand Down
2 changes: 2 additions & 0 deletions contracts/interfaces/IControllerV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ pragma solidity ^0.8.0;

import {Epoch} from "../libraries/Epoch.sol";
import {BookId} from "../external/clober-v2/BookId.sol";
import {Coupon} from "../libraries/Coupon.sol";

interface IControllerV2 {
event SetCouponMarket(address indexed asset, Epoch indexed epoch, BookId sellMarketBookId, BookId buyMarketBookId);
event CouponTrade(uint256 indexed positionId, int256 cost, Coupon[] couponsToBuy, Coupon[] couponsToSell);

error InvalidAccess();
error InvalidMarket();
Expand Down
45 changes: 26 additions & 19 deletions contracts/libraries/ControllerV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ abstract contract ControllerV2 is IControllerV2, ERC1155Holder, Ownable2Step, Re

function _executeCouponTrade(
address user,
uint256 positionId,
address token,
Coupon[] memory couponsToMint,
Coupon[] memory couponsToBurn,
Expand All @@ -94,7 +95,6 @@ abstract contract ControllerV2 is IControllerV2, ERC1155Holder, Ownable2Step, Re
tokensToSettle[length] = token;

uint256 amount;

length = couponsToBurn.length;
for (uint256 i = 0; i < length; ++i) {
actionList[i] = IController.Action.TAKE;
Expand Down Expand Up @@ -133,35 +133,42 @@ abstract contract ControllerV2 is IControllerV2, ERC1155Holder, Ownable2Step, Re
if (interestThreshold > 0) {
if (IERC20(token).balanceOf(address(this)) < uint256(interestThreshold)) {
address underlyingToken = ISubstitute(token).underlyingToken();
uint256 minRequired = Math.min(
amount = Math.min(
IERC20(underlyingToken).allowance(user, address(this)), IERC20(underlyingToken).balanceOf(user)
);
ISubstitute(token).mintAll(user, Math.min(uint256(interestThreshold), minRequired));
ISubstitute(token).mintAll(user, Math.min(uint256(interestThreshold), amount));
}
IERC20(token).approve(address(_cloberController), uint256(interestThreshold));
}

uint256 beforeBalance = IERC20(token).balanceOf(address(this));
int256 balanceDiff;
unchecked {
IController.ERC20PermitParams[] memory erc20PermitParamsList;
IController.ERC721PermitParams[] memory erc721PermitParamsList;
_cloberController.execute(
actionList,
paramsDataList,
tokensToSettle,
erc20PermitParamsList,
erc721PermitParamsList,
uint64(block.timestamp)
);
if (interestThreshold > 0) {
IERC20(token).approve(address(_cloberController), 0);
}

IController.ERC20PermitParams[] memory erc20PermitParamsList;
IController.ERC721PermitParams[] memory erc721PermitParamsList;
_cloberController.execute(
actionList,
paramsDataList,
tokensToSettle,
erc20PermitParamsList,
erc721PermitParamsList,
uint64(block.timestamp)
);
if (interestThreshold > 0) {
IERC20(token).approve(address(_cloberController), 0);
uint256 afterBalance = IERC20(token).balanceOf(address(this));
if (afterBalance > beforeBalance) {
balanceDiff = -(afterBalance - beforeBalance).toInt256();
} else {
balanceDiff = (beforeBalance - afterBalance).toInt256();
}
}
if (
interestThreshold < 0
&& IERC20(token).balanceOf(address(this)) < beforeBalance + uint256(-interestThreshold)
) {
if (interestThreshold < balanceDiff) {
revert ControllerSlippage();
}
emit CouponTrade(positionId, balanceDiff, couponsToBurn, couponsToMint);
}

function _getUnderlyingToken(address substitute) internal view returns (address) {
Expand Down
Loading