Contract Name:
PoolAccountantProxy
Contract Source Code:
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard ERC20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*/
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
mapping(address account => uint256) private _balances;
mapping(address account => mapping(address spender => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `value`.
*/
function transfer(address to, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, value);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `value`.
* - the caller must have allowance for ``from``'s tokens of at least
* `value`.
*/
function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, value);
_transfer(from, to, value);
return true;
}
/**
* @dev Moves a `value` amount of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _transfer(address from, address to, uint256 value) internal {
if (from == address(0)) {
revert ERC20InvalidSender(address(0));
}
if (to == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(from, to, value);
}
/**
* @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
* (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
* this function.
*
* Emits a {Transfer} event.
*/
function _update(address from, address to, uint256 value) internal virtual {
if (from == address(0)) {
// Overflow check required: The rest of the code assumes that totalSupply never overflows
_totalSupply += value;
} else {
uint256 fromBalance = _balances[from];
if (fromBalance < value) {
revert ERC20InsufficientBalance(from, fromBalance, value);
}
unchecked {
// Overflow not possible: value <= fromBalance <= totalSupply.
_balances[from] = fromBalance - value;
}
}
if (to == address(0)) {
unchecked {
// Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
_totalSupply -= value;
}
} else {
unchecked {
// Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
_balances[to] += value;
}
}
emit Transfer(from, to, value);
}
/**
* @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
* Relies on the `_update` mechanism
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _mint(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(address(0), account, value);
}
/**
* @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
* Relies on the `_update` mechanism.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead
*/
function _burn(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
_update(account, address(0), value);
}
/**
* @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}
/**
* @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
*
* By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
* `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
* `Approval` event during `transferFrom` operations.
*
* Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
* true using the following override:
* ```
* function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
* super._approve(owner, spender, value, true);
* }
* ```
*
* Requirements are the same as {_approve}.
*/
function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
if (owner == address(0)) {
revert ERC20InvalidApprover(address(0));
}
if (spender == address(0)) {
revert ERC20InvalidSpender(address(0));
}
_allowances[owner][spender] = value;
if (emitEvent) {
emit Approval(owner, spender, value);
}
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `value`.
*
* Does not update the allowance value in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Does not emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
if (currentAllowance < value) {
revert ERC20InsufficientAllowance(spender, currentAllowance, value);
}
unchecked {
_approve(owner, spender, currentAllowance - value, false);
}
}
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.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 ERC20 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);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
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);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
import "./AcceptableImplementationClaimableAdminStorage.sol";
/**
* @title SafeUpgradeableClaimableAdmin
* @dev based on Compound's Unitroller
* https://github.com/compound-finance/compound-protocol/blob/a3214f67b73310d547e00fc578e8355911c9d376/contracts/Unitroller.sol
*/
contract AcceptableImplementationClaimableAdmin is
AcceptableImplementationClaimableAdminStorage
{
/**
* @notice Emitted when pendingImplementation is changed
*/
event NewPendingImplementation(
address oldPendingImplementation,
address newPendingImplementation
);
/**
* @notice Emitted when pendingImplementation is accepted, which means delegation implementation is updated
*/
event NewImplementation(address oldImplementation, address newImplementation);
/**
* @notice Emitted when pendingAdmin is changed
*/
event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);
/**
* @notice Emitted when pendingAdmin is accepted, which means admin is updated
*/
event NewAdmin(address oldAdmin, address newAdmin);
/*** Admin Functions ***/
function _setPendingImplementation(address newPendingImplementation) public {
require(msg.sender == admin, "not admin");
require(
approvePendingImplementationInternal(newPendingImplementation),
"INVALID_IMPLEMENTATION"
);
address oldPendingImplementation = pendingImplementation;
pendingImplementation = newPendingImplementation;
emit NewPendingImplementation(
oldPendingImplementation,
pendingImplementation
);
}
/**
* @notice Accepts new implementation. msg.sender must be pendingImplementation
* @dev Admin function for new implementation to accept it's role as implementation
*/
function _acceptImplementation() public returns (uint) {
// Check caller is pendingImplementation and pendingImplementation ≠ address(0)
require(
msg.sender == pendingImplementation &&
pendingImplementation != address(0),
"Not the EXISTING pending implementation"
);
// Save current values for inclusion in log
address oldImplementation = implementation;
address oldPendingImplementation = pendingImplementation;
implementation = pendingImplementation;
pendingImplementation = address(0);
emit NewImplementation(oldImplementation, implementation);
emit NewPendingImplementation(
oldPendingImplementation,
pendingImplementation
);
return 0;
}
/**
* @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
* @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.
* @param newPendingAdmin New pending admin.
*/
function _setPendingAdmin(address newPendingAdmin) public {
// Check caller = admin
require(msg.sender == admin, "Not Admin");
// Save current value, if any, for inclusion in log
address oldPendingAdmin = pendingAdmin;
// Store pendingAdmin with value newPendingAdmin
pendingAdmin = newPendingAdmin;
// Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)
emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);
}
/**
* @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin
* @dev Admin function for pending admin to accept role and update admin
*/
function _acceptAdmin() public {
// Check caller is pendingAdmin and pendingAdmin ≠ address(0)
require(
msg.sender == pendingAdmin && pendingAdmin != address(0),
"Not the EXISTING pending admin"
);
// Save current values for inclusion in log
address oldAdmin = admin;
address oldPendingAdmin = pendingAdmin;
// Store admin with value pendingAdmin
admin = pendingAdmin;
// Clear the pending value
pendingAdmin = address(0);
emit NewAdmin(oldAdmin, admin);
emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);
}
constructor(address _initialAdmin) {
admin = _initialAdmin;
emit NewAdmin(address(0), _initialAdmin);
}
/**
* @dev Delegates execution to an implementation contract.
* It returns to the external caller whatever the implementation returns
* or forwards reverts.
*/
fallback() external payable {
// delegate all other functions to current implementation
(bool success, ) = implementation.delegatecall(msg.data);
assembly {
let free_mem_ptr := mload(0x40)
returndatacopy(free_mem_ptr, 0, returndatasize())
switch success
case 0 {
revert(free_mem_ptr, returndatasize())
}
default {
return(free_mem_ptr, returndatasize())
}
}
}
receive() external payable {}
function approvePendingImplementationInternal(
address // _implementation
) internal virtual returns (bool) {
return true;
}
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
contract ClaimableAdminStorage {
/**
* @notice Administrator for this contract
*/
address public admin;
/**
* @notice Pending administrator for this contract
*/
address public pendingAdmin;
/*** Modifiers ***/
modifier onlyAdmin() {
require(msg.sender == admin, "ONLY_ADMIN");
_;
}
/*** Constructor ***/
constructor() {
// Set admin to caller
admin = msg.sender;
}
}
contract AcceptableImplementationClaimableAdminStorage is
ClaimableAdminStorage
{
/**
* @notice Active logic
*/
address public implementation;
/**
* @notice Pending logic
*/
address public pendingImplementation;
}
contract AcceptableRegistryImplementationClaimableAdminStorage is
AcceptableImplementationClaimableAdminStorage
{
/**
* @notice System Registry
*/
address public registry;
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
import "./AcceptableImplementationClaimableAdmin.sol";
import "./IContractRegistryBase.sol";
/**
* @title AcceptableRegistryImplementationClaimableAdmin
*/
contract AcceptableRegistryImplementationClaimableAdmin is
AcceptableImplementationClaimableAdmin,
AcceptableRegistryImplementationClaimableAdminStorage
{
bytes32 public immutable CONTRACT_NAME_HASH;
constructor(
address _registry,
string memory proxyName,
address _initialAdmin
) AcceptableImplementationClaimableAdmin(_initialAdmin) {
registry = _registry;
CONTRACT_NAME_HASH = keccak256(abi.encodePacked(proxyName));
}
function approvePendingImplementationInternal(
address _implementation
) internal view override returns (bool) {
return
IContractRegistryBase(registry).isImplementationValidForProxy(
CONTRACT_NAME_HASH,
_implementation
);
}
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
interface IContractRegistryBase {
function isImplementationValidForProxy(
bytes32 proxyNameHash,
address _implementation
) external view returns (bool);
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;
/**
* @dev only use immutables and constants in this contract
*/
contract CommonScales {
uint256 public constant PRECISION = 1e18; // 18 decimals
uint256 public constant LEVERAGE_SCALE = 100; // 2 decimal points
uint256 public constant FRACTION_SCALE = 100000; // 5 decimal points
uint256 public constant ACCURACY_IMPROVEMENT_SCALE = 1e9;
function calculateLeveragedPosition(
uint256 collateral,
uint256 leverage
) internal pure returns (uint256) {
return (collateral * leverage) / LEVERAGE_SCALE;
}
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
interface IFundingRateModel {
// return value is the "funding paid by heavier side" in PRECISION per OI (heavier side) per second
// e.g : (0.01 * PRECISION) = Paying (heavier) side (as a whole) pays 1% of funding per second for each OI unit
function getFundingRate(
uint256 pairId,
uint256 openInterestLong,
uint256 openInterestShort,
uint256 pairMaxOpenInterest
) external view returns (uint256);
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
interface IInterestRateModel {
// Returns asset/second of interest per borrowed unit
// e.g : (0.01 * PRECISION) = 1% of interest per second
function getBorrowRate(uint256 utilization) external view returns (uint256);
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
import "./LexErrors.sol";
import "./LexPoolAdminEnums.sol";
import "./IPoolAccountantV1.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface LexPoolStructs {
struct PendingDeposit {
uint256 amount;
uint256 minAmountOut;
}
struct PendingRedeem {
uint256 amount;
uint256 minAmountOut;
uint256 maxAmountOut;
}
}
interface LexPoolEvents is LexPoolAdminEnums {
event NewEpoch(
uint256 epochId,
int256 reportedUnrealizedPricePnL,
uint256 exchangeRate,
uint256 virtualUnderlyingBalance,
uint256 totalSupply
);
event AddressUpdated(LexPoolAddressesEnum indexed enumCode, address a);
event NumberUpdated(LexPoolNumbersEnum indexed enumCode, uint value);
event DepositRequest(
address indexed user,
uint256 amount,
uint256 minAmountOut,
uint256 processingEpoch
);
event RedeemRequest(
address indexed user,
uint256 amount,
uint256 minAmountOut,
uint256 processingEpoch
);
event ProcessedDeposit(
address indexed user,
bool deposited,
uint256 depositedAmount
);
event ProcessedRedeem(
address indexed user,
bool redeemed,
uint256 withdrawnAmount // Underlying amount
);
event CanceledDeposit(
address indexed user,
uint256 epoch,
uint256 cancelledAmount
);
event CanceledRedeem(
address indexed user,
uint256 epoch,
uint256 cancelledAmount
);
event ImmediateDepositAllowedToggled(bool indexed value);
event ImmediateDeposit(
address indexed depositor,
uint256 depositAmount,
uint256 mintAmount
);
event ReservesWithdrawn(
address _to,
uint256 interestShare,
uint256 totalFundingShare
);
}
interface ILexPoolFunctionality is
IERC20,
LexPoolStructs,
LexPoolEvents,
LexErrors
{
function setPoolAccountant(
IPoolAccountantFunctionality _poolAccountant
) external;
function setPnlRole(address pnl) external;
function setMaxExtraWithdrawalAmountF(uint256 maxExtra) external;
function setEpochsDelayDeposit(uint256 delay) external;
function setEpochsDelayRedeem(uint256 delay) external;
function setEpochDuration(uint256 duration) external;
function setMinDepositAmount(uint256 amount) external;
function toggleImmediateDepositAllowed() external;
function reduceReserves(
address _to
) external returns (uint256 interestShare, uint256 totalFundingShare);
function requestDeposit(
uint256 amount,
uint256 minAmountOut,
bytes32 domain,
bytes32 referralCode
) external;
function requestDepositViaIntent(
address user,
uint256 amount,
uint256 minAmountOut,
bytes32 domain,
bytes32 referralCode
) external;
function requestRedeem(uint256 amount, uint256 minAmountOut) external;
function requestRedeemViaIntent(
address user,
uint256 amount,
uint256 minAmountOut
) external;
function processDeposit(
address[] memory users
)
external
returns (
uint256 amountDeposited,
uint256 amountCancelled,
uint256 counterDeposited,
uint256 counterCancelled
);
function cancelDeposits(
address[] memory users,
uint256[] memory epochs
) external;
function processRedeems(
address[] memory users
)
external
returns (
uint256 amountRedeemed,
uint256 amountCancelled,
uint256 counterDeposited,
uint256 counterCancelled
);
function cancelRedeems(
address[] memory users,
uint256[] memory epochs
) external;
function nextEpoch(
int256 totalUnrealizedPricePnL
) external returns (uint256 newExchangeRate);
function currentVirtualUtilization() external view returns (uint256);
function currentVirtualUtilization(
uint256 totalBorrows,
uint256 totalReserves,
int256 unrealizedFunding
) external view returns (uint256);
function virtualBalanceForUtilization() external view returns (uint256);
function virtualBalanceForUtilization(
uint256 extraAmount,
int256 unrealizedFunding
) external view returns (uint256);
function underlyingBalanceForExchangeRate() external view returns (uint256);
function sendAssetToTrader(address to, uint256 amount) external;
function isUtilizationForLPsValid() external view returns (bool);
}
interface ILexPoolV1 is ILexPoolFunctionality {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function SELF_UNIT_SCALE() external view returns (uint);
function underlyingDecimals() external view returns (uint256);
function poolAccountant() external view returns (address);
function underlying() external view returns (IERC20);
function tradingFloor() external view returns (address);
function currentEpoch() external view returns (uint256);
function currentExchangeRate() external view returns (uint256);
function nextEpochStartMin() external view returns (uint256);
function epochDuration() external view returns (uint256);
function minDepositAmount() external view returns (uint256);
function epochsDelayDeposit() external view returns (uint256);
function epochsDelayRedeem() external view returns (uint256);
function immediateDepositAllowed() external view returns (bool);
function pendingDeposits(
uint epoch,
address account
) external view returns (PendingDeposit memory);
function pendingRedeems(
uint epoch,
address account
) external view returns (PendingRedeem memory);
function pendingDepositAmount() external view returns (uint256);
function pendingWithdrawalAmount() external view returns (uint256);
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
import "./LexErrors.sol";
import "./ILexPoolV1.sol";
import "./IInterestRateModel.sol";
import "./IFundingRateModel.sol";
import "./TradingEnumsV1.sol";
interface PoolAccountantStructs {
// @note To be used for passing information in function calls
struct PositionRegistrationParams {
uint256 collateral;
uint32 leverage;
bool long;
uint64 openPrice;
uint64 tp;
}
struct PairFunding {
// Slot 0
int256 accPerOiLong; // 32 bytes -- Underlying Decimals
// Slot 1
int256 accPerOiShort; // 32 bytes -- Underlying Decimals
// Slot 2
uint256 lastUpdateTimestamp; // 32 bytes
}
struct TradeInitialAccFees {
// Slot 0
uint256 borrowIndex; // 32 bytes
// Slot 1
int256 funding; // 32 bytes -- underlying units -- Underlying Decimals
}
struct PairOpenInterest {
// Slot 0
uint256 long; // 32 bytes -- underlying units -- Dynamic open interest for long positions
// Slot 1
uint256 short; // 32 bytes -- underlying units -- Dynamic open interest for short positions
}
// This struct is not kept in storage
struct PairFromTo {
string from;
string to;
}
struct Pair {
// Slot 0
uint16 id; // 02 bytes
uint16 groupId; // 02 bytes
uint16 feeId; // 02 bytes
uint32 minLeverage; // 04 bytes
uint32 maxLeverage; // 04 bytes
uint32 maxBorrowF; // 04 bytes -- FRACTION_SCALE (5)
// Slot 1
uint256 maxPositionSize; // 32 bytes -- underlying units
// Slot 2
uint256 maxGain; // 32 bytes -- underlying units
// Slot 3
uint256 maxOpenInterest; // 32 bytes -- Underlying units
// Slot 4
uint256 maxSkew; // 32 bytes -- underlying units
// Slot 5
uint256 minOpenFee; // 32 bytes -- underlying units. MAX_UINT means use the default group level value
// Slot 6
uint256 minPerformanceFee; // 32 bytes -- underlying units
}
struct Group {
// Slot 0
uint16 id; // 02 bytes
uint32 minLeverage; // 04 bytes
uint32 maxLeverage; // 04 bytes
uint32 maxBorrowF; // 04 bytes -- FRACTION_SCALE (5)
// Slot 1
uint256 maxPositionSize; // 32 bytes (Underlying units)
// Slot 2
uint256 minOpenFee; // 32 bytes (Underlying uints). MAX_UINT means use the default global level value
}
struct Fee {
// Slot 0
uint16 id; // 02 bytes
uint32 openFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of leveraged pos)
uint32 closeFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of leveraged pos)
uint32 performanceFeeF; // 04 bytes -- FRACTION_SCALE (5) (Fraction of performance)
}
}
interface PoolAccountantEvents is PoolAccountantStructs {
event PairAdded(
uint256 indexed id,
string indexed from,
string indexed to,
Pair pair
);
event PairUpdated(uint256 indexed id, Pair pair);
event GroupAdded(uint256 indexed id, string indexed groupName, Group group);
event GroupUpdated(uint256 indexed id, Group group);
event FeeAdded(uint256 indexed id, string indexed name, Fee fee);
event FeeUpdated(uint256 indexed id, Fee fee);
event TradeInitialAccFeesStored(
bytes32 indexed positionId,
uint256 borrowIndex,
// uint256 rollover,
int256 funding
);
event AccrueFunding(
uint256 indexed pairId,
int256 valueLong,
int256 valueShort
);
event ProtocolFundingShareAccrued(
uint16 indexed pairId,
uint256 protocolFundingShare
);
// event AccRolloverFeesStored(uint256 pairIndex, uint256 value);
event FeesCharged(
bytes32 indexed positionId,
address indexed trader,
uint16 indexed pairId,
PositionRegistrationParams positionRegistrationParams,
// bool long,
// uint256 collateral, // Underlying Decimals
// uint256 leverage,
int256 profitPrecision, // PRECISION
uint256 interest,
int256 funding, // Underlying Decimals
uint256 closingFee,
uint256 tradeValue
);
event PerformanceFeeCharging(
bytes32 indexed positionId,
uint256 performanceFee
);
event MaxOpenInterestUpdated(uint256 pairIndex, uint256 maxOpenInterest);
event AccrueInterest(
uint256 cash,
uint256 totalInterestNew,
uint256 borrowIndexNew,
uint256 interestShareNew
);
event Borrow(
uint256 indexed pairId,
uint256 borrowAmount,
uint256 newTotalBorrows
);
event Repay(
uint256 indexed pairId,
uint256 repayAmount,
uint256 newTotalBorrows
);
}
interface IPoolAccountantFunctionality is
PoolAccountantStructs,
PoolAccountantEvents,
LexErrors,
TradingEnumsV1
{
function setTradeIncentivizer(address _tradeIncentivizer) external;
function setMaxGainF(uint256 _maxGainF) external;
function setFrm(IFundingRateModel _frm) external;
function setMinOpenFee(uint256 min) external;
function setLexPartF(uint256 partF) external;
function setFundingRateMax(uint256 maxValue) external;
function setLiquidationThresholdF(uint256 threshold) external;
function setLiquidationFeeF(uint256 fee) external;
function setIrm(IInterestRateModel _irm) external;
function setIrmHard(IInterestRateModel _irm) external;
function setInterestShareFactor(uint256 factor) external;
function setFundingShareFactor(uint256 factor) external;
function setBorrowRateMax(uint256 rate) external;
function setMaxTotalBorrows(uint256 maxBorrows) external;
function setMaxVirtualUtilization(uint256 _maxVirtualUtilization) external;
function resetTradersPairGains(uint256 pairId) external;
function addGroup(Group calldata _group) external;
function updateGroup(Group calldata _group) external;
function addFee(Fee calldata _fee) external;
function updateFee(Fee calldata _fee) external;
function addPair(Pair calldata _pair) external;
function addPairs(Pair[] calldata _pairs) external;
function updatePair(Pair calldata _pair) external;
function readAndZeroReserves()
external
returns (uint256 accumulatedInterestShare,
uint256 accFundingShare);
function registerOpenTrade(
bytes32 positionId,
address trader,
uint16 pairId,
uint256 collateral,
uint32 leverage,
bool long,
uint256 tp,
uint256 openPrice
) external returns (uint256 fee, uint256 lexPartFee);
function registerCloseTrade(
bytes32 positionId,
address trader,
uint16 pairId,
PositionRegistrationParams calldata positionRegistrationParams,
uint256 closePrice,
PositionCloseType positionCloseType
)
external
returns (
uint256 closingFee,
uint256 tradeValue,
int256 profitPrecision,
uint finalClosePrice
);
function registerUpdateTp(
bytes32 positionId,
address trader,
uint16 pairId,
uint256 collateral,
uint32 leverage,
bool long,
uint256 openPrice,
uint256 oldTriggerPrice,
uint256 triggerPrice
) external;
// function registerUpdateSl(
// address trader,
// uint256 pairIndex,
// uint256 index,
// uint256 collateral,
// uint256 leverage,
// bool long,
// uint256 openPrice,
// uint256 triggerPrice
// ) external returns (uint256 fee);
function accrueInterest()
external
returns (
uint256 totalInterestNew,
uint256 interestShareNew,
uint256 borrowIndexNew
);
// Limited only for the LexPool
function accrueInterest(
uint256 availableCash
)
external
returns (
uint256 totalInterestNew,
uint256 interestShareNew,
uint256 borrowIndexNew
);
function getTradeClosingValues(
bytes32 positionId,
uint16 pairId,
PositionRegistrationParams calldata positionRegistrationParams,
uint256 closePrice,
bool isLiquidation
)
external
returns (
uint256 tradeValue, // Underlying Decimals
uint256 safeClosingFee,
int256 profitPrecision,
uint256 interest,
int256 funding
);
function getTradeLiquidationPrice(
bytes32 positionId,
uint16 pairId,
uint256 openPrice, // PRICE_SCALE (8)
uint256 tp,
bool long,
uint256 collateral, // Underlying Decimals
uint32 leverage
)
external
returns (
uint256 // PRICE_SCALE (8)
);
function calcTradeDynamicFees(
bytes32 positionId,
uint16 pairId,
bool long,
uint256 collateral,
uint32 leverage,
uint256 openPrice,
uint256 tp
) external returns (uint256 interest, int256 funding);
function unrealizedFunding() external view returns (int256);
function totalBorrows() external view returns (uint256);
function interestShare() external view returns (uint256);
function fundingShare() external view returns (uint256);
function totalReservesView() external view returns (uint256);
function borrowsAndInterestShare()
external
view
returns (uint256 totalBorrows, uint256 totalInterestShare);
function pairTotalOpenInterest(
uint256 pairIndex
) external view returns (int256);
function pricePnL(
uint256 pairId,
uint256 price
) external view returns (int256);
function getAllSupportedPairIds() external view returns (uint16[] memory);
function getAllSupportedGroupsIds() external view returns (uint16[] memory);
function getAllSupportedFeeIds() external view returns (uint16[] memory);
}
interface IPoolAccountantV1 is IPoolAccountantFunctionality {
function totalBorrows() external view returns (uint256);
function maxTotalBorrows() external view returns (uint256);
function pairBorrows(uint256 pairId) external view returns (uint256);
function groupBorrows(uint256 groupId) external view returns (uint256);
function pairMaxBorrow(uint16 pairId) external view returns (uint256);
function groupMaxBorrow(uint16 groupId) external view returns (uint256);
function lexPool() external view returns (ILexPoolV1);
function maxGainF() external view returns (uint256);
function interestShareFactor() external view returns (uint256);
function fundingShareFactor() external view returns (uint256);
function frm() external view returns (IFundingRateModel);
function irm() external view returns (IInterestRateModel);
function pairs(uint16 pairId) external view returns (Pair memory);
function groups(uint16 groupId) external view returns (Group memory);
function fees(uint16 feeId) external view returns (Fee memory);
function openInterestInPair(
uint pairId
) external view returns (PairOpenInterest memory);
function minOpenFee() external view returns (uint256);
function liquidationThresholdF() external view returns (uint256);
function liquidationFeeF() external view returns (uint256);
function lexPartF() external view returns (uint256);
function tradersPairGains(uint256 pairId) external view returns (int256);
function calcBorrowAmount(
uint256 collateral,
uint256 leverage,
bool long,
uint256 openPrice,
uint256 tp
) external pure returns (uint256);
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
import "./TradingFloorStructsV1.sol";
import "./IPoolAccountantV1.sol";
import "./ILexPoolV1.sol";
interface ITradingFloorV1Functionality is TradingFloorStructsV1 {
function supportNewSettlementAsset(
address _asset,
address _lexPool,
address _poolAccountant
) external;
function getPositionTriggerInfo(
bytes32 _positionId
)
external
view
returns (
PositionPhase positionPhase,
uint64 timestamp,
uint16 pairId,
bool long,
uint32 spreadReductionF
);
function getPositionPortalInfo(
bytes32 _positionId
)
external
view
returns (
PositionPhase positionPhase,
uint64 inPhaseSince,
address positionTrader
);
function storePendingPosition(
OpenOrderType _orderType,
PositionRequestIdentifiers memory _requestIdentifiers,
PositionRequestParams memory _requestParams,
uint32 _spreadReductionF
) external returns (bytes32 positionId);
function setOpenedPositionToMarketClose(
bytes32 _positionId,
uint64 _minPrice,
uint64 _maxPrice
) external;
function cancelPendingPosition(
bytes32 _positionId,
OpenOrderType _orderType,
uint feeFraction
) external;
function cancelMarketCloseForPosition(
bytes32 _positionId,
CloseOrderType _orderType,
uint feeFraction
) external;
function updatePendingPosition_openLimit(
bytes32 _positionId,
uint64 _minPrice,
uint64 _maxPrice,
uint64 _tp,
uint64 _sl
) external;
function openNewPosition_market(
bytes32 _positionId,
uint64 assetEffectivePrice,
uint256 feeForCancellation
) external;
function openNewPosition_limit(
bytes32 _positionId,
uint64 assetEffectivePrice,
uint256 feeForCancellation
) external;
function closeExistingPosition_Market(
bytes32 _positionId,
uint64 assetPrice,
uint64 effectivePrice
) external;
function closeExistingPosition_Limit(
bytes32 _positionId,
LimitTrigger limitTrigger,
uint64 assetPrice,
uint64 effectivePrice
) external;
// Manage open trade
function updateOpenedPosition(
bytes32 _positionId,
PositionField updateField,
uint64 fieldValue,
uint64 effectivePrice
) external;
// Fees
function collectFee(address _asset, FeeType _feeType, address _to) external;
}
interface ITradingFloorV1 is ITradingFloorV1Functionality {
function PRECISION() external pure returns (uint);
// *** Views ***
function pairTradersArray(
address _asset,
uint _pairIndex
) external view returns (address[] memory);
function generatePositionHashId(
address settlementAsset,
address trader,
uint16 pairId,
uint32 index
) external pure returns (bytes32 hashId);
// *** Public Storage addresses ***
function lexPoolForAsset(address asset) external view returns (ILexPoolV1);
function poolAccountantForAsset(
address asset
) external view returns (IPoolAccountantV1);
function registry() external view returns (address);
// *** Public Storage params ***
function positionsById(bytes32 id) external view returns (Position memory);
function positionIdentifiersById(
bytes32 id
) external view returns (PositionIdentifiers memory);
function positionLimitsInfoById(
bytes32 id
) external view returns (PositionLimitsInfo memory);
function triggerPricesById(
bytes32 id
) external view returns (PositionTriggerPrices memory);
function pairTradersInfo(
address settlementAsset,
address trader,
uint pairId
) external view returns (PairTraderInfo memory);
function spreadReductionsP(uint) external view returns (uint);
function maxSlF() external view returns (uint);
function maxTradesPerPair() external view returns (uint);
function maxSanityProfitF() external view returns (uint);
function feesMap(
address settlementAsset,
FeeType feeType
) external view returns (uint256);
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
interface LexErrors {
enum CapType {
NONE, // 0
MIN_OPEN_FEE, // 1
MAX_POS_SIZE_PAIR, // 2
MAX_POS_SIZE_GROUP, // 3
MAX_LEVERAGE, // 4
MIN_LEVERAGE, // 5
MAX_VIRTUAL_UTILIZATION, // 6
MAX_OPEN_INTEREST, // 7
MAX_ABS_SKEW, // 8
MAX_BORROW_PAIR, // 9
MAX_BORROW_GROUP, // 10
MIN_DEPOSIT_AMOUNT, // 11
MAX_ACCUMULATED_GAINS, // 12
BORROW_RATE_MAX, // 13
FUNDING_RATE_MAX, // 14
MAX_POTENTIAL_GAIN, // 15
MAX_TOTAL_BORROW, // 16
MIN_PERFORMANCE_FEE // 17
//...
}
error CapError(CapType, uint256 value);
}
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;
interface LexPoolAdminEnums {
enum LexPoolAddressesEnum {
none,
poolAccountant,
pnlRole
}
enum LexPoolNumbersEnum {
none,
maxExtraWithdrawalAmountF,
epochsDelayDeposit,
epochsDelayRedeem,
epochDuration,
minDepositAmount
}
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
interface TradingEnumsV1 {
enum PositionPhase {
NONE,
OPEN_MARKET,
OPEN_LIMIT,
OPENED,
CLOSE_MARKET,
CLOSED
}
enum OpenOrderType {
NONE,
MARKET,
LIMIT
}
enum CloseOrderType {
NONE,
MARKET
}
enum FeeType {
NONE,
OPEN_FEE,
CLOSE_FEE,
TRIGGER_FEE
}
enum LimitTrigger {
NONE,
TP,
SL,
LIQ
}
enum PositionField {
NONE,
TP,
SL
}
enum PositionCloseType {
NONE,
TP,
SL,
LIQ,
MARKET
}
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
import "./TradingEnumsV1.sol";
interface TradingFloorStructsV1 is TradingEnumsV1 {
enum AdminNumericParam {
NONE,
MAX_TRADES_PER_PAIR,
MAX_SL_F,
MAX_SANITY_PROFIT_F
}
/**
* @dev Memory struct for identifiers
*/
struct PositionRequestIdentifiers {
address trader;
uint16 pairId;
address settlementAsset;
uint32 positionIndex;
}
struct PositionRequestParams {
bool long;
uint256 collateral; // Settlement Asset Decimals
uint32 leverage;
uint64 minPrice; // PRICE_SCALE
uint64 maxPrice; // PRICE_SCALE
uint64 tp; // PRICE_SCALE
uint64 sl; // PRICE_SCALE
uint64 tpByFraction; // FRACTION_SCALE
uint64 slByFraction; // FRACTION_SCALE
}
/**
* @dev Storage struct for identifiers
*/
struct PositionIdentifiers {
// Slot 0
address settlementAsset; // 20 bytes
uint16 pairId; // 02 bytes
uint32 index; // 04 bytes
// Slot 1
address trader; // 20 bytes
}
struct Position {
// Slot 0
uint collateral; // 32 bytes -- Settlement Asset Decimals
// Slot 1
PositionPhase phase; // 01 bytes
uint64 inPhaseSince; // 08 bytes
uint32 leverage; // 04 bytes
bool long; // 01 bytes
uint64 openPrice; // 08 bytes -- PRICE_SCALE (8)
uint32 spreadReductionF; // 04 bytes -- FRACTION_SCALE (5)
}
/**
* Holds the non liquidation limits for the position
*/
struct PositionLimitsInfo {
uint64 tpLastUpdated; // 08 bytes -- timestamp
uint64 slLastUpdated; // 08 bytes -- timestamp
uint64 tp; // 08 bytes -- PRICE_SCALE (8)
uint64 sl; // 08 bytes -- PRICE_SCALE (8)
}
/**
* Holds the prices for opening (and market closing) of a position
*/
struct PositionTriggerPrices {
uint64 minPrice; // 08 bytes -- PRICE_SCALE
uint64 maxPrice; // 08 bytes -- PRICE_SCALE
uint64 tpByFraction; // 04 bytes -- FRACTION_SCALE
uint64 slByFraction; // 04 bytes -- FRACTION_SCALE
}
/**
* @dev administration struct, used to keep tracks on the 'PairTraders' list and
* to limit the amount of positions a trader can have
*/
struct PairTraderInfo {
uint32 positionsCounter; // 04 bytes
uint32 positionInArray; // 04 bytes (the index + 1)
// Note : Can add more fields here
}
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
import "../../AdministrationContracts/AcceptableImplementationClaimableAdminStorage.sol";
import "../interfaces/ITradingFloorV1.sol";
import "../Common/CommonScales.sol";
/**
* @title LexCommon
* @dev For Lex contracts to inherit from, holding common variables and modifiers
*/
contract LexCommon is
CommonScales,
AcceptableRegistryImplementationClaimableAdminStorage
{
IERC20 public underlying;
ITradingFloorV1 public tradingFloor;
function initializeLexCommon(
ITradingFloorV1 _tradingFloor,
IERC20 _underlying
) public {
require(
address(tradingFloor) == address(0) && address(underlying) == address(0),
"Initialized"
);
tradingFloor = _tradingFloor;
underlying = _underlying;
}
modifier onlyTradingFloor() {
require(msg.sender == address(tradingFloor), "TRADING_FLOOR_ONLY");
_;
}
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/**
* @title LexERC20
* @dev simple erc20 contract.
* @notice This is the token that is issued against the deposited funds.
* The value of the token is represented by the exchange rate of the pool.
*/
contract LexERC20 is IERC20 {
mapping(address => uint256) internal _balances;
mapping(address => mapping(address => uint256)) internal _allowances;
uint256 public totalSupply;
string public name;
string public symbol;
function initializeLexERC20(
string memory _name,
string memory _symbol
) public {
require(
bytes(name).length == 0 && bytes(symbol).length == 0,
"Initialized"
);
name = _name;
symbol = _symbol;
}
function decimals() public pure returns (uint8) {
return 18;
}
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public returns (bool) {
_transfer(msg.sender, recipient, amount);
return true;
}
function allowance(
address owner,
address spender
) public view returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public returns (bool) {
_approve(msg.sender, spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][msg.sender];
require(
currentAllowance >= amount,
"ERC20: transfer amount exceeds allowance"
);
unchecked {
_approve(sender, msg.sender, currentAllowance - amount);
}
return true;
}
function _transfer(
address sender,
address recipient,
uint256 amount
) internal {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal {
require(account != address(0), "ERC20: mint to the zero address");
totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal {
require(account != address(0), "ERC20: burn from the zero address");
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
totalSupply -= amount;
emit Transfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "../LexCommon.sol";
import "./LexERC20.sol";
/**
* @title LexPoolStorage
* @dev Storage contract for LexPool
*/
abstract contract LexPoolStorage is LexCommon, LexERC20, LexPoolStructs {
uint256 public underlyingDecimals;
// ***** Roles *****
IPoolAccountantFunctionality public poolAccountant;
address public pnlRole;
// ***** Depositing and Withdrawing *****
// epoch => user => PendingDeposit
mapping(uint256 => mapping(address => PendingDeposit)) public pendingDeposits;
// epoch => user => PendingRedeem
mapping(uint256 => mapping(address => PendingRedeem)) public pendingRedeems;
// epoch => users who deposits on this epoch
mapping(uint256 => address[]) public pendingDepositorsArr;
// epoch => users who redeems on this epoch
mapping(uint256 => address[]) public pendingRedeemersArr;
uint256 public pendingDepositAmount;
uint256 public pendingWithdrawalAmount;
// Extra fraction allowed to be withdrawn when redeem processes
uint256 public maxExtraWithdrawalAmountF;
uint256 public minDepositAmount;
// ***** Epochs *****
uint256 public currentEpoch;
uint256 public nextEpochStartMin; // Minimum timestamp that calling nextEpoch will be possible
uint256 public currentExchangeRate;
uint256 public epochsDelayDeposit;
uint256 public epochsDelayRedeem;
uint256 public epochDuration;
// ***** Flags *****
bool public immediateDepositAllowed;
function initializeLexPoolStorage(
ITradingFloorV1 _tradingFloor,
ERC20 _underlying,
uint _epochDuration
) internal {
initializeLexERC20(
string.concat("Lynx LP ", _underlying.symbol()),
string.concat("lx", _underlying.symbol())
);
initializeLexCommon(_tradingFloor, IERC20(_underlying));
underlyingDecimals = _underlying.decimals();
epochDuration = _epochDuration;
}
}
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.24;
import "../../../AdministrationContracts/AcceptableRegistryImplementationClaimableAdmin.sol";
import "../LexPool/LexPoolStorage.sol";
/**
* @title LexPoolProxy
* @dev Used as the upgradable lex pool of the Lynx platform
*/
contract PoolAccountantProxy is AcceptableRegistryImplementationClaimableAdmin {
constructor(
address _registry,
address _initialAdmin
)
AcceptableRegistryImplementationClaimableAdmin(
_registry,
"PoolAccountant",
_initialAdmin
)
{}
}