Description:
Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"@openzeppelin/contracts/interfaces/IERC20Metadata.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";
"
},
"@openzeppelin/contracts/interfaces/IERC4626.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC4626.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";
import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";
/**
* @dev Interface of the ERC-4626 "Tokenized Vault Standard", as defined in
* https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].
*/
interface IERC4626 is IERC20, IERC20Metadata {
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/**
* @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.
*
* - MUST be an ERC-20 token contract.
* - MUST NOT revert.
*/
function asset() external view returns (address assetTokenAddress);
/**
* @dev Returns the total amount of the underlying asset that is “managed” by Vault.
*
* - SHOULD include any compounding that occurs from yield.
* - MUST be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT revert.
*/
function totalAssets() external view returns (uint256 totalManagedAssets);
/**
* @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToShares(uint256 assets) external view returns (uint256 shares);
/**
* @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal
* scenario where all the conditions are met.
*
* - MUST NOT be inclusive of any fees that are charged against assets in the Vault.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.
* - MUST NOT revert.
*
* NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the
* “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and
* from.
*/
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,
* through a deposit call.
*
* - MUST return a limited value if receiver is subject to some deposit limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.
* - MUST NOT revert.
*/
function maxDeposit(address receiver) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit
* call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called
* in the same transaction.
* - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the
* deposit would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewDeposit(uint256 assets) external view returns (uint256 shares);
/**
* @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* deposit execution, and are accounted for during deposit.
* - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.
* - MUST return a limited value if receiver is subject to some mint limit.
* - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.
* - MUST NOT revert.
*/
function maxMint(address receiver) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given
* current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call
* in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the
* same transaction.
* - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint
* would be accepted, regardless if the user has enough tokens approved, etc.
* - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by minting.
*/
function previewMint(uint256 shares) external view returns (uint256 assets);
/**
* @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.
*
* - MUST emit the Deposit event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint
* execution, and are accounted for during mint.
* - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not
* approving enough underlying tokens to the Vault contract, etc).
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.
*/
function mint(uint256 shares, address receiver) external returns (uint256 assets);
/**
* @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the
* Vault, through a withdraw call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxWithdraw(address owner) external view returns (uint256 maxAssets);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw
* call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if
* called
* in the same transaction.
* - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though
* the withdrawal would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by depositing.
*/
function previewWithdraw(uint256 assets) external view returns (uint256 shares);
/**
* @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* withdraw execution, and are accounted for during withdraw.
* - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
/**
* @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,
* through a redeem call.
*
* - MUST return a limited value if owner is subject to some withdrawal limit or timelock.
* - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.
* - MUST NOT revert.
*/
function maxRedeem(address owner) external view returns (uint256 maxShares);
/**
* @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block,
* given current on-chain conditions.
*
* - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
* in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the
* same transaction.
* - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the
* redemption would be accepted, regardless if the user has enough shares, etc.
* - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.
* - MUST NOT revert.
*
* NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in
* share price or some other type of condition, meaning the depositor will lose assets by redeeming.
*/
function previewRedeem(uint256 shares) external view returns (uint256 assets);
/**
* @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.
*
* - MUST emit the Withdraw event.
* - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the
* redeem execution, and are accounted for during redeem.
* - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner
* not having enough shares, etc).
*
* NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.
* Those methods should be performed separately.
*/
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
}
"
},
"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC-20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
"
},
"@openzeppelin/contracts/token/ERC20/IERC20.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
"
},
"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.20;
import {IERC721} from "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}
"
},
"@openzeppelin/contracts/token/ERC721/IERC721.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC-721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC-721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
* {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the address zero.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
"
},
"@openzeppelin/contracts/utils/introspection/IERC165.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
"
},
"contracts/interfaces/IApp.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.28;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IApp is IERC20 {
function mint(address account_, uint256 amount_) external;
function burn(uint256 amount) external;
}
"
},
"contracts/interfaces/IAppConvertibles.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.28;
pragma abicoder v2;
import "./IApp.sol";
import "./IAppOracle.sol";
import "./IOracleV2.sol";
import "./IPermissionedERC20.sol";
import "./IPermissionedERC20Factory.sol";
import "@openzeppelin/contracts/interfaces/IERC4626.sol";
import "@openzeppelin/contracts/interfaces/IERC20Metadata.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
/// @title IAppConvertibles Interface
/// @author RZR Protocol
/// @notice Interface for the RZR Convertibles system
interface IAppConvertibles is IERC721Enumerable {
/// @notice Position data structure for convertible positions
/// @param amountStaked Amount of loan tokens staked in this position
/// @param amountConvertible Amount of RZR tokens convertible in this position
/// @param fixedInterestRate Fixed interest rate per second for this position
/// @param fixedInterestClaimed Amount of interest claimed by user
/// @param lockDuration Lock duration for this position
/// @param lockStartTime Timestamp when the lock period started
/// @param priceConversion Price at which conversion can occur
/// @param priceEntry Price when the position was created
struct Position {
IERC4626 asset;
uint256 amountStaked;
uint256 amountConvertible;
uint256 stakingPower;
uint256 fixedInterestRate;
uint256 fixedInterestClaimed;
uint256 lockDuration;
uint256 lockStartTime;
uint256 priceConversion;
uint256 priceEntry;
}
/// @notice Contract configuration variables
/// @param minConversionPremium Minimum conversion premium (in basis points)
/// @param maxConversionPremium Maximum conversion premium (in basis points)
/// @param minFixedInterestRate Minimum fixed interest rate per second
/// @param maxFixedInterestRate Maximum fixed interest rate per second
struct Variables {
IPermissionedERC20 trackingToken;
uint256 minConversionPremium;
uint256 maxConversionPremium;
uint256 minFixedInterestRate;
uint256 maxFixedInterestRate;
uint256 debtCap;
}
/// @notice Emitted when a user creates a new convertible position
/// @param user The address of the user who staked
/// @param tokenId The NFT token ID for the new position
/// @param amountStaked Amount of loan tokens staked
/// @param amountConvertible Amount of RZR tokens convertible
/// @param lockDuration Lock duration for the position
/// @param priceEntry Price when the position was created
/// @param priceConversion Price at which conversion can occur
/// @param fixedInterestPerSecond Fixed interest rate per second
event Staked(
address indexed user,
uint256 indexed tokenId,
uint256 amountStaked,
uint256 amountConvertible,
uint256 lockDuration,
uint256 priceEntry,
uint256 priceConversion,
uint256 fixedInterestPerSecond
);
/// @notice Emitted when a user converts their convertible position to RZR tokens
/// @param user The address of the user who converted
/// @param tokenId The NFT token ID that was converted
/// @param amountStaked Amount of loan tokens that were staked
/// @param amountConvertible Amount of RZR tokens that were convertible
/// @param twapPrice The TWAP price that triggered the conversion
event Converted(
address indexed user,
uint256 indexed tokenId,
uint256 amountStaked,
uint256 amountConvertible,
uint256 twapPrice
);
/// @notice Emitted when a user redeems their convertible position for loan tokens + interest
/// @param user The address of the user who redeemed
/// @param tokenId The NFT token ID that was redeemed
/// @param amountStaked Amount of loan tokens that were staked
/// @param amountConvertible Amount of RZR tokens that were convertible
/// @param interestAccumulated Amount of interest accumulated and paid out
event Redeemed(
address indexed user,
uint256 indexed tokenId,
uint256 amountStaked,
uint256 amountConvertible,
uint256 interestAccumulated
);
/// @notice Emitted when governance updates the contract variables
/// @param loanToken The loan token that was enabled
/// @param minConversionPremium New minimum conversion premium
/// @param maxConversionPremium New maximum conversion premium
/// @param minFixedInterestRate New minimum fixed interest rate per second
/// @param maxFixedInterestRate New maximum fixed interest rate per second
/// @param debtCap New maximum debt of convertible positions
event VariablesUpdated(
IERC20 indexed loanToken,
uint256 minConversionPremium,
uint256 maxConversionPremium,
uint256 minFixedInterestRate,
uint256 maxFixedInterestRate,
uint256 debtCap
);
/// @notice Emitted when a convertible NFT is transferred between addresses
/// @param from The address transferring the position
/// @param to The address receiving the position
/// @param tokenId The NFT token ID being transferred
/// @param amountStaked Amount of loan tokens staked in the position
/// @param amountConvertible Amount of RZR tokens convertible in the position
event PositionTransferred(
address indexed from,
address indexed to,
uint256 indexed tokenId,
uint256 amountStaked,
uint256 amountConvertible
);
/// @notice Emitted when a convertible position is split into two positions
/// @param user The address of the user who split the position
/// @param originalTokenId The original NFT token ID
/// @param newTokenId The new NFT token ID created from the split
/// @param originalAmountStaked Total amount staked in the original position
/// @param newAmountStaked Amount staked in the new position
/// @param originalAmountConvertible Total amount convertible in the original position
/// @param newAmountConvertible newAmountConvertible Amount convertible in the new position
/// @param percentageE18 The percentage used for the split (in basis points)
event PositionSplit(
address indexed user,
uint256 indexed originalTokenId,
uint256 indexed newTokenId,
uint256 originalAmountStaked,
uint256 newAmountStaked,
uint256 originalAmountConvertible,
uint256 newAmountConvertible,
uint256 percentageE18
);
/// @notice Emitted when a user claims interest from a convertible position
/// @param user The address of the user who claimed interest
/// @param tokenId The NFT token ID that the interest was claimed from
/// @param interestClaimed interestClaimed Amount of interest claimed
event InterestClaimed(address indexed user, uint256 indexed tokenId, uint256 interestClaimed);
/// @notice Emitted when a token is enabled
/// @param token The token that was enabled
event TokenEnabled(address indexed token);
/// @notice Get the claimable interest for a convertible position
/// @param tokenId The NFT token ID that the interest was claimed from
/// @return interestClaimable interestClaimable Amount of interest claimable
/// @return totalInterestClaimed Total amount of interest claimed
function claimableInterest(uint256 tokenId)
external
view
returns (uint256 interestClaimable, uint256 totalInterestClaimed);
/// @notice Claim interest from a convertible position
/// @param tokenId The NFT token ID to claim interest from
/// @param unwrap4626 Whether to unwrap the interest from the 4626 vault
/// @return interestClaimed interestClaimed Amount of interest claimed
/// @return totalInterestClaimed Total amount of interest claimed
function claimInterest(uint256 tokenId, bool unwrap4626)
external
returns (uint256 interestClaimed, uint256 totalInterestClaimed);
/// @notice Maximum lock duration for convertible positions (4 years)
/// @return value The maximum lock duration in seconds
function MAX_LOCK_DURATION() external view returns (uint256 value);
/// @notice Minimum lock duration for convertible positions (30 days)
/// @return value The minimum lock duration in seconds
function MIN_LOCK_DURATION() external view returns (uint256 value);
/// @notice Maximum age of oracle price data before considered stale (1 day)
/// @return value The maximum oracle staleness period in seconds
function MAX_ORACLE_STALENESS() external view returns (uint256 value);
/// @notice Minimum bond duration for convertible positions (7 days)
/// @return value The minimum bond duration in seconds
function MIN_BOND_DURATION() external view returns (uint256 value);
/// @notice The RZR token contract
/// @return rzr rzr The RZR token contract address
function rzr() external view returns (IApp rzr);
/// @notice The tracking token for loan positions
/// @return stakingPowerToken stakingPowerToken The loan tracking token contract address
function stakingPowerToken() external view returns (IPermissionedERC20 stakingPowerToken);
/// @notice The tracking token for RZR convertible positions
/// @return rzrTrackingToken rzrTrackingToken The RZR tracking token contract address
function rzrTrackingToken() external view returns (IPermissionedERC20 rzrTrackingToken);
/// @notice The oracle contract for price feeds
/// @return oracle The oracle contract address
function oracle() external view returns (IAppOracle oracle);
/// @notice The TWAP oracle contract for conversion price validation
/// @return twapOracle The TWAP oracle contract address
function twapOracle() external view returns (IOracleV2 twapOracle);
/// @notice The spot oracle contract for conversion price validation
/// @return spotOracle The spot oracle contract address
function spotOracle() external view returns (IOracleV2 spotOracle);
/// @notice The last issued token ID
/// @return lastId The most recent token ID
function lastId() external view returns (uint256 lastId);
/// @notice The factory contract for creating permissioned ERC20 tokens
/// @return factory factory The factory contract address
function factory() external view returns (IPermissionedERC20Factory factory);
/// @notice Total amount of loan tokens staked across all positions
/// @return totalStaked The total staked amount
function totalStaked(address loanToken) external view returns (uint256 totalStaked);
/// @notice Total amount of RZR tokens convertible across all positions
/// @return totalConvertible The total convertible amount
function totalConvertible() external view returns (uint256 totalConvertible);
/// @notice Contract variables for conversion premiums and interest rates
/// @param _loanToken The loan token that was enabled
/// @return vars The contract variables
function variables(IERC20 _loanToken) external view returns (Variables memory vars);
/// @notice Get position details for a specific token ID
/// @param tokenId The NFT token ID
/// @return position The position details
function positions(uint256 tokenId) external view returns (Position memory position);
/// @notice Initialize the convertibles contract
/// @param _rzr The RZR token contract address
/// @param _oracle The oracle contract address for price feeds
/// @param _spotOracle The spot oracle contract address
/// @param _twapOracle The TWAP oracle contract address
/// @param _authority The authority contract address
function initialize(
address _rzr,
address _oracle,
address _spotOracle,
address _twapOracle,
address _authority,
address _factory
) external;
/// @notice Enable a new loan token for convertible positions
/// @param loanToken The loan token to enable
/// @param _minConversionPremium Minimum conversion premium (in basis points)
/// @param _maxConversionPremium Maximum conversion premium (in basis points)
/// @param _minFixedInterestRate Minimum fixed interest rate per second
/// @param _maxFixedInterestRate Maximum fixed interest rate per second
/// @param _debtCap Maximum debt of convertible positions
function enableToken(
IERC20Metadata loanToken,
uint256 _minConversionPremium,
uint256 _maxConversionPremium,
uint256 _minFixedInterestRate,
uint256 _maxFixedInterestRate,
uint256 _debtCap
) external;
/// @notice Set contract variables (governance only)
/// @param _loanToken The loan token that was enabled
/// @param _minConversionPremium Minimum conversion premium (in basis points)
/// @param _maxConversionPremium Maximum conversion premium (in basis points)
/// @param _minFixedInterestRate Minimum fixed interest rate per second
/// @param _maxFixedInterestRate Maximum fixed interest rate per second
/// @param _debtCap Maximum debt of convertible positions
function setVariables(
IERC20 _loanToken,
uint256 _minConversionPremium,
uint256 _maxConversionPremium,
uint256 _minFixedInterestRate,
uint256 _maxFixedInterestRate,
uint256 _debtCap
) external;
/// @notice Create a new convertible position by staking loan tokens
/// @param amount Amount of loan tokens to stake
/// @param lockDuration Duration to lock the position (must be between MIN and MAX)
/// @param receiver The address to receive the convertible position
/// @return tokenId The NFT token ID for the new position
/// @return conversionPrice Price at which conversion can occur
/// @return conversionAmount Amount of RZR tokens convertible
/// @return fixedInterestRate Fixed interest rate per second
/// @return fixedInterestRateAmount Fixed interest rate amount
/// @return stakingPower Amount of staking power tokens received
function stake(IERC20 loanToken, uint256 amount, uint256 lockDuration, address receiver)
external
returns (
uint256 tokenId,
uint256 conversionPrice,
uint256 conversionAmount,
uint256 fixedInterestRate,
uint256 fixedInterestRateAmount,
uint256 stakingPower
);
/// @notice Convert a convertible position to RZR tokens
/// @param tokenId The NFT token ID to convert
function convert(uint256 tokenId) external;
/// @notice Redeem a convertible position for loan tokens + accumulated interest
/// @param tokenId The NFT token ID to redeem
/// @param unwrap4626 Whether to unwrap the loan tokens from the 4626 vault
function redeem(uint256 tokenId, bool unwrap4626) external;
/// @notice Split a convertible position into two positions
/// @param tokenId The NFT token ID to split
/// @param percentageE18 The percentage to split (0-1e18 representing 0-100%)
function split(uint256 tokenId, uint256 percentageE18) external;
/// @notice Calculate conversion terms for a given amount and lock duration
/// @param loanToken The loan token that was enabled
/// @param amountLoan Amount of loan tokens to stake
/// @param lockDuration Duration to lock the position
/// @return conversionPrice Price at which conversion can occur
/// @return conversionAmount Amount of RZR tokens convertible
/// @return fixedInterestRate Fixed interest rate per second
function getOfferings(IERC20 loanToken, uint256 amountLoan, uint256 lockDuration)
external
view
returns (uint256 conversionPrice, uint256 conversionAmount, uint256 fixedInterestRate);
/// @notice Executes a function on the contract
/// @param target The target contract
/// @param data The data to execute
function execute(address target, bytes memory data) external;
}
"
},
"contracts/interfaces/IAppOracle.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.28;
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
interface IAppOracle {
event OracleUpdated(address indexed token, address indexed oracle, uint256 maxStaleness);
event FloorPriceUpdated(uint256 oldPrice, uint256 newPrice);
event PriceFetched(
address indexed token, uint256 amount, uint256 rzrAmount, uint256 usdAmount, uint256 lastUpdatedAt
);
// Errors
error OracleNotFound(address token);
error OracleAlreadyExists(address token);
error OracleInactive(address token);
error InvalidOracleAddress();
error InvalidTokenAddress();
/// @notice Initializes the AppOracle contract
/// @dev This function is only callable once
/// @param _authority The address of the authority contract
/// @param _app The address of the app contract
function initialize(address _authority, address _app) external;
/**
* @notice Update the oracle for a token
* @param token The token address
* @param oracle The oracle contract
*/
function updateOracle(address token, address oracle, uint256 maxStaleness) external;
/**
* @notice Get the price for a token
* @param token The token address
* @return rzrAmount The token price in RZR
* @return usdAmount The token price in USD
* @return lastUpdatedAt The timestamp of the last update
*/
function getPrice(address token)
external
view
returns (uint256 rzrAmount, uint256 usdAmount, uint256 lastUpdatedAt);
/**
* @notice Get the price for a token in RZR for an amount
* @param token The token address
* @param amount The amount of the token
* @return rzrAmount The token price in RZR for the amount
* @return usdAmount The token price in USD for the amount
* @return lastUpdatedAt The timestamp of the last update
*/
function getPriceForAmount(address token, uint256 amount)
external
view
returns (uint256 rzrAmount, uint256 usdAmount, uint256 lastUpdatedAt);
/**
* @notice Get the price for a token in RZR for an amount in the floor price
* @param token The token address
* @param amount The amount of the token
* @return rzrAmount The token price in RZR for the amount
* @return usdAmount The token price in USD for the amount
* @return lastUpdatedAt The timestamp of the last update
*/
function getPriceForAmountInFloor(address token, uint256 amount)
external
view
returns (uint256 rzrAmount, uint256 usdAmount, uint256 lastUpdatedAt);
/**
* @notice Get the floor price for RZR
* @return price The RZR floor price
*/
function getTokenPrice() external view returns (uint256);
/**
* @notice Set the floor price for RZR
* @param newFloorPrice The new RZR price
*/
function setTokenPrice(uint256 newFloorPrice) external;
}
"
},
"contracts/interfaces/IAppReferrals.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.28;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IAppReferrals {
struct ClaimRewardsInput {
address user;
uint256 amount;
bytes32[] proofs;
}
// Events
event ReferralCodeRegistered(address indexed referrer, bytes8 code);
event ReferralRegistered(address indexed referred, bytes8 indexed referrerCode);
event RewardsClaimed(address indexed user, uint256 amount, bytes32 root);
event ReferralStaked(address indexed user, uint256 amount, uint256 declaredValue, bytes8 referralCode);
event ReferralBondBought(address indexed user, uint256 payout, bytes8 referralCode);
event ReferralStakedIntoLST(address indexed user, uint256 amount, bytes8 referralCode);
event MerkleServerSet(address indexed merkleServer);
event MerkleRootSet(bytes32 indexed merkleRoot);
// Functions
/// @notice Initializes the contract
/// @param _rzr The address of the rzr contract
/// @param _usdr The address of the usdr contract
/// @param _bond4626 The address of the bond4626 contract
/// @param _usdtreasury The address of the usdtreasury contract
/// @param _appTreasury The address of the app treasury contract
/// @param _staking The address of the staking contract
/// @param _staking4626 The address of the staking4626 contract
/// @param _authority The address of the authority
/// @param _allowReferralCodeRegistration The flag to allow referral code registration
function initialize(
address _rzr,
address _usdr,
address _bond4626,
address _usdtreasury,
address _appTreasury,
address _staking,
address _staking4626,
address _authority,
bool _allowReferralCodeRegistration
) external;
/// @notice Gets the referral code for a user
/// @param _user The user to get the referral code for
/// @return referrerCode The referral code for the user
function userToReferralCode(address _user) external view returns (bytes8 referrerCode);
/// @notice Gets the user for a referral code
/// @param _code The referral code to get the user for
/// @return user The user for the referral code
function referralCodeToUser(bytes8 _code) external view returns (address user);
/// @notice Sets the merkle server
/// @param _merkleServer The merkle server address
function setMerkleServer(address _merkleServer) external;
/// @notice Sets the merkle root for the current week
/// @param _merkleRoot The merkle root for the week
function setMerkleRoot(bytes32 _merkleRoot) external;
/// @notice Claims rewards using a merkle proof
/// @param inputs The inputs for the rewards to claim
/// @dev The proofs are the two parts of the merkle proof
function claimRewards(ClaimRewardsInput[] calldata inputs) external;
/// @notice Registers a referral code for the caller
function registerReferralCode(bytes8 code) external;
/// @notice Registers a referral code for the given referrer
/// @param _code The referral code to register
/// @param _referrer The referrer to register the referral code for
function registerReferralCodeFor(bytes8 _code, address _referrer) external;
/// @notice Gets all referrals for a referrer
/// @param referrer The referrer to get referrals for
/// @return referrals Array of addresses that were referred
function getReferrals(address referrer) external view returns (address[] memory referrals);
/// @notice Stakes RZR tokens with a referral code
/// @param amount The amount of RZR tokens to stake
/// @param declaredValue The declared value of the stake
/// @param _referralCode The referral code to use
/// @param _to The address to stake for
/// @return tokenId_ The ID of the created stake position NFT
/// @return taxPaid_ The amount of tax paid
function stakeWithReferral(uint256 amount, uint256 declaredValue, bytes8 _referralCode, address _to)
external
returns (uint256 tokenId_, uint256 taxPaid_);
/// @notice Stakes RZR tokens with a referral code into the LST
/// @param amount The amount of RZR tokens to stake
/// @param _referralCode The referral code to use
/// @param _to The address to stake for
/// @return minted The amount of tokens minted
function stakeIntoLSTWithReferral(uint256 amount, bytes8 _referralCode, address _to)
external
returns (uint256 minted);
/// @notice Buys a bond with a referral code
/// @param _amount The amount of USDR tokens to buy
/// @param _referralCode The referral code to use
/// @param _to The address to buy the bond for
/// @return payout The amount of RZR tokens received
function bondWithReferral(
uint256 _amount,
bytes8 _referralCode,
address _to
) external returns (uint256 payout);
}
"
},
"contracts/interfaces/IAppStaking.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.28;
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./ITotalSupplyOracle.sol";
/// @title IAppStaking
/// @notice Interface for the staking system that allows users to stake RZR tokens and earn rewards
/// @dev This interface extends IERC721Enumerable to provide NFT functionality for staking positions
interface IAppStaking is IERC721Enumerable {
// Structs
/// @notice Represents a staking position
/// @param amount Amount of RZR tokens staked in the position
/// @param declaredValue Self-declared value in RZR for harberger tax
/// @param rewardPerTokenPaid Last reward per token paid to this position
/// @param rewards Accumulated rewards for this position
/// @param withdrawCooldownEnd Timestamp when withdraw cooldown period ends; if 0, position is not in withdraw cooldown
/// @param withdrawCooldownStart Timestamp when withdraw cooldown period starts; if 0, position is not in withdraw cooldown
/// @param buyCooldownEnd Timestamp when buy cooldown period ends; if 0, position is not in buy cooldown
/// @param taxPerSecond Tax rate for this position
/// @param taxCredit Tax credit for this position
/// @param lastTaxCollectionTime Timestamp of last tax collection for this position
struct Position {
uint256 amount;
uint256 declaredValue;
uint256 rewardPerTokenPaid;
uint256 rewards;
uint256 withdrawCooldownEnd;
uint256 withdrawCooldownStart;
uint256 buyCooldownEnd;
uint256 taxPerSecond;
uint256 taxCredit;
uint256 lastTaxCollectionTime;
}
struct Variables {
uint256 harbergerTaxRate;
uint256 resellFeeRate;
uint256 withdrawCooldownPeriod;
uint256 buyCooldownPeriod;
uint256 lowDemandThreshold;
uint256 highDemandThreshold;
uint256 maxDepositFee;
}
/// @notice Emitted when variables are updated
/// @param variables The new variables
event VariablesUpdated(Variables variables);
// Events
/// @notice Emitted when a new staking position is created
/// @param tokenId The ID of the created position NFT
/// @param owner The address of the position owner
/// @param amount The amount of RZR tokens staked
/// @param declaredValue The self-declared value for harberger tax
event PositionCreated(uint256 indexed tokenId, address indexed owner, uint256 amount, uint256 declaredValue);
/// @notice Emitted when a position is migrated
/// @param tokenId The ID of the migrated position NFT
/// @param owner The address of the position owner
/// @param amount The amount of RZR tokens staked
/// @param declaredValue The self-declared value for harberger tax
event PositionMigrated(uint256 indexed tokenId, address indexed owner, uint256 amount, uint256 declaredValue);
/// @notice Emitted when variables are overwritten
/// @param periodFinish The timestamp when the reward period finishes
/// @param rewardRate The reward rate
/// @param lastUpdateTime The timestamp of the last reward update
/// @param rewardPerTokenStored The reward per token stored
/// @param totalStaked The total amount of tokens staked
event VariablesOverwritten(
uint256 periodFinish,
uint256 rewardRate,
uint256 lastUpdateTime,
uint256 rewardPerTokenStored,
uint256 totalStaked
);
/// @notice Emitted when a staking position is sold
/// @param tokenId The ID of the position NFT
/// @param seller The address of the seller
/// @param buyer The address of the buyer
/// @param price The price paid for the position
event PositionSold(uint256 indexed tokenId, address indexed seller, address indexed buyer, uint256 price);
/// @notice Emitted when rewards are claimed from a position
/// @param tokenId The ID of the position NFT
/// @param owner The address of the position owner
/// @param amount The amount of rewards claimed
event RewardsClaimed(uint256 indexed tokenId, address indexed owner, uint256 amount);
/// @notice Emitted when tokens are unstaked from a position
/// @param tokenId The ID of the position NFT
/// @param owner The address of the position owner
/// @param amount The amount of tokens unstaked
event PositionUnstaked(uint256 indexed tokenId, address indexed owner, uint256 amount);
/// @notice Emitted when a position enters cooldown period
/// @param tokenId The ID of the position NFT
/// @param owner The address of the position owner
event CooldownStarted(uint256 indexed tokenId, address indexed owner);
/// @notice Emitted when a position's cooldown period ends
/// @param tokenId The ID of the position NFT
/// @param owner The address of the position owner
event CooldownEnded(uint256 indexed tokenId, address indexed owner);
/// @notice Emitted when a position is updated
/// @param tokenId The ID of the position NFT
/// @param owner The address of the position owner
/// @param newAmount The new amount of tokens staked
/// @param newDeclaredValue The new declared value
event PositionUpdated(uint256 indexed tokenId, address indexed owner, uint256 newAmount, uint256 newDeclaredValue);
/// @notice Emitted when unstaking is cancelled
/// @param tokenId The ID of the position NFT
/// @param owner The address of the position owner
event UnstakingCancelled(uint256 indexed tokenId, address indexed owner);
/// @notice Emitted when new rewards are added to the staking pool
/// @param reward The amount of rewards added
event RewardAdded(uint256 reward);
/// @notice Emitted when rewards are paid to a user
/// @param user The address of the user receiving rewards
/// @param reward The amount of rewards paid
event RewardPaid(address indexed user, uint256 reward);
/// @notice Emitted when upfront tax credit is set for a position
/// @param tokenId The position ID
/// @param creditAmount The amount of upfront tax credit set
event UpfrontTaxCreditSet(uint256 indexed tokenId, uint256 creditAmount);
/// @notice Emitted when upfront tax credit is consumed
/// @param tokenId The position ID
/// @param creditConsumed The amount of credit consumed
/// @param remainingCredit The remaining credit amount
event UpfrontTaxCreditConsumed(uint256 indexed tokenId, uint256 creditConsumed, uint256 remainingCredit);
/// @notice Emitted when a position is split
/// @param originalTokenId The ID of the original position NFT
/// @param newTokenId The ID of the new position NFT
/// @param owner The address of the position owner
/// @param to The address to which the new position is split
/// @param splitAmount The amount of tokens split
/// @param splitDeclaredValue The declared value of the split position
event PositionSplit(
uint256 indexed originalTokenId,
uint256 indexed newTokenId,
address indexed owner,
address to,
uint256 splitAmount,
uint256 splitDeclaredValue
);
/// @notice Emitted when a position is merged
/// @param survivingTokenId The ID of the surviving position NFT
/// @param mergedTokenId The ID of the merged position NFT
/// @param owner The address of the position owner
/// @param newAmount The new amount of tokens staked in the merged position
/// @param newDeclaredValue The new declared value for harberger tax in the merged position
event PositionMerged(
uint256 indexed survivingTokenId,
uint256 indexed mergedTokenId,
address indexed owner,
uint256 newAmount,
uint256 newDeclaredValue
);
/// @notice Emitted when streaming tax is collected from a position
/// @param tokenId The ID of the position NFT
/// @param taxAmount The amount of tax collected
event StreamingTaxCollected(uint256 indexed tokenId, uint256 taxAmount);
/// @notice Emitted when streaming tax rate is updated for a position
/// @param tokenId The ID of the position NFT
/// @param oldRate The old streaming tax rate
/// @param newRate The new streaming tax rate
event StreamingTaxRateUpdated(uint256 indexed tokenId, uint256 oldRate, uint256 newRate);
/// @notice Initializes the staking contract
/// @param _appToken The address of the dre token
/// @param _trackingToken The address of the tracking token
/// @param _authority The address of the authority contract
/// @param _burner The address of the burner contract
function initialize(address _appToken, address _trackingToken, address _authority, address _burner) external;
/// @notice Sets the variables
/// @param _variables The new variables
function setVariables(Variables memory _variables) external;
/// @notice Gets the variables
/// @return The variables
function variables() external view returns (Variables memory);
// View functions
/// @notice Gets the last time rewards were applicable
/// @return The timestamp of the last reward application
function lastTimeRewardApplicable() external view returns (uint256);
/// @notice Gets the current reward per token rate
/// @return The reward per token rate
function rewardPerToken() external view returns (uint256);
/// @notice Gets the earned rewards for a specific position
/// @param tokenId The ID of the position NFT
/// @return The amount of rewards earned
function earned(uint256 tokenId) external view returns (uint256);
/// @notice Gets the total amount of tokens staked
/// @return The total amount of staked tokens
function totalStaked() external view returns (uint256);
// State changing functions
/// @notice Notifies the contract of new rewards to be distributed
/// @param reward The amount of rewards to be distributed
function notifyRewardAmount(uint256 reward) external;
/// @notice Creates a new staking position
/// @param _user The address of the user creating the position
/// @param _amount The amount of tokens to stake
/// @param _declaredValue The self-declared value for harberger tax
/// @param _lockEnd The timestamp when the lock period ends
/// @return tokenId The ID of the created position NFT
/// @return taxPaid The amount of tax paid for the position
function createPosition(address _user, uint256 _amount, uint256 _declaredValue, uint256 _lockEnd)
external
returns (uint256 tokenId, uint256 taxPaid);
/// @notice Starts the unstaking process for a position
/// @param tokenId The ID of the position NFT
function startUnstaking(uint256 tokenId) external;
/// @notice Completes the unstaking process for a position
/// @param tokenId The ID of the position NFT
function completeUnstaking(uint256 tokenId) external;
/// @notice Buys a staking position
/// @param tokenId The ID of the position NFT to buy
function buyPosition(uint256 tokenId) external;
/// @notice Claims rewards from a staking position
/// @param tokenId The ID of the position NFT
/// @return reward The amount of rewards claimed
function claimRewards(uint256 tokenId) external returns (uint256 reward);
/// @notice Increases the amount of tokens staked in a position
/// @param tokenId The ID of the position NFT
/// @param additionalAmount The additional amount of tokens to stake
/// @param addtionalDeclaredValue The additional declared value
/// @return taxPaid The amount of tax paid for the additional amount
function increaseAmount(uint256 tokenId, uint256 additionalAmount, uint256 addtionalDeclaredValue)
external
returns (uint256 taxPaid);
/// @notice Cancels the unstaking process for a position
/// @param tokenId The ID of the position NFT
function cancelUnstaking(uint256 tokenId) external;
/// @notice Gets the details of a staking position
/// @param tokenId The ID of the position NFT
/// @return The position details
function positions(uint256 tokenId) external view returns (Position memory);
/// @notice Sets upfront tax credit for a position (governor only)
/// @param tokenId The position ID
/// @param creditAmount The amount of upfront tax credit to set
function setUpfrontTaxCredit(uint256 tokenId, uint256 creditAmount) external;
/// @notice Gets the remaining upfront tax credit for a position
/// @param tokenId The position ID
/// @return The remaining upfront tax credit
function getUpfrontTaxCredit(uint256 tokenId) external view returns (uint256);
/// @notice Gets the current reward rate
/// @return The current reward rate
function rewardRate() external view returns (uint256);
/// @notice Gets the current reward per token rate
/// @return The current reward per token rate
function rewardPerTokenStored() external view returns (uint256);
/// @notice Gets the last time rewards were applicable
/// @return The timestamp of the last reward application
function lastUpdateTime() external view returns (uint256);
/// @notice Gets the current reward rate
/// @return The current reward rate
function periodFinish() external view returns (uint256);
/// @notice Gets the address of the burner contract
/// @return The address of the burner contract
function burner() external view returns (address);
/// @notice Gets the epoch duration
/// @return The epoch duration
function EPOCH_DURATION() external view returns (uint256);
/// @notice Gets the app token
/// @return The app token
function appToken() external view returns (IERC20);
/// @notice Splits a position into two positions, sending the new position to a specified address
/// @param tokenId The ID of the position to split
/// @param splitRatio The ratio to split the position
/// @param to The address to receive the new position
/// @return newTokenId The ID of the newly created position
function splitPosition(uint256 tokenId, uint256 splitRatio, address to) external returns (uint256 newTokenId);
/// @notice Merges two positions owned by the caller into a single position.
/// @param tokenId1 The ID of the first position NFT (this one will survive).
/// @param tokenId2 The ID of the second position NFT (this one will be burned).
/// @return mergedTokenId The ID of the resulting merged position (equals tokenId1)
function mergePositions(uint256 tokenId1, uint256 tokenId2) external returns (uint256 mergedTokenId);
/// @notice Collects streaming tax from a position
/// @param id The ID of the position NFT
/// @return tax The amount of tax collected
/// @return credit The amount of credit used
function collectStreamingTax(uint256 id) external returns (uint256 tax, uint256 credit);
/// @notice Calculates the streaming tax owed for a position
/// @param id The ID of the position NFT
/// @return tax The amount of tax owed
function calculateStreamingTax(uint256 id) external view returns (uint256 tax);
}
"
},
"contracts/interfaces/IAppTreasury.sol": {
"content": "// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.28;
import "./IAppOracle.sol";
import "./IApp.sol";
interface IAppTreasury {
/**
* @notice Gets the app
* @return app_ The app
*/
function app() external view returns (IApp app_);
/**
* @notice allow approved address to deposit an asset for app
* @param _amount uint256 amount of token to deposit
* @param _token address of token to deposit
Submitted on: 2025-09-20 16:20:00
Comments
Log in to comment.
No comments yet.