Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;

import "../../../libraries/ArrayLib.sol";
import "../../../../interfaces/IStandardizedYieldAdapter.sol";
import "../../../../interfaces/InfiniFi/InfiniFiInterfaces.sol";

import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

contract PendleInfiniFiAdapter is IStandardizedYieldAdapter {
using SafeERC20 for IERC20;

error TokenMustBeUSDC(address token);

address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
address public constant IUSD = 0x48f9e38f3070AD8945DFEae3FA70987722E3D89c;
address public constant MSIG = 0x80608f852D152024c0a2087b16939235fEc2400c;
address public constant GATEWAY_PROXY = 0x3f04b65Ddbd87f9CE0A2e7Eb24d80e7fb87625b5;

address public constant PIVOT_TOKEN = IUSD;

bool allowUSDCOut;

constructor() {
IERC20(IUSD).forceApprove(GATEWAY_PROXY, type(uint256).max);
IERC20(USDC).forceApprove(GATEWAY_PROXY, type(uint256).max);
}

modifier onlyUSDC(address _token) {
if (_token != USDC) {
revert TokenMustBeUSDC(_token);
}
_;
}

function setAllowUSDCOut(bool _enabled) external {
if (msg.sender != MSIG) {
revert("Sender not authorized");
}
allowUSDCOut = _enabled;
}

function convertToDeposit(
address tokenIn,
uint256 amountTokenIn
) external override onlyUSDC(tokenIn) returns (uint256) {
return InfiniFiGateway(GATEWAY_PROXY).mint(msg.sender, amountTokenIn);
}

function convertToRedeem(
address tokenOut,
uint256 amountYieldTokenIn
) external override onlyUSDC(tokenOut) returns (uint256) {
uint256 assetAmountOut = _receiptToAsset(amountYieldTokenIn);
return InfiniFiGateway(GATEWAY_PROXY).redeem(msg.sender, amountYieldTokenIn, assetAmountOut);
}

function previewConvertToDeposit(
address tokenIn,
uint256 amountTokenIn
) external view override onlyUSDC(tokenIn) returns (uint256 /*amountOut*/) {
return _assetToReceipt(amountTokenIn);
}

function previewConvertToRedeem(
address tokenOut,
uint256 amountYieldTokenIn
) external view override onlyUSDC(tokenOut) returns (uint256 /*amountOut*/) {
return _receiptToAsset(amountYieldTokenIn);
}

function getAdapterTokensDeposit() external pure override returns (address[] memory) {
return ArrayLib.create(USDC);
}

function getAdapterTokensRedeem() external view override returns (address[] memory) {
return allowUSDCOut ? ArrayLib.create(USDC) : new address[](0);
}

function _receiptToAsset(uint256 amountReceipt) internal view returns (uint256) {
address redeemController = InfiniFiGateway(GATEWAY_PROXY).getAddress("redeemController");
return IRedeemController(redeemController).receiptToAsset(amountReceipt);
}

function _assetToReceipt(uint256 amountAsset) internal view returns (uint256) {
address mintController = InfiniFiGateway(GATEWAY_PROXY).getAddress("mintController");
return IMintController(mintController).assetToReceipt(amountAsset);
}
}
16 changes: 16 additions & 0 deletions contracts/interfaces/InfiniFi/InfiniFiInterfaces.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.0;

interface InfiniFiGateway {
function mint(address _to, uint256 _amount) external returns (uint256);
function redeem(address _to, uint256 _amount, uint256 _minAmountOut) external returns (uint256);
function getAddress(string memory _name) external view returns (address);
}

interface IMintController {
function assetToReceipt(uint256 _assetAmount) external view returns (uint256);
}

interface IRedeemController {
function receiptToAsset(uint256 _receiptAmount) external view returns (uint256);
}