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/access/AccessManagerV2.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;
import "../../v1/access/AccessManager.sol";
import {IOracleV2} from "../oracle/IOracleV2.sol";
import {ITermMaxVaultV2, OrderV2ConfigurationParams, CurveCuts} from "../vault/ITermMaxVaultV2.sol";
import {IWhitelistManager} from "./IWhitelistManager.sol";
import {VersionV2} from "../VersionV2.sol";
/**
* @title TermMax Access Manager V2
* @author Term Structure Labs
* @notice Extended access manager for TermMax V2 protocol with additional oracle and batch operations
* @dev Inherits from AccessManager V1 and adds V2-specific functionality for managing oracles and batch operations
*/
contract AccessManagerV2 is AccessManager, VersionV2 {
error CannotRenounceRole();
/// @notice Role to manage whitelist
bytes32 public constant WHITELIST_ROLE = keccak256("WHITELIST_ROLE");
/// @notice Role to upgrade contracts
bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE");
function upgradeSubContract(UUPSUpgradeable proxy, address newImplementation, bytes memory data)
external
override
onlyRole(UPGRADER_ROLE)
{
proxy.upgradeToAndCall(newImplementation, data);
}
function batchSetWhitelist(
IWhitelistManager whitelistManager,
address[] calldata contractAddresses,
IWhitelistManager.ContractModule module,
bool approved
) external onlyRole(WHITELIST_ROLE) {
whitelistManager.batchSetWhitelist(contractAddresses, module, approved);
}
/**
* @notice Batch pause/unpause multiple entities in a single transaction
* @dev Allows efficient management of multiple pausable contracts simultaneously
* @param entities Array of IPausable contracts to pause/unpause
* @param state True to unpause entities, false to pause them
* @custom:access Requires PAUSER_ROLE
* @custom:gas-optimization Uses a simple loop for batch operations
*/
function batchSetSwitch(IPausable[] calldata entities, bool state) external onlyRole(PAUSER_ROLE) {
if (state) {
for (uint256 i = 0; i < entities.length; ++i) {
entities[i].unpause();
}
} else {
for (uint256 i = 0; i < entities.length; ++i) {
entities[i].pause();
}
}
}
/**
* @notice Submit a pending oracle configuration for a specific asset
* @dev Allows oracle managers to propose new oracle configurations that can be activated later
* @param aggregator The oracle aggregator contract to submit the pending oracle to
* @param asset The asset address for which the oracle is being configured
* @param oracle The oracle configuration structure containing price feed details
* @custom:access Requires ORACLE_ROLE
* @custom:security Oracle updates go through a pending mechanism for security
*/
function submitPendingOracle(IOracleV2 aggregator, address asset, IOracleV2.Oracle memory oracle)
external
onlyRole(ORACLE_ROLE)
{
aggregator.submitPendingOracle(asset, oracle);
}
/**
* @notice Revoke a pending oracle configuration for a specific asset
* @dev Allows oracle managers to cancel pending oracle updates before they are activated
* @param aggregator The oracle aggregator contract to revoke the pending oracle from
* @param asset The asset address for which the pending oracle should be revoked
* @custom:access Requires ORACLE_ROLE
* @custom:security Provides a way to cancel erroneous oracle submissions
*/
function revokePendingOracle(IOracleV2 aggregator, address asset) external onlyRole(ORACLE_ROLE) {
aggregator.revokePendingOracle(asset);
}
/**
* @notice Revoke a pending minimum APY change for the vault
* @param vault The TermMax vault contract to update
* @custom:access Requires VAULT_ROLE
* @custom:security Allows governance to cancel proposed changes before they take effect
*/
function revokePendingMinApy(ITermMaxVaultV2 vault) external onlyRole(VAULT_ROLE) {
vault.revokePendingMinApy();
}
/**
* @notice Revoke a pending pool change for the vault
* @param vault The TermMax vault contract to update
* @custom:access Requires VAULT_ROLE
* @custom:security Allows governance to abort pool changes before they take effect
*/
function revokePendingPool(ITermMaxVaultV2 vault) external onlyRole(VAULT_ROLE) {
vault.revokePendingPool();
}
/// @notice Forbid renouncing roles
function renounceRole(bytes32 role, address callerConfirmation) public override {
revert CannotRenounceRole();
}
}
"
},
"contracts/v1/access/AccessManager.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;
import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {ITermMaxMarket} from "../ITermMaxMarket.sol";
import {ITermMaxFactory} from "../factory/ITermMaxFactory.sol";
import {ITermMaxRouter} from "../router/ITermMaxRouter.sol";
import {ITermMaxOrder} from "../ITermMaxOrder.sol";
import {IOracle} from "../oracle/IOracle.sol";
import {ITermMaxVault} from "../vault/ITermMaxVault.sol";
import {MarketConfig, FeeConfig, MarketInitialParams} from "../storage/TermMaxStorage.sol";
interface IOwnable {
function transferOwnership(address newOwner) external;
function acceptOwnership() external;
}
interface IPausable {
function pause() external;
function unpause() external;
}
/**
* @title TermMax Access Manager
* @author Term Structure Labs
*/
contract AccessManager is AccessControlUpgradeable, UUPSUpgradeable {
error CannotRevokeDefaultAdminRole();
/// @notice Role to manage switch
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
/// @notice Role to manage configuration items
bytes32 public constant CONFIGURATOR_ROLE = keccak256("CONFIGURATOR_ROLE");
/// @notice Role to manage vault
bytes32 public constant VAULT_ROLE = keccak256("VAULT_ROLE");
/// @notice Role to manage oracle
bytes32 public constant ORACLE_ROLE = keccak256("ORACLE_ROLE");
/// @notice Role to manage market
bytes32 public constant MARKET_ROLE = keccak256("MARKET_ROLE");
function initialize(address admin) public initializer {
__UUPSUpgradeable_init();
__AccessControl_init();
_grantRole(DEFAULT_ADMIN_ROLE, admin);
}
/// @notice Set GT implementation to the factory
function setGtImplement(ITermMaxFactory factory, string memory gtImplementName, address gtImplement)
external
onlyRole(MARKET_ROLE)
{
factory.setGtImplement(gtImplementName, gtImplement);
}
/// @notice Deploy a new market
function createMarket(
ITermMaxFactory factory,
bytes32 gtKey,
MarketInitialParams calldata deployParams,
uint256 salt
) external onlyRole(MARKET_ROLE) returns (address market) {
market = factory.createMarket(gtKey, deployParams, salt);
}
/// @notice Transfer ownable contract's ownership
function transferOwnership(IOwnable entity, address to) external onlyRole(DEFAULT_ADMIN_ROLE) {
entity.transferOwnership(to);
}
function acceptOwnership(IOwnable entity) external onlyRole(DEFAULT_ADMIN_ROLE) {
entity.acceptOwnership();
}
/// @notice Upgrade the target contract using UUPS
function upgradeSubContract(UUPSUpgradeable proxy, address newImplementation, bytes memory data)
external
virtual
onlyRole(DEFAULT_ADMIN_ROLE)
{
proxy.upgradeToAndCall(newImplementation, data);
}
/// @notice Set the adapter whitelist for router
function setAdapterWhitelist(ITermMaxRouter router, address adapter, bool isWhitelist)
external
onlyRole(MARKET_ROLE)
{
router.setAdapterWhitelist(adapter, isWhitelist);
}
function submitPendingOracle(IOracle aggregator, address asset, IOracle.Oracle memory oracle)
external
onlyRole(ORACLE_ROLE)
{
aggregator.submitPendingOracle(asset, oracle);
}
function acceptPendingOracle(IOracle aggregator, address asset) external onlyRole(ORACLE_ROLE) {
aggregator.acceptPendingOracle(asset);
}
/// @notice Update the market configuration
function updateMarketConfig(ITermMaxMarket market, MarketConfig calldata newConfig)
external
onlyRole(CONFIGURATOR_ROLE)
{
market.updateMarketConfig(newConfig);
}
/// @notice Set the configuration of Gearing Token
function updateGtConfig(ITermMaxMarket market, bytes memory configData) external onlyRole(CONFIGURATOR_ROLE) {
market.updateGtConfig(configData);
}
/// @notice Set the fee rate of an order
function updateOrderFeeRate(ITermMaxMarket market, ITermMaxOrder order, FeeConfig memory feeConfig)
external
onlyRole(CONFIGURATOR_ROLE)
{
market.updateOrderFeeRate(order, feeConfig);
}
/// @notice Set the switch of an entity
function setSwitch(IPausable entity, bool state) external onlyRole(PAUSER_ROLE) {
if (state) {
entity.unpause();
} else {
entity.pause();
}
}
function submitVaultGuardian(ITermMaxVault vault, address newGuardian) external onlyRole(VAULT_ROLE) {
vault.submitGuardian(newGuardian);
}
/// @notice Revoke a pending guardian for the vault
function revokeVaultPendingGuardian(ITermMaxVault vault) external onlyRole(VAULT_ROLE) {
vault.revokePendingGuardian();
}
/// @notice Revoke a pending timelock for the vault
function revokeVaultPendingTimelock(ITermMaxVault vault) external onlyRole(VAULT_ROLE) {
vault.revokePendingTimelock();
}
/// @notice Revoke a pending market for the vault
function revokeVaultPendingMarket(ITermMaxVault vault, address market) external onlyRole(VAULT_ROLE) {
vault.revokePendingMarket(market);
}
/// @notice Set the curator for the vault, only admin role
function setCuratorForVault(ITermMaxVault vault, address newCurator) external onlyRole(VAULT_ROLE) {
vault.setCurator(newCurator);
}
/// @notice Set the allocator for the vault
function setIsAllocatorForVault(ITermMaxVault vault, address allocator, bool isAllocator)
external
onlyRole(VAULT_ROLE)
{
vault.setIsAllocator(allocator, isAllocator);
}
/// @notice Revoke role
/// @dev Can't revoke your own role
function revokeRole(bytes32 role, address account) public override onlyRole(getRoleAdmin(role)) {
if (msg.sender == account) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, account);
}
/// @notice Revoke role
/// @dev Can't revoke default admin role
function renounceRole(bytes32 role, address callerConfirmation) public virtual override {
if (role == DEFAULT_ADMIN_ROLE) {
revert CannotRevokeDefaultAdminRole();
}
_revokeRole(role, callerConfirmation);
}
function _authorizeUpgrade(address newImplementation) internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {}
}
"
},
"contracts/v2/oracle/IOracleV2.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
/**
* @title IOracleV2
* @author Term Structure Labs
* @notice Enhanced oracle interface for TermMax V2 protocol with improved price feed management
* @dev Extends the V1 oracle interface with additional features including price caps, separate backup heartbeats,
* and oracle revocation capabilities for enhanced security and flexibility
*/
interface IOracleV2 {
/**
* @notice Oracle configuration structure for price feed management
* @dev Contains primary and backup aggregators with independent heartbeat configurations
* @param aggregator Primary price feed aggregator (required)
* @param backupAggregator Secondary price feed aggregator for fallback (optional)
* @param maxPrice Maximum allowed price value for this asset (0 = no limit)
* @param minPrice Minimum allowed price value for this asset (0 = no limit)
* @param heartbeat Maximum allowed staleness for primary aggregator in seconds (0 = no staleness check)
* @param backupHeartbeat Maximum allowed staleness for backup aggregator in seconds (0 = no staleness check)
*/
struct Oracle {
AggregatorV3Interface aggregator;
AggregatorV3Interface backupAggregator;
int256 maxPrice;
int256 minPrice;
uint32 heartbeat;
uint32 backupHeartbeat;
}
/**
* @notice Error thrown when the oracle system cannot provide a reliable price
* @dev Occurs when both primary and backup oracles are stale, returning invalid data, or when no oracle is configured
* @param asset The address of the asset for which the oracle is not working
*/
error OracleIsNotWorking(address asset);
/**
* @notice Retrieves the current price of an asset in USD from the oracle system
* @dev Uses primary oracle first, falls back to backup if primary is stale or invalid
* Applies maxPrice cap if configured. Returns price with the aggregator's native decimals
* @param asset The address of the asset to get the price for
* @return price The current price of the asset (may be capped by maxPrice)
* @return decimals The number of decimal places in the returned price
* @custom:reverts OracleIsNotWorking if no valid price can be obtained
*/
function getPrice(address asset) external view returns (uint256 price, uint8 decimals);
/**
* @notice Submits a new oracle configuration for an asset with timelock protection
* @dev Creates a pending oracle update that must wait for the timelock period before activation
* Used for adding new oracles or updating existing ones with enhanced security
* @param asset The address of the asset to configure the oracle for
* @param oracle The oracle configuration structure with primary/backup feeds and settings
* @custom:access Typically restricted to oracle managers or governance
* @custom:security Subject to timelock delay for security
*/
function submitPendingOracle(address asset, Oracle memory oracle) external;
/**
* @notice Activates a previously submitted pending oracle configuration
* @dev Can only be called after the timelock period has elapsed since submission
* Replaces the current oracle configuration with the pending one
* @param asset The address of the asset to accept the pending oracle for
* @custom:access Usually callable by anyone after timelock expires
* @custom:validation Requires valid pending oracle and elapsed timelock
*/
function acceptPendingOracle(address asset) external;
/**
* @notice Cancels a pending oracle configuration before it can be accepted
* @dev Allows oracle managers to revoke pending updates if errors are discovered
* Can only revoke pending oracles that haven't been accepted yet
* @param asset The address of the asset to revoke the pending oracle for
* @custom:access Typically restricted to oracle managers or governance
* @custom:security Provides emergency mechanism to cancel erroneous oracle updates
*/
function revokePendingOracle(address asset) external;
}
"
},
"contracts/v2/vault/ITermMaxVaultV2.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import {PendingAddress, PendingUint192} from "../../v1/lib/PendingLib.sol";
import {VaultInitialParamsV2} from "../storage/TermMaxStorageV2.sol";
import {CurveCuts} from "../../v1/storage/TermMaxStorage.sol";
import {OrderV2ConfigurationParams} from "./VaultStorageV2.sol";
import {ITermMaxMarketV2} from "../ITermMaxMarketV2.sol";
import {ITermMaxOrderV2} from "../ITermMaxOrderV2.sol";
/**
* @title ITermMaxVaultV2
* @notice Interface for TermMax Vault V2 contract
* @dev This interface defines the core functionality for vault operations including:
* - Vault initialization and configuration
* - APY and idle fund rate management with timelock mechanism
* - Pool whitelist management with pending approval system
* - Order creation and management (curves, configuration, liquidity)
* - Integration with ERC4626 pools and TermMax markets
*
* The vault implements a timelock mechanism for critical parameter changes
* to ensure security and allow for community review of proposed changes.
*/
interface ITermMaxVaultV2 {
// ============================================
// INITIALIZATION
// ============================================
/**
* @notice Initializes the vault with the provided parameters
* @dev This function should only be called once during contract deployment.
* Sets up initial vault configuration including APY parameters, access controls,
* and initial pool configurations.
* @param params The initial configuration parameters for the vault including:
* - minApy: minimum guaranteed APY
* - minIdleFundRate: minimum rate for idle funds
* - governance and admin addresses
* - initial pool configurations
*/
function initialize(VaultInitialParamsV2 memory params) external;
// ============================================
// APY AND RATE QUERIES
// ============================================
/**
* @notice Returns the current annual percentage yield based on accreting principal
* @dev APY is calculated based on the vault's current performance and accruing interest.
* This is a dynamic value that reflects real-time vault performance.
* @return The current APY as a uint256 value (e.g., 5% APY = 0.05e8)
*/
function apy() external view returns (uint256);
/**
* @notice Returns the minimum guaranteed APY for the vault
* @dev This represents the floor APY that the vault aims to maintain.
* Changes to this value require timelock approval for security.
* @return The minimum APY as a uint64 value (e.g., 5% APY = 0.05e8)
*/
function minApy() external view returns (uint64);
// ============================================
// PENDING PARAMETER QUERIES
// ============================================
/**
* @notice Returns the pending minimum APY update details
* @dev Contains the proposed new value and timing information for the pending change.
* Used to track timelock status and proposed changes.
* @return PendingUint192 struct with pending minimum APY data, structure includes:
* - newValue: the proposed new minimum APY
* - validAt: the timestamp when the change becomes valid
* - isActive: whether there's an active pending change
*/
function pendingMinApy() external view returns (PendingUint192 memory);
/**
* @notice Returns the pending pool value
* @dev Contains the proposed new value and timing information for the pending change.
* Used to track timelock status and proposed changes.
* @return PendingAddress struct with pending pool data, structure includes:
* - newValue: the proposed new pool address
* - validAt: the timestamp when the change becomes valid
*/
function pendingPool() external view returns (PendingAddress memory);
// ============================================
// PARAMETER SUBMISSION (TIMELOCK INITIATION)
// ============================================
/**
* @notice Submits a new minimum APY for pending approval
* @dev Initiates a timelock period before the new minimum APY can be applied.
* Only authorized governance can call this function.
* @param newMinApy The proposed new minimum APY value (e.g., 5% APY = 0.05e8)
*/
function submitPendingMinApy(uint64 newMinApy) external;
/**
* @notice Submits a new pool for pending approval
* @dev Initiates a timelock period before the new pool can be used for earning yield.
* @param pool The address of the ERC4626 pool
*/
function submitPendingPool(address pool) external;
// ============================================
// PARAMETER ACCEPTANCE (TIMELOCK COMPLETION)
// ============================================
/**
* @notice Accepts and applies the pending minimum APY change
* @dev Can only be called after the timelock period has elapsed.
* Finalizes the APY change and updates the active minimum APY.
*/
function acceptPendingMinApy() external;
/**
* @notice
*/
function acceptPool() external;
/**
*
*/
function pool() external view returns (IERC4626);
// ============================================
// PARAMETER REVOCATION (TIMELOCK CANCELLATION)
// ============================================
/**
* @notice Revokes the pending minimum APY change
* @dev Cancels the pending change and resets the pending state.
* Allows governance to cancel proposed changes before they take effect.
*/
function revokePendingMinApy() external;
/**
* @notice Revokes a pending pool change
* @dev Cancels the pending change and resets the pending state.
* Allows governance to abort pool changes before they take effect.
*/
function revokePendingPool() external;
// ============================================
// ORDER MANAGEMENT
// ============================================
/**
* @notice Update the configuration for multiple orders
* @param orders The list of order addresses to update
* @param orderConfigs The new configuration parameters for each order, containing:
* - virtualXtReserve: The new virtual XT reserve for the order
* - maxXtReserve: The new maximum XT reserve for the order
* - removingLiquidity: The amount of liquidity to remove from the order
* - curveCuts: The new curve cuts for the order
*/
function updateOrdersConfiguration(address[] memory orders, OrderV2ConfigurationParams[] memory orderConfigs)
external;
/**
* @notice Remove the liquidity from multiple orders
* @param orders The list of order addresses to update
* @param removedLiquidities The amount of liquidity to remove from each order
*/
function removeLiquidityFromOrders(address[] memory orders, uint256[] memory removedLiquidities) external;
/**
* @notice Creates a new order with the specified parameters
* @dev Deploys a new TermMax order contract with the given configuration.
* The order will be associated with the specified market and pool.
* @param market The TermMax market address that the order will operate in
* @param params The configuration parameters for the new order
* @return order The address of the newly created TermMax order contract
*/
function createOrder(ITermMaxMarketV2 market, OrderV2ConfigurationParams memory params)
external
returns (ITermMaxOrderV2 order);
}
"
},
"contracts/v2/access/IWhitelistManager.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title IWhitelistManager
* @author Term Structure Labs
* @notice Interface for managing whitelists for different contract modules
*/
interface IWhitelistManager {
event WhitelistUpdated(address[] contractAddress, ContractModule module, bool approved);
enum ContractModule {
ADAPTER,
ORDER_CALLBACK,
MARKET,
ORACLE,
POOL
}
/**
* @notice Set the whitelist status for contract addresses and module
* @param contractAddresses Array of addresses to set the whitelist status for
* @param module The contract module type
* @param approved Whether the addresses should be approved or not
*/
function batchSetWhitelist(address[] memory contractAddresses, ContractModule module, bool approved) external;
/**
* @notice Check if a contract address is whitelisted for a specific module
* @param contractAddress The address to check
* @param module The contract module type
* @return bool True if the address is whitelisted for the module, false otherwise
*/
function isWhitelisted(address contractAddress, ContractModule module) external view returns (bool);
}
"
},
"contracts/v2/VersionV2.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
abstract contract VersionV2 {
// Function to get the version number
function getVersion() public pure virtual returns (string memory) {
return "2.0.0";
}
}
"
},
"dependencies/@openzeppelin-contracts-upgradeable-5.2.0/access/AccessControlUpgradeable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)
pragma solidity ^0.8.20;
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {ERC165Upgradeable} from "../utils/introspection/ERC165Upgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControl, ERC165Upgradeable {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/// @custom:storage-location erc7201:openzeppelin.storage.AccessControl
struct AccessControlStorage {
mapping(bytes32 role => RoleData) _roles;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessControl")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant AccessControlStorageLocation = 0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800;
function _getAccessControlStorage() private pure returns (AccessControlStorage storage $) {
assembly {
$.slot := AccessControlStorageLocation
}
}
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
function __AccessControl_init() internal onlyInitializing {
}
function __AccessControl_init_unchained() internal onlyInitializing {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
AccessControlStorage storage $ = _getAccessControlStorage();
return $._roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
AccessControlStorage storage $ = _getAccessControlStorage();
return $._roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
AccessControlStorage storage $ = _getAccessControlStorage();
bytes32 previousAdminRole = getRoleAdmin(role);
$._roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
AccessControlStorage storage $ = _getAccessControlStorage();
if (!hasRole(role, account)) {
$._roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
/**
* @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
AccessControlStorage storage $ = _getAccessControlStorage();
if (hasRole(role, account)) {
$._roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}
"
},
"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);
}
}
}
"
},
"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/v1/factory/ITermMaxFactory.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {MarketInitialParams} from "../storage/TermMaxStorage.sol";
/**
* @title The TermMax factory interface
* @author Term Structure Labs
*/
interface ITermMaxFactory {
function TERMMAX_MARKET_IMPLEMENTATION() external view returns (address);
function gtImplements(bytes32 gtKey) external view returns (address gtImplement);
/// @notice Set the implementations of TermMax Gearing Token contract
function setGtImplement(string memory gtImplementName, address gtImplement) external;
/// @notice Predict the address of token pair
function predictMarketAddress(
address deployer,
address collateral,
address debtToken,
uint64 maturity,
uint256 salt
) external view returns (address market);
/// @notice Deploy a new market
function createMarket(bytes32 gtKey, MarketInitialParams memory params, uint256 salt)
external
returns (address market);
}
"
},
"contracts/v1/router/ITermMaxRouter.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {ITermMaxMarket} from "../ITermMaxMarket.sol";
import {ITermMaxOrder} from "../ITermMaxOrder.sol";
import {SwapUnit} from "./ISwapAdapter.sol";
import {CurveCuts} from "../storage/TermMaxStorage.sol";
import {ISwapCallback} from "../ISwapCallback.sol";
/**
* @title TermMax Router interface
* @author Term Structure Labs
* @notice Interface for the main router contract that handles all user interactions with TermMax protocol
* @dev This interface defines all external functions for swapping, leveraging, and managing positions
*/
interface ITermMaxRouter {
/**
* @notice Pauses all protocol operations
* @dev Can only be called by authorized addresses
*/
function pause() external;
/**
* @notice Unpauses protocol operations
* @dev Can only be called by authorized addresses
*/
function unpause() external;
/**
* @notice View the adapter whitelist status
* @dev Used for controlling which swap adapters can be used
* @param adapter The adapter's address to check whitelist status for
* @return True if whitelisted, false otherwise
*/
function adapterWhitelist(address adapter) external view returns (bool);
/**
* @notice Set the adapter whitelist status
* @dev Used for controlling which swap adapters can be used
* @param adapter The adapter's address to set whitelist status for
* @param isWhitelist True to whitelist, false to remove from whitelist
*/
function setAdapterWhitelist(address adapter, bool isWhitelist) external;
/**
* @notice Retrieves all assets owned by an address in a specific market
* @dev Returns both ERC20 tokens and GT (Governance Token) positions
* @param market The market to query assets from
* @param owner The address to check assets for
* @return tokens Array of ERC20 token addresses
* @return balances Corresponding balances for each token
* @return gt The GT token contract address
* @return gtIds Array of GT token IDs owned by the address
*/
function assetsWithERC20Collateral(ITermMaxMarket market, address owner)
external
view
returns (IERC20[4] memory tokens, uint256[4] memory balances, address gt, uint256[] memory gtIds);
/**
* @notice Swaps an exact amount of input token for output token
* @dev Uses specified orders for the swap path
* @param tokenIn Input token to swap from
* @param tokenOut Output token to swap to
* @param recipient Address to receive the output tokens
* @param orders Array of orders to use for the swap path
* @param tradingAmts Array of amounts to trade for each order
* @param minTokenOut Minimum amount of output tokens to receive
* @param deadline The deadline timestamp for the transaction
* @return netTokenOut Actual amount of output tokens received
*/
function swapExactTokenToToken(
IERC20 tokenIn,
IERC20 tokenOut,
address recipient,
ITermMaxOrder[] memory orders,
uint128[] memory tradingAmts,
uint128 minTokenOut,
uint256 deadline
) external returns (uint256 netTokenOut);
/**
* @notice Swaps tokens to receive an exact amount of output token
* @dev Uses specified orders for the swap path
* @param tokenIn Input token to swap from
* @param tokenOut Output token to swap to
* @param recipient Address to receive the output tokens
* @param orders Array of orders to use for the swap path
* @param tradingAmts Array of amounts to trade for each order
* @param maxTokenIn Maximum amount of input tokens to spend
* @param deadline The deadline timestamp for the transaction
* @return netTokenIn Actual amount of input tokens spent
*/
function swapTokenToExactToken(
IERC20 tokenIn,
IERC20 tokenOut,
address recipient,
ITermMaxOrder[] memory orders,
uint128[] memory tradingAmts,
uint128 maxTokenIn,
uint256 deadline
) external returns (uint256 netTokenIn);
/**
* @notice Sells FT and XT tokens for underlying tokens
* @dev Executes multiple orders to sell tokens
* @param recipient Address to receive the output tokens
* @param market The market to sell tokens in
* @param ftInAmt Amount of FT tokens to sell
* @param xtInAmt Amount of XT tokens to sell
* @param orders Array of orders to execute
* @param amtsToSellTokens Array of amounts to sell for each order
* @param minTokenOut Minimum amount of output tokens to receive
* @param deadline The deadline timestamp for the transaction
* @return netTokenOut Actual amount of output tokens received
*/
function sellTokens(
address recipient,
ITermMaxMarket market,
uint128 ftInAmt,
uint128 xtInAmt,
ITermMaxOrder[] memory orders,
uint128[] memory amtsToSellTokens,
uint128 minTokenOut,
uint256 deadline
) external returns (uint256 netTokenOut);
/**
* @notice Creates a leveraged position from input tokens
* @dev Swaps tokens for XT and creates a leveraged position
* @param recipient Address to receive the position
* @param market The market to create position in
* @param orders Array of orders to execute
* @param amtsToBuyXt Array of amounts of XT to buy for each order
* @param minXtOut Minimum amount of XT to establish the position
* @param tokenToSwap Amount of tokens to swap
* @param maxLtv Maximum loan-to-value ratio
* @param units Array of swap units defining the swap path
* @param deadline The deadline timestamp for the transaction
* @return gtId ID of the generated GT token
* @return netXtOut Amount of XT tokens received
*/
function leverageFromToken(
address recipient,
ITermMaxMarket market,
ITermMaxOrder[] memory orders,
uint128[] memory amtsToBuyXt,
uint128 minXtOut,
uint128 tokenToSwap,
uint128 maxLtv,
SwapUnit[] memory units,
uint256 deadline
) external returns (uint256 gtId, uint256 netXtOut);
/**
* @notice Creates a leveraged position from XT tokens
* @dev Uses existing XT tokens to create a leveraged position
* @param recipient Address to receive the position
* @param market The market to create position in
* @param xtInAmt Amount of XT tokens to use
* @param tokenInAmt Amount of additional tokens to use
* @param maxLtv Maximum loan-to-value ratio
* @param units Array of swap units defining the swap path
* @return gtId ID of the generated GT token
*/
function leverageFromXt(
address recipient,
ITermMaxMarket market,
uint128 xtInAmt,
uint128 tokenInAmt,
uint128 maxLtv,
SwapUnit[] memory units
) external returns (uint256 gtId);
function leverageFromXtAndCollateral(
address recipient,
ITermMaxMarket market,
uint128 xtInAmt,
uint128 collateralInAmt,
uint128 maxLtv,
SwapUnit[] memory units
) external returns (uint256 gtId);
/**
* @notice Borrows tokens using collateral
* @dev Creates a collateralized debt position
* @param recipient Address to receive the borrowed tokens
* @param market The market to borrow from
* @param collInAmt Amount of collateral to deposit
* @param orders Array of orders to execute
* @param tokenAmtsWantBuy Array of token amounts to buy
* @param maxDebtAmt Maximum amount of debt to take on
* @param deadline The deadline timestamp for the transaction
* @return gtId ID of the generated GT token
*/
function borrowTokenFromCollateral(
address recipient,
ITermMaxMarket market,
uint256 collInAmt,
ITermMaxOrder[] memory orders,
uint128[] memory tokenAmtsWantBuy,
uint128 maxDebtAmt,
uint256 deadline
) external returns (uint256 gtId);
/**
* @notice Borrows tokens using collateral and XT
* @dev Creates a collateralized debt position
* @param recipient Address to receive the borrowed tokens
* @param market The market to borrow from
* @param collInAmt Amount of collateral to deposit
* @param borrowAmt Amount of tokens to borrow
* @return gtId ID of the generated GT token
*/
function borrowTokenFromCollateral(address recipient, ITermMaxMarket market, uint256 collInAmt, uint256 borrowAmt)
external
returns (uint256 gtId);
/**
* @notice Borrows tokens from an existing GT position
* @dev Increases the debt of an existing position
* @param recipient Address to receive the borrowed tokens
* @param market The market to borrow from
* @param gtId ID of the GT token to borrow from
* @param borrowAmt Amount of tokens to borrow
*/
function borrowTokenFromGt(address recipient, ITermMaxMarket market, uint256 gtId, uint256 borrowAmt) external;
/**
* @notice Repays debt from collateral
* @dev Repays debt and closes a position
* @param recipient Address to receive any remaining collateral
* @param market The market to repay debt in
* @param gtId ID of the GT token to repay debt from
* @param orders Array of orders to execute
* @param amtsToBuyFt Array of amounts to buy for each order
* @param byDebtToken Whether to repay debt using debt tokens
* @param units Array of swap units defining the swap path
* @param deadline The deadline timestamp for the transaction
* @return netTokenOut Actual amount of tokens received
*/
function flashRepayFromColl(
address recipient,
ITermMaxMarket market,
uint256 gtId,
ITermMaxOrder[] memory orders,
uint128[] memory amtsToBuyFt,
bool byDebtToken,
SwapUnit[] memory units,
uint256 deadline
) external returns (uint256 netTokenOut);
/**
* @notice Repays debt using FT tokens
* @dev Repays debt and closes a position
* @param recipient Address to receive any remaining tokens
* @param market The market to repay debt in
* @param gtId ID of the GT token to repay debt from
* @param orders Array of orders to execute
* @param ftAmtsWantBuy Array of FT amounts to buy for each order
* @param maxTokenIn Maximum amount of tokens to spend
* @param deadline The deadline timestamp for the transaction
* @return returnAmt Actual amount of tokens returned
*/
function repayByTokenThroughFt(
address recipient,
ITermMaxMarket market,
uint256 gtId,
ITermMaxOrder[] memory orders,
uint128[] memory ftAmtsWantBuy,
uint128 maxTokenIn,
uint256 deadline
) external returns (uint256 returnAmt);
/**
* @notice Redeems FT tokens and swaps for underlying tokens
* @dev Executes a swap to redeem FT tokens
* @param recipient Address to receive the output tokens
* @param market The market to redeem FT tokens in
* @param ftAmount Amount of FT tokens to redeem
* @param units Array of swap units defining the swap path
* @param minTokenOut Minimum amount of output tokens to receive
* @return redeemedAmt Actual amount of output tokens received
*/
function redeemAndSwap(
address recipient,
ITermMaxMarket market,
uint256 ftAmount,
SwapUnit[] memory units,
uint256 minTokenOut
) external returns (uint256 redeemedAmt);
/**
* @notice Creates an order and deposits tokens
* @dev Creates a new order and deposits tokens to the market
* @param market The market to create order in
* @param maker Address of the order maker
* @param maxXtReserve Maximum amount of XT to reserve
* @param swapTrigger Swap trigger callback
* @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 curveCuts Curve cuts for the order
* @return order The created order
*/
function createOrderAndDeposit(
ITermMaxMarket market,
address maker,
uint256 maxXtReserve,
ISwapCallback swapTrigger,
uint256 debtTokenToDeposit,
uint128 ftToDeposit,
uint128 xtToDeposit,
CurveCuts memory curveCuts
) external returns (ITermMaxOrder order);
}
"
},
"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/v1/oracle/IOracle.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.27;
import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
/**
* @title IOracle
* @author Term Structure Labs
*/
interface IOracle {
struct Oracle {
AggregatorV3Interface aggregator;
AggregatorV3Interface backupAggregator;
uint32 heartbeat;
}
/// @notice Error thrown when the oracle is not working
error OracleIsNotWorking(address
Submitted on: 2025-10-13 11:00:10
Comments
Log in to comment.
No comments yet.