Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"contracts/v2/router/MakerHelper.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/interfaces/IERC721Receiver.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {
Ownable2StepUpgradeable,
OwnableUpgradeable
} from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
import {ITermMaxMarket} from "../../v1/ITermMaxMarket.sol";
import {ITermMaxMarketV2} from "../ITermMaxMarketV2.sol";
import {ITermMaxOrder} from "../../v1/ITermMaxOrder.sol";
import {TransferUtilsV2} from "../lib/TransferUtilsV2.sol";
import {IGearingToken} from "../../v1/tokens/IGearingToken.sol";
import {CurveCuts, OrderConfig} from "../../v1/storage/TermMaxStorage.sol";
import {OrderInitialParams} from "../ITermMaxOrderV2.sol";
import {VersionV2} from "../VersionV2.sol";
import {DelegateAble} from "../lib/DelegateAble.sol";
import {MakerHelperEvents} from "../events/MakerHelperEvents.sol";
import {MakerHelperErrors} from "../errors/MakerHelperErrors.sol";
/**
* @title MakerHelper
* @notice Helper contract for placing orders and other operations for the maker in the TermMax protocol
*/
contract MakerHelper is UUPSUpgradeable, Ownable2StepUpgradeable, IERC721Receiver, VersionV2 {
using TransferUtilsV2 for IERC20;
function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner {}
function initialize(address admin) public initializer {
__UUPSUpgradeable_init_unchained();
__Ownable_init_unchained(admin);
}
/**
* @notice Places an order and mints a GT token(The gt token will not be linked to the order)
* @dev This function is used to create a new order in the TermMax protocol
* @param market The market to place the order in
* @param maker The address of the maker placing the order
* @param collateralToMintGt Amount of collateral to mint GT tokens
* @param debtTokenToDeposit Amount of debt tokens to deposit
* @param ftToDeposit Amount of FT tokens to deposit
* @param xtToDeposit Amount of XT tokens to deposit
* @param orderConfig Configuration parameters for the order
* @return order The created ITermMaxOrder instance
* @return gtId The ID of the minted GT token
*/
function placeOrderForV1(
ITermMaxMarket market,
address maker,
uint256 collateralToMintGt,
uint256 debtTokenToDeposit,
uint128 ftToDeposit,
uint128 xtToDeposit,
OrderConfig memory orderConfig
) external returns (ITermMaxOrder order, uint256 gtId) {
(IERC20 ft, IERC20 xt, IGearingToken gt, address collateral, IERC20 debtToken) = market.tokens();
if (collateralToMintGt > 0) {
IERC20(collateral).safeTransferFrom(msg.sender, address(this), collateralToMintGt);
IERC20(collateral).safeIncreaseAllowance(address(gt), collateralToMintGt);
(gtId,) = market.issueFt(maker, 0, abi.encode(collateralToMintGt));
}
order = market.createOrder(maker, orderConfig.maxXtReserve, orderConfig.swapTrigger, orderConfig.curveCuts);
if (debtTokenToDeposit > 0) {
debtToken.safeTransferFrom(msg.sender, address(this), debtTokenToDeposit);
debtToken.safeIncreaseAllowance(address(market), debtTokenToDeposit);
market.mint(address(order), debtTokenToDeposit);
}
ft.safeTransferFrom(msg.sender, address(order), ftToDeposit);
xt.safeTransferFrom(msg.sender, address(order), xtToDeposit);
emit MakerHelperEvents.OrderPlaced(
maker, address(market), address(order), gtId, debtTokenToDeposit, ftToDeposit, xtToDeposit
);
}
/**
* @notice Places an order and mints a GT token(the gt token will be linked to the order)
* @dev This function is used to create a new order in the TermMax protocol
* @param market The market to place the order in
* @param salt A unique salt for the order
* @param collateralToMintGt Amount of collateral to mint GT tokens
* @param debtTokenToDeposit Amount of debt tokens to deposit
* @param ftToDeposit Amount of FT tokens to deposit
* @param xtToDeposit Amount of XT tokens to deposit
* @param initialParams Configuration parameters for the order
* @param delegateParams Parameters for delegation
* @param delegateSignature Signature for delegation
* @return order The created ITermMaxOrder instance
* @return gtId The ID of the minted GT token
*/
function placeOrderForV2(
ITermMaxMarket market,
uint256 salt,
uint256 collateralToMintGt,
uint256 debtTokenToDeposit,
uint128 ftToDeposit,
uint128 xtToDeposit,
OrderInitialParams memory initialParams,
DelegateAble.DelegateParameters memory delegateParams,
DelegateAble.Signature memory delegateSignature
) external returns (ITermMaxOrder, uint256) {
(IERC20 ft, IERC20 xt, IGearingToken gt, address collateral, IERC20 debtToken) = market.tokens();
if (collateralToMintGt > 0) {
IERC20(collateral).safeTransferFrom(msg.sender, address(this), collateralToMintGt);
IERC20(collateral).safeIncreaseAllowance(address(gt), collateralToMintGt);
(initialParams.orderConfig.gtId,) = market.issueFt(initialParams.maker, 0, abi.encode(collateralToMintGt));
}
ITermMaxOrder order = ITermMaxMarketV2(address(market)).createOrder(initialParams, salt);
if (delegateParams.delegator != address(0)) {
require(
delegateParams.delegatee == address(order), MakerHelperErrors.OrderAddressIsDifferentFromDelegatee()
);
DelegateAble(address(gt)).setDelegateWithSignature(delegateParams, delegateSignature);
}
if (debtTokenToDeposit > 0) {
debtToken.safeTransferFrom(msg.sender, address(this), debtTokenToDeposit);
if (initialParams.pool != IERC4626(address(0))) {
debtToken.safeIncreaseAllowance(address(initialParams.pool), debtTokenToDeposit);
// if the order has a pool, we need to deposit the debt token to the pool
initialParams.pool.deposit(debtTokenToDeposit, address(order));
} else {
// if the order does not have a pool, we need to mint the ft/xt token directly
debtToken.safeIncreaseAllowance(address(market), debtTokenToDeposit);
market.mint(address(order), debtTokenToDeposit);
}
}
ft.safeTransferFrom(msg.sender, address(order), ftToDeposit);
xt.safeTransferFrom(msg.sender, address(order), xtToDeposit);
emit MakerHelperEvents.OrderPlaced(
initialParams.maker,
address(market),
address(order),
initialParams.orderConfig.gtId,
debtTokenToDeposit,
ftToDeposit,
xtToDeposit
);
return (order, initialParams.orderConfig.gtId);
}
function mint(ITermMaxMarket market, address recipient, uint256 debtTokenToDeposit) external {
(,,,, IERC20 debtToken) = market.tokens();
debtToken.safeTransferFrom(msg.sender, address(this), debtTokenToDeposit);
debtToken.safeIncreaseAllowance(address(market), debtTokenToDeposit);
market.mint(recipient, debtTokenToDeposit);
emit MakerHelperEvents.MintTokens(address(market), recipient, debtTokenToDeposit);
}
function burn(ITermMaxMarket market, address recipient, uint256 amount) external {
(IERC20 ft, IERC20 xt,,,) = market.tokens();
ft.safeTransferFrom(msg.sender, address(this), amount);
ft.safeIncreaseAllowance(address(market), amount);
xt.safeTransferFrom(msg.sender, address(this), amount);
xt.safeIncreaseAllowance(address(market), amount);
market.burn(recipient, amount);
emit MakerHelperEvents.BurnTokens(address(market), recipient, amount);
}
function onERC721Received(address, address, uint256, bytes memory) external pure override returns (bytes4) {
return this.onERC721Received.selector;
}
}
"
},
"dependencies/@openzeppelin-contracts-5.2.0/token/ERC20/IERC20.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
"
},
"dependencies/@openzeppelin-contracts-5.2.0/interfaces/IERC4626.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC4626.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";
/**
* @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in
* https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
*/
interface IERC4626 is IERC20, IERC20Metadata {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}
"
},
"dependencies/@openzeppelin-contracts-5.2.0/interfaces/IERC721Receiver.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721Receiver.sol)
pragma solidity ^0.8.20;
import {IERC721Receiver} from "../token/ERC721/IERC721Receiver.sol";
"
},
"dependencies/@openzeppelin-contracts-upgradeable-5.2.0/proxy/utils/UUPSUpgradeable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.22;
import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol";
import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol";
import {Initializable} from "./Initializable.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*/
abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address private immutable __self = address(this);
/**
* @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`
* and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,
* while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.
* If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must
* be the empty byte string if no function should be called, making it impossible to invoke the `receive` function
* during an upgrade.
*/
string public constant UPGRADE_INTERFACE_VERSION = "5.0.0";
/**
* @dev The call is from an unauthorized context.
*/
error UUPSUnauthorizedCallContext();
/**
* @dev The storage `slot` is unsupported as a UUID.
*/
error UUPSUnsupportedProxiableUUID(bytes32 slot);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
_checkProxy();
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
_checkNotDelegated();
_;
}
function __UUPSUpgradeable_init() internal onlyInitializing {
}
function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
}
/**
* @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual notDelegated returns (bytes32) {
return ERC1967Utils.IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data);
}
/**
* @dev Reverts if the execution is not performed via delegatecall or the execution
* context is not of a proxy with an ERC-1967 compliant implementation pointing to self.
* See {_onlyProxy}.
*/
function _checkProxy() internal view virtual {
if (
address(this) == __self || // Must be called through delegatecall
ERC1967Utils.getImplementation() != __self // Must be called through an active proxy
) {
revert UUPSUnauthorizedCallContext();
}
}
/**
* @dev Reverts if the execution is performed via delegatecall.
* See {notDelegated}.
*/
function _checkNotDelegated() internal view virtual {
if (address(this) != __self) {
// Must not be called through delegatecall
revert UUPSUnauthorizedCallContext();
}
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
/**
* @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.
*
* As a security check, {proxiableUUID} is invoked in the new implementation, and the return value
* is expected to be the implementation slot in ERC-1967.
*
* Emits an {IERC1967-Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {
revert UUPSUnsupportedProxiableUUID(slot);
}
ERC1967Utils.upgradeToAndCall(newImplementation, data);
} catch {
// The implementation is not UUPS
revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);
}
}
}
"
},
"dependencies/@openzeppelin-contracts-upgradeable-5.2.0/access/Ownable2StepUpgradeable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.20;
import {OwnableUpgradeable} from "./OwnableUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* This extension of the {Ownable} contract includes a two-step mechanism to transfer
* ownership, where the new owner must call {acceptOwnership} in order to replace the
* old one. This can help prevent common mistakes, such as transfers of ownership to
* incorrect accounts, or to contracts that are unable to interact with the
* permission system.
*
* The initial owner is specified at deployment time in the constructor for `Ownable`. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {
/// @custom:storage-location erc7201:openzeppelin.storage.Ownable2Step
struct Ownable2StepStorage {
address _pendingOwner;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable2Step")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant Ownable2StepStorageLocation = 0x237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00;
function _getOwnable2StepStorage() private pure returns (Ownable2StepStorage storage $) {
assembly {
$.slot := Ownable2StepStorageLocation
}
}
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
function __Ownable2Step_init() internal onlyInitializing {
}
function __Ownable2Step_init_unchained() internal onlyInitializing {
}
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
Ownable2StepStorage storage $ = _getOwnable2StepStorage();
return $._pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*
* Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
Ownable2StepStorage storage $ = _getOwnable2StepStorage();
$._pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
Ownable2StepStorage storage $ = _getOwnable2StepStorage();
delete $._pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
if (pendingOwner() != sender) {
revert OwnableUnauthorizedAccount(sender);
}
_transferOwnership(sender);
}
}
"
},
"contracts/v1/ITermMaxMarket.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IMintableERC20, IERC20} from "./tokens/IMintableERC20.sol";
import {IGearingToken} from "./tokens/IGearingToken.sol";
import {ITermMaxOrder} from "./ITermMaxOrder.sol";
import {MarketConfig, MarketInitialParams, CurveCuts, FeeConfig} from "./storage/TermMaxStorage.sol";
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
import {ISwapCallback} from "./ISwapCallback.sol";
/**
* @title TermMax Market interface
* @author Term Structure Labs
*/
interface ITermMaxMarket {
/// @notice Initialize the token and configuration of the market
function initialize(MarketInitialParams memory params) external;
/// @notice Return the configuration
function config() external view returns (MarketConfig memory);
/// @notice Set the market configuration
function updateMarketConfig(MarketConfig calldata newConfig) external;
/// @notice Return the tokens in TermMax Market
/// @return ft Fixed-rate Token(bond token). Earning Fixed Income with High Certainty
/// @return xt Intermediary Token for Collateralization and Leveragin
/// @return gt Gearing Token
/// @return collateral Collateral token
/// @return underlying Underlying Token(debt)
function tokens()
external
view
returns (IMintableERC20 ft, IMintableERC20 xt, IGearingToken gt, address collateral, IERC20 underlying);
/// @notice Mint FT and XT tokens by underlying token.
/// No price slippage or handling fees.
/// @param debtTokenAmt Amount of underlying token want to lock
function mint(address recipient, uint256 debtTokenAmt) external;
/// @notice Burn FT and XT to get underlying token.
/// No price slippage or handling fees.
/// @param debtTokenAmt Amount of underlying token want to get
function burn(address recipient, uint256 debtTokenAmt) external;
/// @notice Using collateral to issue FT tokens.
/// Caller will get FT(bond) tokens equal to the debt amount subtract issue fee
/// @param debt The amount of debt, unit by underlying token
/// @param collateralData The encoded data of collateral
/// @return gtId The id of Gearing Token
///
function issueFt(address recipient, uint128 debt, bytes calldata collateralData)
external
returns (uint256 gtId, uint128 ftOutAmt);
/// @notice Return the issue fee ratio
function mintGtFeeRatio() external view returns (uint256);
/// @notice Using collateral to issue FT tokens.
/// Caller will get FT(bond) tokens equal to the debt amount subtract issue fee
/// @param recipient Who will receive Gearing Token
/// @param debt The amount of debt, unit by underlying token
/// @param gtId The id of Gearing Token
/// @return ftOutAmt The amount of FT issued
///
function issueFtByExistedGt(address recipient, uint128 debt, uint256 gtId) external returns (uint128 ftOutAmt);
/// @notice Flash loan underlying token for leverage
/// @param recipient Who will receive Gearing Token
/// @param xtAmt The amount of XT token.
/// The caller will receive an equal amount of underlying token by flash loan.
/// @param callbackData The data of flash loan callback
/// @return gtId The id of Gearing Token
function leverageByXt(address recipient, uint128 xtAmt, bytes calldata callbackData)
external
returns (uint256 gtId);
/// @notice Preview the redeem amount and delivery data
/// @param ftAmount The amount of FT want to redeem
/// @return debtTokenAmt The amount of debt token
/// @return deliveryData The delivery data
function previewRedeem(uint256 ftAmount) external view returns (uint256 debtTokenAmt, bytes memory deliveryData);
/// @notice Redeem underlying tokens after maturity
/// @param ftAmount The amount of FT want to redeem
/// @param recipient Who will receive the underlying tokens
/// @return debtTokenAmt The amount of debt token
/// @return deliveryData The delivery data
function redeem(uint256 ftAmount, address recipient)
external
returns (uint256 debtTokenAmt, bytes memory deliveryData);
/// @notice Set the configuration of Gearing Token
function updateGtConfig(bytes memory configData) external;
/// @notice Set the fee rate of order
function updateOrderFeeRate(ITermMaxOrder order, FeeConfig memory newFeeConfig) external;
/// @notice Create a new order
function createOrder(address maker, uint256 maxXtReserve, ISwapCallback swapTrigger, CurveCuts memory curveCuts)
external
returns (ITermMaxOrder order);
}
"
},
"contracts/v2/ITermMaxMarketV2.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {OrderConfig} from "../v1/storage/TermMaxStorage.sol";
import {ITermMaxOrder} from "../v1/ITermMaxOrder.sol";
import {OrderInitialParams} from "./storage/TermMaxStorageV2.sol";
/**
* @title TermMax Market V2 interface
* @author Term Structure Labs
* @notice Interface for TermMax V2 markets with enhanced functionality over V1
* @dev Extends the base market functionality with additional features for better user experience
*/
interface ITermMaxMarketV2 {
/**
* @notice Returns the human-readable name of the market
* @dev Used for identification and display purposes in V2 markets
* @return The name string of the market (e.g., "Termmax Market:USDC-24-Dec")
*/
function name() external view returns (string memory);
/**
* @notice Burns FT and XT tokens on behalf of an owner to redeem underlying tokens
* @dev V2 enhancement allowing third-party burning with proper authorization
* @param owner The address that owns the tokens to be burned
* @param recipient The address that will receive the redeemed underlying tokens
* @param debtTokenAmt The amount of debt tokens (FT/XT pairs) to burn
*/
function burn(address owner, address recipient, uint256 debtTokenAmt) external;
/**
* @notice Creates a leveraged position using XT tokens from a specified owner
* @dev V2 enhancement allowing leverage creation on behalf of another address
* @param xtOwner The address that owns the XT tokens to be used for leverage
* @param recipient The address that will receive the generated GT (Gearing Token)
* @param xtAmt The amount of XT tokens to use for creating the leveraged position
* @param callbackData Encoded data passed to the flash loan callback for collateral handling
* @return gtId The ID of the newly minted Gearing Token representing the leveraged position
*/
function leverageByXt(address xtOwner, address recipient, uint128 xtAmt, bytes calldata callbackData)
external
returns (uint256 gtId);
/**
* @notice Redeems FT tokens on behalf of an owner after market maturity
* @dev V2 enhancement allowing third-party redemption with proper authorization
* @param ftOwner The address that owns the FT tokens to be redeemed
* @param recipient The address that will receive the redeemed assets
* @param ftAmount The amount of FT tokens to redeem
* @return debtTokenAmt The amount of underlying debt tokens received
* @return deliveryData Encoded data containing collateral delivery information
*/
function redeem(address ftOwner, address recipient, uint256 ftAmount) external returns (uint256, bytes memory);
/**
* @notice Creates a new TermMax order with default parameters
* @dev Uses CREATE to deploy the order contract at a non-deterministic address
*/
function createOrder(OrderInitialParams memory params) external returns (ITermMaxOrder order);
/**
* @notice Creates a new TermMax order with a unique salt for address uniqueness
* @dev Uses CREATE2 to deploy the order contract at a deterministic address based on the salt
*/
function createOrder(OrderInitialParams memory params, uint256 salt) external returns (ITermMaxOrder order);
/**
* @notice Predict the address of a TermMax order that would be created with given parameters and salt
* @dev Computes the address using CREATE2 without actually deploying the contract
*/
function predictOrderAddress(OrderInitialParams memory params, uint256 salt)
external
view
returns (address orderAddress);
}
"
},
"contracts/v1/ITermMaxOrder.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;
import {IMintableERC20, IERC20} from "./tokens/IMintableERC20.sol";
import {IGearingToken} from "./tokens/IGearingToken.sol";
import {ITermMaxMarket} from "./ITermMaxMarket.sol";
import {OrderConfig, MarketConfig, CurveCuts, FeeConfig} from "./storage/TermMaxStorage.sol";
import {ISwapCallback} from "./ISwapCallback.sol";
/**
* @title TermMax Order interface
* @author Term Structure Labs
*/
interface ITermMaxOrder {
/// @notice Initialize the token and configuration of the order
/// @param maker The maker
/// @param tokens The tokens
/// @param gt The Gearing Token
/// @param maxXtReserve The maximum reserve of XT token
/// @param curveCuts The curve cuts
/// @param marketConfig The market configuration
/// @dev Only factory will call this function once when deploying new market
function initialize(
address maker,
IERC20[3] memory tokens,
IGearingToken gt,
uint256 maxXtReserve,
ISwapCallback trigger,
CurveCuts memory curveCuts,
MarketConfig memory marketConfig
) external;
/// @notice Return the configuration
function orderConfig() external view returns (OrderConfig memory);
/// @notice Return the maker
function maker() external view returns (address);
/// @notice Set the market configuration
/// @param newOrderConfig New order configuration
/// @param ftChangeAmt Change amount of FT reserve
/// @param xtChangeAmt Change amount of XT reserve
function updateOrder(OrderConfig memory newOrderConfig, int256 ftChangeAmt, int256 xtChangeAmt) external;
function withdrawAssets(IERC20 token, address recipient, uint256 amount) external;
function updateFeeConfig(FeeConfig memory newFeeConfig) external;
/// @notice Return the token reserves
function tokenReserves() external view returns (uint256 ftReserve, uint256 xtReserve);
/// @notice Return the tokens in TermMax Market
/// @return market The market
function market() external view returns (ITermMaxMarket market);
/// @notice Return the current apr of the amm order book
/// @return lendApr Lend APR
/// @return borrowApr Borrow APR
function apr() external view returns (uint256 lendApr, uint256 borrowApr);
/// @notice Swap exact token to token
/// @param tokenIn The token want to swap
/// @param tokenOut The token want to receive
/// @param recipient Who receive output tokens
/// @param tokenAmtIn The number of tokenIn tokens input
/// @param minTokenOut Minimum number of tokenOut token outputs required
/// @param deadline The timestamp after which the transaction will revert
/// @return netOut The actual number of tokenOut tokens received
function swapExactTokenToToken(
IERC20 tokenIn,
IERC20 tokenOut,
address recipient,
uint128 tokenAmtIn,
uint128 minTokenOut,
uint256 deadline
) external returns (uint256 netOut);
/// @notice Swap token to exact token
/// @param tokenIn The token want to swap
/// @param tokenOut The token want to receive
/// @param recipient Who receive output tokens
/// @param tokenAmtOut The number of tokenOut tokens output
/// @param maxTokenIn Maximum number of tokenIn token inputs required
/// @param deadline The timestamp after which the transaction will revert
/// @return netIn The actual number of tokenIn tokens input
function swapTokenToExactToken(
IERC20 tokenIn,
IERC20 tokenOut,
address recipient,
uint128 tokenAmtOut,
uint128 maxTokenIn,
uint256 deadline
) external returns (uint256 netIn);
/// @notice Suspension of market trading
function pause() external;
/// @notice Open Market Trading
function unpause() external;
}
"
},
"contracts/v2/lib/TransferUtilsV2.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
library TransferUtilsV2 {
using SafeERC20 for IERC20;
error CanNotTransferUintMax();
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
token.safeTransferFrom(from, to, value);
}
function safeTransfer(IERC20 token, address to, uint256 value) internal {
token.safeTransfer(to, value);
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
token.safeIncreaseAllowance(spender, value);
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
if (value == 0 || spender == address(this)) {
return;
}
token.safeDecreaseAllowance(spender, value);
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
token.forceApprove(spender, value);
}
function safeTransferFromWithCheck(IERC20 token, address from, address to, uint256 value) internal {
if (from == to || value == 0) {
return;
}
token.safeTransferFrom(from, to, value);
}
function safeTransferWithCheck(IERC20 token, address to, uint256 value) internal {
if (to == address(this) || value == 0) {
return;
}
token.safeTransfer(to, value);
}
function safeIncreaseAllowanceWithCheck(IERC20 token, address spender, uint256 value) internal {
if (value == 0 || spender == address(this)) {
return;
}
token.safeIncreaseAllowance(spender, value);
}
function safeDecreaseAllowanceWithCheck(IERC20 token, address spender, uint256 value) internal {
if (value == 0 || spender == address(this)) {
return;
}
token.safeDecreaseAllowance(spender, value);
}
function forceApproveWithCheck(IERC20 token, address spender, uint256 value) internal {
if (spender == address(this)) {
return;
}
token.forceApprove(spender, value);
}
}
"
},
"contracts/v1/tokens/IGearingToken.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;
import {IERC20Metadata, IERC20} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {IERC721Enumerable} from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import {GtConfig} from "../storage/TermMaxStorage.sol";
/**
* @title TermMax Gearing token interface
* @author Term Structure Labs
*/
interface IGearingToken is IERC721Enumerable {
// @notice Initial function
/// @param name The token's name
/// @param symbol The token's symbol
/// @param config Configuration of GT
/// @param initalParams The initilization parameters of implementation
function initialize(string memory name, string memory symbol, GtConfig memory config, bytes memory initalParams)
external;
/// @notice Set the treasurer address
/// @param treasurer New address of treasurer
/// @dev Only the market can call this function
function setTreasurer(address treasurer) external;
/// @notice Set the configuration of Gearing Token
function updateConfig(bytes memory configData) external;
/// @notice Return the configuration of Gearing Token
function getGtConfig() external view returns (GtConfig memory);
/// @notice Return the flag to indicate debt is liquidatable or not
function liquidatable() external view returns (bool);
/// @notice Return the market address
function marketAddr() external view returns (address);
/// @notice Mint this token to an address
/// @param collateralProvider Who provide collateral token
/// @param to The address receiving token
/// @param debtAmt The amount of debt, unit by debtToken token
/// @param collateralData The encoded data of collateral
/// @return id The id of Gearing Token
/// @dev Only the market can mint Gearing Token
function mint(address collateralProvider, address to, uint128 debtAmt, bytes memory collateralData)
external
returns (uint256 id);
/// @notice Augment the debt of Gearing Token
/// @param id The id of Gearing Token
/// @param ftAmt The amount of debt, unit by debtToken token
function augmentDebt(address caller, uint256 id, uint256 ftAmt) external;
/// @notice Return the loan information of Gearing Token
/// @param id The id of Gearing Token
/// @return owner The owner of Gearing Token
/// @return debtAmt The amount of debt, unit by debtToken token
/// @return collateralData The encoded data of collateral
function loanInfo(uint256 id) external view returns (address owner, uint128 debtAmt, bytes memory collateralData);
/// @notice Merge multiple Gearing Tokens into one
/// @param ids The array of Gearing Tokens to be merged
/// @return newId The id of new Gearing Token
function merge(uint256[] memory ids) external returns (uint256 newId);
/// @notice Repay the debt of Gearing Token.
/// If repay amount equals the debt amount, Gearing Token's owner will get his collateral.
/// @param id The id of Gearing Token
/// @param repayAmt The amount of debt you want to repay
/// @param byDebtToken Repay using debtToken token or bonds token
function repay(uint256 id, uint128 repayAmt, bool byDebtToken) external;
/// @notice Repay the debt of Gearing Token,
/// the collateral will send by flashloan first.
/// @param id The id of Gearing Token
/// @param byDebtToken Repay using debtToken token or bonds token
function flashRepay(uint256 id, bool byDebtToken, bytes calldata callbackData) external;
/// @notice Remove collateral from the loan.
/// Require the loan to value bigger than maxLtv after this action.
/// @param id The id of Gearing Token
/// @param collateralData Collateral data to be removed
function removeCollateral(uint256 id, bytes memory collateralData) external;
/// @notice Add collateral to the loan
/// @param id The id of Gearing Token
/// @param collateralData Collateral data to be added
function addCollateral(uint256 id, bytes memory collateralData) external;
/// @notice Return the liquidation info of the loan
/// @param id The id of the G-token
/// @return isLiquidable Whether the loan is liquidable
/// @return ltv The loan to collateral
/// @return maxRepayAmt The maximum amount of the debt to be repaid
function getLiquidationInfo(uint256 id)
external
view
returns (bool isLiquidable, uint128 ltv, uint128 maxRepayAmt);
/// @notice Liquidate the loan when its ltv bigger than liquidationLtv or expired.
/// The ltv can not inscrease after liquidation.
/// A maximum of 10% of the repayment amount of collateral is given as a
/// reward to the protocol and liquidator,
/// The proportion of collateral liquidated will not exceed the debt liquidation ratio.
/// @param id The id of the G-token
/// @param repayAmt The amount of the debt to be liquidate
/// @param byDebtToken Repay using debtToken token or bonds token
function liquidate(uint256 id, uint128 repayAmt, bool byDebtToken) external;
/// @notice Preview the delivery data
/// @param proportion The proportion of collateral that should be obtained
/// @return deliveryData The delivery data
function previewDelivery(uint256 proportion) external view returns (bytes memory deliveryData);
/// @notice Deilivery outstanding debts after maturity
/// @param proportion The proportion of collateral that should be obtained
/// @param to The address receiving collateral token
/// @dev Only the market can delivery collateral
function delivery(uint256 proportion, address to) external returns (bytes memory deliveryData);
/// @notice Return the value of collateral in USD with base decimals
/// @param collateralData encoded collateral data
/// @return collateralValue collateral's value in USD
function getCollateralValue(bytes memory collateralData) external view returns (uint256 collateralValue);
}
"
},
"contracts/v1/storage/TermMaxStorage.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IOracle} from "../oracle/IOracle.sol";
import {ISwapCallback} from "../ISwapCallback.sol";
/**
* @title The data struct of token pair
* @author Term Structure Labs
*/
struct CurveCut {
uint256 xtReserve;
uint256 liqSquare;
int256 offset;
}
struct FeeConfig {
/// @notice The lending fee ratio taker
/// i.e. 0.01e8 means 1%
uint32 lendTakerFeeRatio;
/// @notice The lending fee ratio for maker
/// i.e. 0.01e8 means 1%
uint32 lendMakerFeeRatio;
/// @notice The borrowing fee ratio for taker
/// i.e. 0.01e8 means 1%
uint32 borrowTakerFeeRatio;
/// @notice The borrowing fee ratio for maker
/// i.e. 0.01e8 means 1%
uint32 borrowMakerFeeRatio;
/// @notice The fee ratio when minting GT tokens by collateral
/// i.e. 0.01e8 means 1%
uint32 mintGtFeeRatio;
/// @notice The fee ref when minting GT tokens by collateral
/// i.e. 0.01e8 means 1%
uint32 mintGtFeeRef;
}
struct CurveCuts {
/// @notice The curve cuts of the market to lend
CurveCut[] lendCurveCuts;
/// @notice The curve cuts of the market to borrow
CurveCut[] borrowCurveCuts;
}
struct MarketConfig {
/// @notice The treasurer's address, which will receive protocol fee
address treasurer;
/// @notice The unix time of maturity date
uint64 maturity;
/// @notice The fee ratio when tradings with the market and orders
FeeConfig feeConfig;
}
struct LoanConfig {
/// @notice The oracle aggregator
IOracle oracle;
/// @notice The debt liquidation threshold
/// If the loan to collateral is greater than or equal to this value,
/// it will be liquidated
/// i.e. 0.9e8 means debt value is the 90% of collateral value
uint32 liquidationLtv;
/// @notice Maximum loan to collateral when borrowing
/// i.e. 0.85e8 means debt value is the 85% of collateral value
uint32 maxLtv;
/// @notice The flag to indicate debt is liquidatable or not
/// @dev If liquidatable is false, the collateral can only be delivered after maturity
bool liquidatable;
}
/// @notice Data of Gearing Token's configuturation
struct GtConfig {
/// @notice The address of collateral token
address collateral;
/// @notice The debtToken(debt) token
IERC20Metadata debtToken;
/// @notice The bond token
IERC20 ft;
/// @notice The treasurer's address, which will receive protocol reward while liquidation
address treasurer;
/// @notice The unix time of maturity date
uint64 maturity;
/// @notice The configuration of oracle, ltv and liquidation
LoanConfig loanConfig;
}
struct OrderConfig {
CurveCuts curveCuts;
uint256 gtId;
uint256 maxXtReserve;
ISwapCallback swapTrigger;
FeeConfig feeConfig;
}
struct MarketInitialParams {
/// @notice The address of collateral token
address collateral;
/// @notice The debtToken(debt) token
IERC20Metadata debtToken;
/// @notice The admin address
address admin;
/// @notice The implementation of TermMax Gearing Token contract
address gtImplementation;
/// @notice The configuration of market
MarketConfig marketConfig;
/// @notice The configuration of loan
LoanConfig loanConfig;
/// @notice The encoded parameters to initialize GT implementation contract
bytes gtInitalParams;
string tokenName;
string tokenSymbol;
}
struct VaultInitialParams {
address admin;
address curator;
uint256 timelock;
IERC20 asset;
uint256 maxCapacity;
string name;
string symbol;
uint64 performanceFeeRate;
}
"
},
"contracts/v2/ITermMaxOrderV2.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IERC20} from "../v1/tokens/IMintableERC20.sol";
import {OrderInitialParams} from "./storage/TermMaxStorageV2.sol";
import {ISwapCallback} from "../v1/ISwapCallback.sol";
import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import {CurveCuts} from "../v1/storage/TermMaxStorage.sol";
/**
* @title TermMax Order interface v2
* @author Term Structure Labs
* @notice The V2 Order use vitual xt reserve to present the current price,
* which is different from V1 Order that uses real xt reserve.
* You have to set the virtual xt reserve to set an initialize price.
*/
interface ITermMaxOrderV2 {
/// @notice Initialize the token and configuration of the order (V2 version)
function initialize(OrderInitialParams memory params) external;
// =============================================================================
// V2-SPECIFIC VIEW FUNCTIONS
// =============================================================================
/// @notice Get the pool address set for the order
function pool() external view returns (IERC4626);
/// @notice Get the virtual XT reserve, which is used to present the current price
function virtualXtReserve() external view returns (uint256);
/// @notice Get real reserves including assets in pool
function getRealReserves() external view returns (uint256 ftReserve, uint256 xtReserve);
// =============================================================================
// V2-SPECIFIC ADMIN FUNCTIONS
// =============================================================================
/// @notice Set curve and price configuration
/// @param originalVirtualXtReserve The original virtual reserve of XT token, which is used to prevent price manipulation
/// @param virtualXtReserve The virtual reserve of XT token, which presents the current price
/// @param maxXtReserve The maximum reserve of XT token
/// @param newCurveCuts The new curve configuration parameters
function setCurveAndPrice(
uint256 originalVirtualXtReserve,
uint256 virtualXtReserve,
uint256 maxXtReserve,
CurveCuts memory newCurveCuts
) external;
/// @notice Set general configuration parameters
/// @param gtId The ID of the Gearing Token, which is used to borrow tokens
/// @param swapTrigger The callback contract to trigger swaps
function setGeneralConfig(uint256 gtId, ISwapCallback swapTrigger) external;
/// @notice Set the staking pool
/// @param newPool The new staking pool to be set, the address(0) can be used to unset the pool
function setPool(IERC4626 newPool) external;
// =============================================================================
// V2-SPECIFIC LIQUIDITY MANAGEMENT FUNCTIONS
// =============================================================================
/// @notice Add liquidity to the order
/// @notice If you want to add liquidity by ft or xt, please transfer them to the order directly.
/// @param asset The asset to be added as liquidity, debt token or pool shares
/// @param amount The amount of the asset to be added
function addLiquidity(IERC20 asset, uint256 amount) external;
/// @notice Remove liquidity from the order
/// @param asset The asset to be removed as liquidity, debt token or pool shares
/// @param amount The amount of the asset to be removed
/// @param recipient The address to receive the removed liquidity
function removeLiquidity(IERC20 asset, uint256 amount, address recipient) external;
/// @notice Redeem all assets and close the order, must be called after the maturity + liquidation period
/// @param recipient The address to receive the redeemed assets
/// @return badDebt The amount of bad debt incurred during the redemption
/// @return deliveryData Additional data returned from the redemption process
/// @dev You have to withdraw the delivery collateral manually if the asset is a pool share.
/// @dev This function will close the order and transfer all assets to the recipient.
function redeemAll(address recipient) external returns (uint256 badDebt, bytes memory deliveryData);
/// @notice Withdraw all assets before maturity, only callable by the owner
/// @param recipient The address to receive the withdrawn assets
/// @return debtTokenAmount The amount of debt tokens withdrawn
/// @return ftAmount The amount of FT tokens withdrawn
/// @retur
Submitted on: 2025-10-01 13:35:26
Comments
Log in to comment.
No comments yet.