// SPDX-License-Identifier: MIT pragma solidity >=0.7.6 <0.9; import {IPayment} from ".//IPayment.sol"; import {IBalanceDecreasingTransaction} from ".//IBalanceDecreasingTransaction.sol"; import {IReferencedPaymentNonexistence} from ".//IReferencedPaymentNonexistence.sol"; import {IConfirmedBlockHeightExists} from ".//IConfirmedBlockHeightExists.sol"; import {IAddressValidity} from ".//IAddressValidity.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {IDiamondLoupe} from "./diamond/interfaces/IDiamondLoupe.sol"; import {AssetManagerSettings} from "./data/AssetManagerSettings.sol"; import {CollateralType} from "./data/CollateralType.sol"; import {AgentInfo} from "./data/AgentInfo.sol"; import {AgentSettings} from "./data/AgentSettings.sol"; import {AvailableAgentInfo} from "./data/AvailableAgentInfo.sol"; import {RedemptionTicketInfo} from "./data/RedemptionTicketInfo.sol"; import {RedemptionRequestInfo} from "./data/RedemptionRequestInfo.sol"; import {CollateralReservationInfo} from "./data/CollateralReservationInfo.sol"; import {EmergencyPause} from "./data/EmergencyPause.sol"; import {IAssetManagerEvents} from "./IAssetManagerEvents.sol"; import {IAgentPing} from "./IAgentPing.sol"; import {IRedemptionTimeExtension} from "./IRedemptionTimeExtension.sol"; import {ICoreVaultClient} from "./ICoreVaultClient.sol"; import {ICoreVaultClientSettings} from "./ICoreVaultClientSettings.sol"; import {IAgentAlwaysAllowedMinters} from "./IAgentAlwaysAllowedMinters.sol"; import {IDirectMinting} from "./IDirectMinting.sol"; import {IDirectMintingSettings} from "./IDirectMintingSettings.sol"; import {IRedeemExtended} from "./IRedeemExtended.sol"; import {IRedeemExtendedSettings} from "./IRedeemExtendedSettings.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * Asset manager publicly callable methods. */ interface IAssetManager is IERC165, IDiamondLoupe, IAssetManagerEvents, IAgentPing, IRedemptionTimeExtension, ICoreVaultClient, ICoreVaultClientSettings, IAgentAlwaysAllowedMinters, IDirectMinting, IDirectMintingSettings, IRedeemExtended, IRedeemExtendedSettings { //////////////////////////////////////////////////////////////////////////////////// // Basic system information /** * Get the asset manager controller, the only address that can change settings. * Asset manager must be attached to the asset manager controller in the system contract registry. */ function assetManagerController() external view returns (address); /** * Get the f-asset contract managed by this asset manager instance. */ function fAsset() external view returns (IERC20); /** * Get the price reader contract used by this asset manager instance. */ function priceReader() external view returns (address); /** * Return lot size in UBA (underlying base amount - smallest amount on underlying chain, e.g. satoshi). */ function lotSize() external view returns (uint256 _lotSizeUBA); /** * Return asset minting granularity - smallest unit of f-asset stored internally * within this asset manager instance. */ function assetMintingGranularityUBA() external view returns (uint256); /** * Return asset minting decimals - the number of decimals of precision for minting. */ function assetMintingDecimals() external view returns (uint256); //////////////////////////////////////////////////////////////////////////////////// // System settings /** * Get complete current settings. * @return the current settings */ function getSettings() external view returns (AssetManagerSettings.Data memory); /** * When `controllerAttached` is true, asset manager has been added to the asset manager controller. * This is required for the asset manager to be operational (create agent and minting don't work otherwise). */ function controllerAttached() external view returns (bool); //////////////////////////////////////////////////////////////////////////////////// // Emergency pause /** * If true, the system is in emergency pause mode and most operations (mint, redeem, liquidate) are disabled. */ function emergencyPaused() external view returns (bool); /** * Emergency pause level defines which operations are paused: * NONE - pause is not active, * START_OPERATIONS - prevent starting mint, redeem, liquidation (start/liquidate) and core vault transfer/return, * FULL - everything from START_OPERATIONS, plus prevent finishing or defulating already started mints and redeems, * FULL_AND_TRANSFER - everything from FULL, plus prevent FAsset transfers. */ function emergencyPauseLevel() external view returns (EmergencyPause.Level); /** * The time when emergency pause mode will end automatically. */ function emergencyPausedUntil() external view returns (uint256); //////////////////////////////////////////////////////////////////////////////////// // Asset manager upgrading state /** * True if the asset manager is paused. * In the paused state, minting is disabled, but all other operations (e.g. redemptions, liquidation) still work. * Paused asset manager can be later unpaused. */ function mintingPaused() external view returns (bool); //////////////////////////////////////////////////////////////////////////////////// // Timekeeping for underlying chain /** * Prove that a block with given number and timestamp exists and * update the current underlying block info if the provided data is higher. * This method should be called by minters before minting and by agent's regularly * to prevent current block being too outdated, which gives too short time for * minting or redemption payment. * NOTE: anybody can call. * NOTE: the block/timestamp will only be updated if it is strictly higher than the current value. * For mintings and redemptions we also add the duration from the last update (on this chain) to compensate * for the time that passed since the last update. This mechanism can be abused by providing old block proof * as fresh, which will distort the compensation accounting. Due to monotonicity such an attack will only work * if there was no block update for some time. Therefore it is enough to have at least one honest * current block updater regularly providing updates to avoid this issue. * @param _proof proof that a block with given number and timestamp exists */ function updateCurrentBlock( IConfirmedBlockHeightExists.Proof calldata _proof ) external; /** * Get block number and timestamp of the current underlying block known to the f-asset system. * @return _blockNumber current underlying block number tracked by asset manager * @return _blockTimestamp current underlying block timestamp tracked by asset manager * @return _lastUpdateTs the timestamp on this chain when the current underlying block was last updated */ function currentUnderlyingBlock() external view returns ( uint256 _blockNumber, uint256 _blockTimestamp, uint256 _lastUpdateTs ); //////////////////////////////////////////////////////////////////////////////////// // Available collateral types /** * Get collateral information about a token. */ function getCollateralType( CollateralType.Class _collateralClass, IERC20 _token ) external view returns (CollateralType.Data memory); /** * Get the list of all available tokens used for collateral. */ function getCollateralTypes() external view returns (CollateralType.Data[] memory); //////////////////////////////////////////////////////////////////////////////////// // Agent create / destroy /** * Create an agent vault. * The agent will always be identified by `_agentVault` address. * (Externally, one account may own several agent vaults, * but in fasset system, each agent vault acts as an independent agent.) * NOTE: may only be called by an agent on the allowed agent list. * Can be called from the management or the work agent owner address. * @return _agentVault new agent vault address */ function createAgentVault( IAddressValidity.Proof calldata _addressProof, AgentSettings.Data calldata _settings ) external returns (address _agentVault); /** * Announce that the agent is going to be destroyed. At this time, the agent must not have any mintings * or collateral reservations and must not be on the available agents list. * NOTE: may only be called by the agent vault owner. * @return _destroyAllowedAt the timestamp at which the destroy can be executed */ function announceDestroyAgent( address _agentVault ) external returns (uint256 _destroyAllowedAt); /** * Delete all agent data, self destruct agent vault and send remaining collateral to the `_recipient`. * Procedure for destroying agent: * - exit available agents list * - wait until all assets are redeemed or perform self-close * - announce destroy (and wait the required time) * - call destroyAgent() * NOTE: may only be called by the agent vault owner. * NOTE: the remaining funds from the vault will be transferred to the provided recipient. * @param _agentVault address of the agent's vault to destroy * @param _recipient address that receives the remaining funds and possible vault balance */ function destroyAgent( address _agentVault, address payable _recipient ) external; /** * When agent vault, collateral pool or collateral pool token factory is upgraded, new agent vaults * automatically get the new implementation from the factory. But the existing agent vaults must * be upgraded by their owners using this method. * NOTE: may only be called by the agent vault owner. * @param _agentVault address of the agent's vault; both vault, its corresponding pool, and * its pool token will be upgraded to the newest implementations */ function upgradeAgentVaultAndPool(address _agentVault) external; /** * Check if the collateral pool token has been used already by some vault. * @param _suffix the suffix to check */ function isPoolTokenSuffixReserved( string memory _suffix ) external view returns (bool); //////////////////////////////////////////////////////////////////////////////////// // Agent settings update /** * Due to the effect on the pool, all agent settings are timelocked. * This method announces a setting change. The change can be executed after the timelock expires. * NOTE: may only be called by the agent vault owner. * @param _agentVault agent vault address * @param _name setting name, same as for `getAgentSetting` * @return _updateAllowedAt the timestamp at which the update can be executed */ function announceAgentSettingUpdate( address _agentVault, string memory _name, uint256 _value ) external returns (uint256 _updateAllowedAt); /** * Due to the effect on the pool, all agent settings are timelocked. * This method executes a setting change after the timelock expires. * NOTE: may only be called by the agent vault owner. * @param _agentVault agent vault address * @param _name setting name, same as for `getAgentSetting` */ function executeAgentSettingUpdate( address _agentVault, string memory _name ) external; //////////////////////////////////////////////////////////////////////////////////// // Collateral withdrawal announcement /** * The agent is going to withdraw `_valueNATWei` amount of collateral from the agent vault. * This has to be announced and the agent must then wait `withdrawalWaitMinSeconds` time. * After that time, the agent can call `withdrawCollateral(_vaultCollateralToken, _valueNATWei)` * on the agent vault. * NOTE: may only be called by the agent vault owner. * @param _agentVault agent vault address * @param _valueNATWei the amount to be withdrawn * @return _withdrawalAllowedAt the timestamp when the withdrawal can be made */ function announceVaultCollateralWithdrawal( address _agentVault, uint256 _valueNATWei ) external returns (uint256 _withdrawalAllowedAt); /** * Agent is going to withdraw `_valuePoolTokenWei` of pool tokens from the agent vault * and redeem them for NAT from the collateral pool. * This has to be announced and the agent must then wait `withdrawalWaitMinSeconds`. * After that time, the agent can call redeemCollateralPoolTokens(_valuePoolTokenWei) on agent vault. * NOTE: may only be called by the agent vault owner. * @param _agentVault agent vault address * @param _valuePoolTokenWei the amount to be withdrawn * @return _redemptionAllowedAt the timestamp when the redemption can be made */ function announceAgentPoolTokenRedemption( address _agentVault, uint256 _valuePoolTokenWei ) external returns (uint256 _redemptionAllowedAt); //////////////////////////////////////////////////////////////////////////////////// // Underlying balance topup /** * When the agent tops up his underlying address, it has to be confirmed by calling this method, * which updates the underlying free balance value. * NOTE: may only be called by the agent vault owner. * @param _payment proof of the underlying payment; must include payment * reference of the form `0x4642505266410011000...0` * @param _agentVault agent vault address */ function confirmTopupPayment( IPayment.Proof calldata _payment, address _agentVault ) external; //////////////////////////////////////////////////////////////////////////////////// // Underlying withdrawal announcements /** * Announce withdrawal of underlying currency. * In the event UnderlyingWithdrawalAnnounced the agent receives payment reference, which must be * added to the payment, otherwise it can be challenged as illegal. * Until the announced withdrawal is performed and confirmed or canceled, no other withdrawal can be announced. * NOTE: may only be called by the agent vault owner. * @param _agentVault agent vault address */ function announceUnderlyingWithdrawal(address _agentVault) external; /** * Agent must provide confirmation of performed underlying withdrawal, which updates free balance with used gas * and releases announcement so that a new one can be made. * If the agent doesn't call this method, anyone can call it after a time (`confirmationByOthersAfterSeconds`). * NOTE: may only be called by the owner of the agent vault * except if enough time has passed without confirmation - then it can be called by anybody. * @param _payment proof of the underlying payment * @param _agentVault agent vault address */ function confirmUnderlyingWithdrawal( IPayment.Proof calldata _payment, address _agentVault ) external; /** * Cancel ongoing withdrawal of underlying currency. * Needed in order to reset announcement timestamp, so that others cannot front-run the agent at * `confirmUnderlyingWithdrawal` call. This could happen if withdrawal would be performed more * than `confirmationByOthersAfterSeconds` seconds after announcement. * NOTE: may only be called by the agent vault owner. * @param _agentVault agent vault address */ function cancelUnderlyingWithdrawal(address _agentVault) external; //////////////////////////////////////////////////////////////////////////////////// // Agent information /** * Get (a part of) the list of all active (not destroyed) agents. * The list must be retrieved in parts since retrieving the whole list can consume too much gas for one block. * @param _start first index to return from the available agent's list * @param _end end index (one above last) to return from the available agent's list */ function getAllAgents( uint256 _start, uint256 _end ) external view returns (address[] memory _agents, uint256 _totalLength); /** * Return detailed info about an agent, typically needed by a minter. * @param _agentVault agent vault address * @return structure containing agent's minting fee (BIPS), min collateral ratio (BIPS), * and current free collateral (lots) */ function getAgentInfo( address _agentVault ) external view returns (AgentInfo.Info memory); /** * Get agent's setting by name. * This allows reading individual settings. * @param _agentVault agent vault address * @param _name setting name, one of: `feeBIPS`, `poolFeeShareBIPS`, `redemptionPoolFeeShareBIPS`, * `mintingVaultCollateralRatioBIPS`, `mintingPoolCollateralRatioBIPS`,`buyFAssetByAgentFactorBIPS`, * `poolExitCollateralRatioBIPS` */ function getAgentSetting( address _agentVault, string memory _name ) external view returns (uint256); /** * Returns the collateral pool address of the agent identified by `_agentVault`. */ function getCollateralPool( address _agentVault ) external view returns (address); /** * Return the management address of the owner of the agent identified by `_agentVault`. */ function getAgentVaultOwner( address _agentVault ) external view returns (address _ownerManagementAddress); /** * Return vault collateral ERC20 token chosen by the agent identified by `_agentVault`. */ function getAgentVaultCollateralToken( address _agentVault ) external view returns (IERC20); /** * Return full vault collateral (free + locked) deposited in the vault `_agentVault`. */ function getAgentFullVaultCollateral( address _agentVault ) external view returns (uint256); /** * Return full pool NAT collateral (free + locked) deposited in the vault `_agentVault`. */ function getAgentFullPoolCollateral( address _agentVault ) external view returns (uint256); /** * Return the current liquidation factors and max liquidation amount of the agent * identified by `_agentVault`. */ function getAgentLiquidationFactorsAndMaxAmount( address _agentVault ) external view returns ( uint256 liquidationPaymentFactorVaultBIPS, uint256 liquidationPaymentFactorPoolBIPS, uint256 maxLiquidationAmountUBA ); /** * Return the minimum collateral ratio of the pool collateral owned by vault `_agentVault`. */ function getAgentMinPoolCollateralRatioBIPS( address _agentVault ) external view returns (uint256); /** * Return the minimum collateral ratio of the vault collateral owned by vault `_agentVault`. */ function getAgentMinVaultCollateralRatioBIPS( address _agentVault ) external view returns (uint256); //////////////////////////////////////////////////////////////////////////////////// // List of available agents (i.e. publicly available for minting). /** * Add the agent to the list of publicly available agents. * Other agents can only self-mint. * NOTE: may only be called by the agent vault owner. * @param _agentVault agent vault address */ function makeAgentAvailable(address _agentVault) external; /** * Announce exit from the publicly available agents list. * NOTE: may only be called by the agent vault owner. * @param _agentVault agent vault address * @return _exitAllowedAt the timestamp when the agent can exit */ function announceExitAvailableAgentList( address _agentVault ) external returns (uint256 _exitAllowedAt); /** * Exit the publicly available agents list. * NOTE: may only be called by the agent vault owner and after announcement. * @param _agentVault agent vault address */ function exitAvailableAgentList(address _agentVault) external; /** * Get (a part of) the list of available agents. * The list must be retrieved in parts since retrieving the whole list can consume too much gas for one block. * @param _start first index to return from the available agent's list * @param _end end index (one above last) to return from the available agent's list */ function getAvailableAgentsList( uint256 _start, uint256 _end ) external view returns (address[] memory _agents, uint256 _totalLength); /** * Get (a part of) the list of available agents with extra information about agents' fee, min collateral ratio * and available collateral (in lots). * The list must be retrieved in parts since retrieving the whole list can consume too much gas for one block. * NOTE: agent's available collateral can change anytime due to price changes, minting, or changes * in agent's min collateral ratio, so it is only to be used as an estimate. * @param _start first index to return from the available agent's list * @param _end end index (one above last) to return from the available agent's list */ function getAvailableAgentsDetailedList( uint256 _start, uint256 _end ) external view returns ( AvailableAgentInfo.Data[] memory _agents, uint256 _totalLength ); //////////////////////////////////////////////////////////////////////////////////// // Minting /** * Before paying underlying assets for minting, minter has to reserve collateral and * pay collateral reservation fee. Collateral is reserved at ratio of agent's agentMinCollateralRatio * to requested lots NAT market price. * The minter receives instructions for underlying payment * (value, fee and payment reference) in event CollateralReserved. * Then the minter has to pay `value + fee` on the underlying chain. * If the minter pays the underlying amount, minter obtains f-assets. * The collateral reservation fee is split between the agent and the collateral pool. * NOTE: the owner of the agent vault must be in the AgentOwnerRegistry. * NOTE: if the underlying block isn't updated regularly, it can happen that there is not enough time for * the underlying payment. Therefore minters have to verify the current underlying before minting and, * if needed, update it by calling `updateCurrentBlock`. * @param _agentVault agent vault address * @param _lots the number of lots for which to reserve collateral * @param _maxMintingFeeBIPS maximum minting fee (BIPS) that can be charged by the agent - best is just to * copy current agent's published fee; used to prevent agent from front-running reservation request * and increasing fee (that would mean that the minter would have to pay raised fee or forfeit * collateral reservation fee) * @param _executor the account that is allowed to execute minting (besides minter and agent) */ function reserveCollateral( address _agentVault, uint256 _lots, uint256 _maxMintingFeeBIPS, address payable _executor ) external payable returns (uint256 _collateralReservationId); /** * Return the collateral reservation fee amount that has to be passed to the `reserveCollateral` method. * NOTE: the amount paid may be larger than the required amount, but the difference is not returned. * It is advised that the minter pays the exact amount, but when the amount is so small that the revert * would cost more than the lost difference, the minter may want to send a slightly larger amount to compensate * for the possibility of a FTSO price change between obtaining this value and calling `reserveCollateral`. * @param _lots the number of lots for which to reserve collateral * @return _reservationFeeNATWei the amount of reservation fee in NAT wei */ function collateralReservationFee( uint256 _lots ) external view returns (uint256 _reservationFeeNATWei); /** * Returns the data about the collateral reservation for an ongoing minting. * Note: once the minting is executed or defaulted, the collateral reservation is deleted and this method fails. * @param _collateralReservationId the collateral reservation id, as used for executing or defaulting the minting */ function collateralReservationInfo( uint256 _collateralReservationId ) external view returns (CollateralReservationInfo.Data memory); /** * After obtaining proof of underlying payment, the minter calls this method to finish the minting * and collect the minted f-assets. * NOTE: may only be called by the minter (= creator of CR, the collateral reservation request), * the executor appointed by the minter, or the agent owner (= owner of the agent vault in CR). * @param _payment proof of the underlying payment (must contain exact `value + fee` amount and correct * payment reference) * @param _collateralReservationId collateral reservation id */ function executeMinting( IPayment.Proof calldata _payment, uint256 _collateralReservationId ) external; /** * When the time for the minter to pay the underlying amount is over (i.e. the last underlying block has passed), * the agent can declare payment default. Then the agent collects the collateral reservation fee * (it goes directly to the vault), and the reserved collateral is unlocked. * NOTE: The attestation request must be done with `checkSourceAddresses=false`. * NOTE: may only be called by the owner of the agent vault in the collateral reservation request. * @param _proof proof that the minter didn't pay with correct payment reference on the underlying chain * @param _collateralReservationId id of a collateral reservation created by the minter */ function mintingPaymentDefault( IReferencedPaymentNonexistence.Proof calldata _proof, uint256 _collateralReservationId ) external; /** * The minter can make several mistakes in the underlying payment: * - the payment is too late and is already defaulted before executing * - the payment is too small so executeMinting reverts * - the payment is performed twice * In all of these cases the paid amount ends up on the agent vault's underlying account, but it is not * confirmed and therefore the agent cannot withdraw it without triggering full liquidation (of course * the agent can legally withdraw it once the vault is closed). * This method enables the agent to confirm such payments, converting the deposited amount to agent's * free underlying. * NOTE: may only be called by the agent vault owner. * @param _payment proof of the underlying payment (must have correct payment reference) * @param _collateralReservationId collateral reservation id */ function confirmClosedMintingPayment( IPayment.Proof calldata _payment, uint256 _collateralReservationId ) external; /** * If a collateral reservation request exists for more than 24 hours, payment or non-payment proof are no longer * available. In this case the agent can call this method, which burns reserved collateral at market price * and releases the remaining collateral (CRF is also burned). * NOTE: may only be called by the owner of the agent vault in the collateral reservation request. * NOTE: the agent (management address) receives the vault collateral and NAT is burned instead. Therefore * this method is `payable` and the caller must provide enough NAT to cover the received vault collateral * amount multiplied by `vaultCollateralBuyForFlareFactorBIPS`. * @param _proof proof that the attestation query window can not not contain * the payment/non-payment proof anymore * @param _collateralReservationId collateral reservation id */ function unstickMinting( IConfirmedBlockHeightExists.Proof calldata _proof, uint256 _collateralReservationId ) external payable; /** * Agent can mint against himself. * This is a one-step process, skipping collateral reservation and collateral reservation fee payment. * Moreover, the agent doesn't have to be on the publicly available agents list to self-mint. * NOTE: may only be called by the agent vault owner. * NOTE: the caller must be a whitelisted agent. * @param _payment proof of the underlying payment; must contain payment reference of the form * `0x4642505266410012000...0` * @param _agentVault agent vault address * @param _lots number of lots to mint */ function selfMint( IPayment.Proof calldata _payment, address _agentVault, uint256 _lots ) external; /** * If an agent has enough free underlying, they can mint immediately without any underlying payment. * This is a one-step process, skipping collateral reservation and collateral reservation fee payment. * Moreover, the agent doesn't have to be on the publicly available agents list to self-mint. * NOTE: may only be called by the agent vault owner. * NOTE: the caller must be a whitelisted agent. * @param _agentVault agent vault address * @param _lots number of lots to mint */ function mintFromFreeUnderlying(address _agentVault, uint64 _lots) external; //////////////////////////////////////////////////////////////////////////////////// // Redemption /** * Redeem (up to) `_lots` lots of f-assets. The corresponding amount of the f-assets belonging * to the redeemer will be burned and the redeemer will get paid by the agent in underlying currency * (or, in case of agent's payment default, by agent's collateral with a premium). * NOTE: in some cases not all sent f-assets can be redeemed (either there are not enough tickets or * more than a fixed limit of tickets should be redeemed). In this case only part of the approved assets * are burned and redeemed and the redeemer can execute this method again for the remaining lots. * In such a case the `RedemptionRequestIncomplete` event will be emitted, indicating the number * of remaining lots. * Agent receives redemption request id and instructions for underlying payment in * RedemptionRequested event and has to pay `value - fee` and use the provided payment reference. * NOTE: if the underlying block isn't updated regularly, it can happen that there is no time for underlying * payment. Since the agents cannot know when the next redemption will happen, they should regularly update the * underlying time by obtaining fresh proof of latest underlying block and calling `updateCurrentBlock`. * @param _lots number of lots to redeem * @param _redeemerUnderlyingAddressString the address to which the agent must transfer underlying amount * @param _executor the account that is allowed to execute redemption default (besides redeemer and agent) * @return _redeemedAmountUBA the actual redeemed amount; may be less than requested if there are not enough * redemption tickets available or the maximum redemption ticket limit is reached */ function redeem( uint256 _lots, string memory _redeemerUnderlyingAddressString, address payable _executor ) external payable returns (uint256 _redeemedAmountUBA); /** * If the redeemer provides invalid address, the agent should provide the proof of address invalidity from the * Flare data connector. With this, the agent's obligations are fulfilled and they can keep the underlying. * NOTE: may only be called by the owner of the agent vault in the redemption request * NOTE: also checks that redeemer's address is normalized, so the redeemer must normalize their address, * otherwise it will be rejected! * @param _proof proof that the address is invalid * @param _redemptionRequestId id of an existing redemption request */ function rejectInvalidRedemption( IAddressValidity.Proof calldata _proof, uint256 _redemptionRequestId ) external; /** * After paying to the redeemer, the agent must call this method to unlock the collateral * and to make sure that the redeemer cannot demand payment in collateral on timeout. * The same method must be called for any payment status (SUCCESS, FAILED, BLOCKED). * In case of FAILED, it just releases the agent's underlying funds and the redeemer gets paid in collateral * after calling redemptionPaymentDefault. * In case of SUCCESS or BLOCKED, remaining underlying funds and collateral are released to the agent. * If the agent doesn't confirm payment in enough time (several hours, setting * `confirmationByOthersAfterSeconds`), anybody can do it and get rewarded from the agent's vault. * NOTE: may only be called by the owner of the agent vault in the redemption request * except if enough time has passed without confirmation - then it can be called by anybody * @param _payment proof of the underlying payment (must contain exact `value - fee` amount and correct * payment reference) * @param _redemptionRequestId id of an existing redemption request */ function confirmRedemptionPayment( IPayment.Proof calldata _payment, uint256 _redemptionRequestId ) external; /** * If the agent doesn't transfer the redeemed underlying assets in time (until the last allowed block on * the underlying chain), the redeemer calls this method and receives payment in collateral (with some extra). * The agent can also call default if the redeemer is unresponsive, to payout the redeemer and free the * remaining collateral. * NOTE: The attestation request must be done with `checkSourceAddresses=false`. * NOTE: may only be called by the redeemer (= creator of the redemption request), * the executor appointed by the redeemer, * or the agent owner (= owner of the agent vault in the redemption request) * @param _proof proof that the agent didn't pay with correct payment reference on the underlying chain * @param _redemptionRequestId id of an existing redemption request */ function redemptionPaymentDefault( IReferencedPaymentNonexistence.Proof calldata _proof, uint256 _redemptionRequestId ) external; /** * If the agent hasn't performed the payment, the agent can close the redemption request to free underlying funds. * It can be done immediately after the redeemer or agent calls `redemptionPaymentDefault`, * or this method can trigger the default payment without proof, but only after enough time has passed so that * attestation proof of non-payment is not available any more. * NOTE: may only be called by the owner of the agent vault in the redemption request. * @param _proof proof that the attestation query window can not not contain * the payment/non-payment proof anymore * @param _redemptionRequestId id of an existing, but already defaulted, redemption request */ function finishRedemptionWithoutPayment( IConfirmedBlockHeightExists.Proof calldata _proof, uint256 _redemptionRequestId ) external; /** * Returns the data about an ongoing redemption request. * Note: once the redemptions is confirmed, the request is deleted and this method fails. * However, if there is no payment and the redemption defaults, the method works and returns status DEFAULTED. * @param _redemptionRequestId the redemption request id, as used for confirming or defaulting the redemption */ function redemptionRequestInfo( uint256 _redemptionRequestId ) external view returns (RedemptionRequestInfo.Data memory); /** * Agent can "redeem against himself" by calling `selfClose`, which burns agent's own f-assets * and unlocks agent's collateral. The underlying funds backing the f-assets are released * as agent's free underlying funds and can be later withdrawn after announcement. * NOTE: may only be called by the agent vault owner. * @param _agentVault agent vault address * @param _amountUBA amount of f-assets to self-close * @return _closedAmountUBA the actual self-closed amount, may be less than requested if there are not enough * redemption tickets available or the maximum redemption ticket limit is reached */ function selfClose( address _agentVault, uint256 _amountUBA ) external returns (uint256 _closedAmountUBA); //////////////////////////////////////////////////////////////////////////////////// // Redemption queue info /** * Return (part of) the redemption queue. * @param _firstRedemptionTicketId the ticket id to start listing from; if 0, starts from the beginning * @param _pageSize the maximum number of redemption tickets to return * @return _queue the (part of) the redemption queue; maximum length is _pageSize * @return _nextRedemptionTicketId works as a cursor - if the _pageSize is reached and there are more tickets, * it is the first ticket id not returned; if the end is reached, it is 0 */ function redemptionQueue( uint256 _firstRedemptionTicketId, uint256 _pageSize ) external view returns ( RedemptionTicketInfo.Data[] memory _queue, uint256 _nextRedemptionTicketId ); /** * Return (part of) the redemption queue for a specific agent. * @param _agentVault the agent vault address of the queried agent * @param _firstRedemptionTicketId the ticket id to start listing from; if 0, starts from the beginning * @param _pageSize the maximum number of redemption tickets to return * @return _queue the (part of) the redemption queue; maximum length is _pageSize * @return _nextRedemptionTicketId works as a cursor - if the _pageSize is reached and there are more tickets, * it is the first ticket id not returned; if the end is reached, it is 0 */ function agentRedemptionQueue( address _agentVault, uint256 _firstRedemptionTicketId, uint256 _pageSize ) external view returns ( RedemptionTicketInfo.Data[] memory _queue, uint256 _nextRedemptionTicketId ); //////////////////////////////////////////////////////////////////////////////////// // Dust and small ticket management /** * Due to the minting pool fees or after a lot size change by the governance, * it may happen that less than one lot remains on a redemption ticket. This is named "dust" and * can be self closed or liquidated, but not redeemed. However, after several additions, * the total dust can amount to more than one lot. Using this method, the amount, rounded down * to a whole number of lots, can be converted to a new redemption ticket. * NOTE: we do NOT check that the caller is the agent vault owner, since we want to * allow anyone to convert dust to tickets to increase asset fungibility. * NOTE: dust above 1 lot is actually added to ticket at every minting, so this function need * only be called when the agent doesn't have any minting. * @param _agentVault agent vault address */ function convertDustToTicket(address _agentVault) external; /** * If lot size is increased, there may be many tickets less than one lot in the queue. * In extreme cases, this could prevent redemptions, if there weren't any tickets above 1 lot * among the first `maxRedeemedTickets` tickets. * To fix this, call this method. It converts small tickets to dust and when the dust exceeds one lot * adds it to the ticket. * NOTE: this method can be called by the governance or its executor. * @param _firstTicketId if nonzero, the ticket id of starting ticket; if zero, the starting ticket will * be the redemption queue's first ticket id. * When the method finishes, it emits RedemptionTicketsConsolidated event with the nextTicketId * parameter. If it is nonzero, the method should be invoked again with this value as _firstTicketId. */ function consolidateSmallTickets(uint256 _firstTicketId) external; //////////////////////////////////////////////////////////////////////////////////// // Liquidation /** * Checks that the agent's collateral is too low and if true, starts agent's liquidation. * If the agent is already in liquidation, returns the timestamp when liquidation started. * @param _agentVault agent vault address * @return _liquidationStartTs timestamp when liquidation started */ function startLiquidation( address _agentVault ) external returns (uint256 _liquidationStartTs); /** * Burns up to `_amountUBA` f-assets owned by the caller and pays * the caller the corresponding amount of native currency with premium * (premium depends on the liquidation state). * If the agent isn't in liquidation yet, but satisfies conditions, * automatically puts the agent in liquidation status. * @param _agentVault agent vault address * @param _amountUBA the amount of f-assets to liquidate * @return _liquidatedAmountUBA liquidated amount of f-asset * @return _amountPaidVault amount paid to liquidator (in agent's vault collateral) * @return _amountPaidPool amount paid to liquidator (in NAT from pool) */ function liquidate( address _agentVault, uint256 _amountUBA ) external returns ( uint256 _liquidatedAmountUBA, uint256 _amountPaidVault, uint256 _amountPaidPool ); /** * When the agent's collateral reaches the safe level during liquidation, the liquidation * process can be stopped by calling this method. * Full liquidation (i.e. the liquidation triggered by illegal underlying payment) * cannot be stopped. * NOTE: anybody can call. * NOTE: if the method succeeds, the agent's liquidation has ended. * @param _agentVault agent vault address */ function endLiquidation(address _agentVault) external; //////////////////////////////////////////////////////////////////////////////////// // Challenges /** * Called with a proof of payment made from the agent's underlying address, for which * no valid payment reference exists (valid payment references are from redemption and * underlying withdrawal announcement calls). * On success, immediately triggers full agent liquidation and rewards the caller. * @param _payment proof of a transaction from the agent's underlying address * @param _agentVault agent vault address */ function illegalPaymentChallenge( IBalanceDecreasingTransaction.Proof calldata _payment, address _agentVault ) external; /** * Called with proofs of two payments made from the agent's underlying address * with the same payment reference (each payment reference is valid for only one payment). * On success, immediately triggers full agent liquidation and rewards the caller. * @param _payment1 proof of first payment from the agent's underlying address * @param _payment2 proof of second payment from the agent's underlying address * @param _agentVault agent vault address */ function doublePaymentChallenge( IBalanceDecreasingTransaction.Proof calldata _payment1, IBalanceDecreasingTransaction.Proof calldata _payment2, address _agentVault ) external; /** * Called with proofs of several (otherwise legal) payments, which together make the agent's * underlying free balance negative (i.e. the underlying address balance is less than * the total amount of backed f-assets). * On success, immediately triggers full agent liquidation and rewards the caller. * @param _payments proofs of several distinct payments from the agent's underlying address * @param _agentVault agent vault address */ function freeBalanceNegativeChallenge( IBalanceDecreasingTransaction.Proof[] calldata _payments, address _agentVault ) external; }