// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public immutable decimals;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
// Unchecked because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
// Cannot underflow because a user's balance
// will never be larger than the total supply.
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
import {SafeTransferLib} from "../utils/SafeTransferLib.sol";
import {FixedPointMathLib} from "../utils/FixedPointMathLib.sol";
/// @notice Minimal ERC4626 tokenized Vault implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/mixins/ERC4626.sol)
abstract contract ERC4626 is ERC20 {
using SafeTransferLib for ERC20;
using FixedPointMathLib for uint256;
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed caller,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
/*//////////////////////////////////////////////////////////////
IMMUTABLES
//////////////////////////////////////////////////////////////*/
ERC20 public immutable asset;
constructor(
ERC20 _asset,
string memory _name,
string memory _symbol
) ERC20(_name, _symbol, _asset.decimals()) {
asset = _asset;
}
/*//////////////////////////////////////////////////////////////
DEPOSIT/WITHDRAWAL LOGIC
//////////////////////////////////////////////////////////////*/
function deposit(uint256 assets, address receiver) public virtual returns (uint256 shares) {
// Check for rounding error since we round down in previewDeposit.
require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES");
// Need to transfer before minting or ERC777s could reenter.
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
afterDeposit(assets, shares);
}
function mint(uint256 shares, address receiver) public virtual returns (uint256 assets) {
assets = previewMint(shares); // No need to check for rounding error, previewMint rounds up.
// Need to transfer before minting or ERC777s could reenter.
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
afterDeposit(assets, shares);
}
function withdraw(
uint256 assets,
address receiver,
address owner
) public virtual returns (uint256 shares) {
shares = previewWithdraw(assets); // No need to check for rounding error, previewWithdraw rounds up.
if (msg.sender != owner) {
uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
}
beforeWithdraw(assets, shares);
_burn(owner, shares);
emit Withdraw(msg.sender, receiver, owner, assets, shares);
asset.safeTransfer(receiver, assets);
}
function redeem(
uint256 shares,
address receiver,
address owner
) public virtual returns (uint256 assets) {
if (msg.sender != owner) {
uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
}
// Check for rounding error since we round down in previewRedeem.
require((assets = previewRedeem(shares)) != 0, "ZERO_ASSETS");
beforeWithdraw(assets, shares);
_burn(owner, shares);
emit Withdraw(msg.sender, receiver, owner, assets, shares);
asset.safeTransfer(receiver, assets);
}
/*//////////////////////////////////////////////////////////////
ACCOUNTING LOGIC
//////////////////////////////////////////////////////////////*/
function totalAssets() public view virtual returns (uint256);
function convertToShares(uint256 assets) public view virtual returns (uint256) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.
return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets());
}
function convertToAssets(uint256 shares) public view virtual returns (uint256) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.
return supply == 0 ? shares : shares.mulDivDown(totalAssets(), supply);
}
function previewDeposit(uint256 assets) public view virtual returns (uint256) {
return convertToShares(assets);
}
function previewMint(uint256 shares) public view virtual returns (uint256) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.
return supply == 0 ? shares : shares.mulDivUp(totalAssets(), supply);
}
function previewWithdraw(uint256 assets) public view virtual returns (uint256) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.
return supply == 0 ? assets : assets.mulDivUp(supply, totalAssets());
}
function previewRedeem(uint256 shares) public view virtual returns (uint256) {
return convertToAssets(shares);
}
/*//////////////////////////////////////////////////////////////
DEPOSIT/WITHDRAWAL LIMIT LOGIC
//////////////////////////////////////////////////////////////*/
function maxDeposit(address) public view virtual returns (uint256) {
return type(uint256).max;
}
function maxMint(address) public view virtual returns (uint256) {
return type(uint256).max;
}
function maxWithdraw(address owner) public view virtual returns (uint256) {
return convertToAssets(balanceOf[owner]);
}
function maxRedeem(address owner) public view virtual returns (uint256) {
return balanceOf[owner];
}
/*//////////////////////////////////////////////////////////////
INTERNAL HOOKS LOGIC
//////////////////////////////////////////////////////////////*/
function beforeWithdraw(uint256 assets, uint256 shares) internal virtual {}
function afterDeposit(uint256 assets, uint256 shares) internal virtual {}
}
/**
* Created by Pragma Labs
* SPDX-License-Identifier: BUSL-1.1
*/
pragma solidity 0.8.22;
library LiquidatorErrors {
// Thrown when the liquidateAccount function is called on an Account that is already in an auction.
error AuctionOngoing();
// Thrown when cutOffTime is above the maximum value.
error CutOffTooHigh();
// Thrown when cutOffTime is below the minimum value.
error CutOffTooLow();
// Thrown if the auction was not successfully ended.
error EndAuctionFailed();
// Thrown when halfLifeTime is above the maximum value.
error HalfLifeTimeTooHigh();
// Thrown when halfLifeTime is below the minimum value.
error HalfLifeTimeTooLow();
// Thrown when the auction has not yet expired.
error InvalidBid();
// Thrown when account specified is not an Arcadia Account.
error IsNotAnAccount();
// Thrown when the start price multiplier is above the maximum value.
error MultiplierTooHigh();
// Thrown when the start price multiplier is below the minimum value.
error MultiplierTooLow();
// Thrown when an Account is not for sale.
error NotForSale();
// Thrown when not authorized.
error NotAuthorized();
// Thrown when the sequencer uptime oracle is not reverting.
error OracleNotReverting();
// Thrown when the sequencer uptime oracle is reverting.
error OracleReverting();
// Thrown when the sequencer is down.
error SequencerDown();
}
library DebtTokenErrors {
// Thrown when function called has not be implemented.
error FunctionNotImplemented();
// Thrown when amount of asset would represent zero shares.
error ZeroShares();
}
library LendingPoolErrors {
// Thrown when amount available to withdraw of an asset is less than amount requested to withdraw.
error AmountExceedsBalance();
// Thrown when an auction is in process.
error AuctionOngoing();
// Thrown when an Account would become unhealthy OR the creditor of the Account is not the specific lending pool OR the Account version would not be valid.
error InvalidVersion();
// Thrown when account specified is not an Arcadia Account.
error IsNotAnAccount();
// Thrown when an account has zero debt.
error IsNotAnAccountWithDebt();
// Thrown when liquidation weights are above maximum value.
error LiquidationWeightsTooHigh();
// Thrown when a specific tranche does not exist.
error NonExistingTranche();
// Thrown when address has an open position
error OpenPositionNonZero();
// Thrown when the tranche of the lending pool already exists.
error TrancheAlreadyExists();
// Thrown when caller is not authorized.
error Unauthorized();
// Thrown when asset amount in input is zero.
error ZeroAmount();
}
library TrancheErrors {
// Thrown when a tranche is locked.
error Locked();
// Thrown when amount of shares would represent zero assets.
error ZeroAssets();
// Thrown when an auction is in process.
error AuctionOngoing();
// Thrown when caller is not valid.
error Unauthorized();
// Thrown when amount of asset would represent zero shares.
error ZeroShares();
}
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
library FixedPointMathLib {
/*//////////////////////////////////////////////////////////////
SIMPLIFIED FIXED POINT OPERATIONS
//////////////////////////////////////////////////////////////*/
uint256 internal constant MAX_UINT256 = 2 ** 256 - 1;
uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.
/*//////////////////////////////////////////////////////////////
LOW LEVEL FIXED POINT OPERATIONS
//////////////////////////////////////////////////////////////*/
function mulDivDown(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) { revert(0, 0) }
// Divide x * y by the denominator.
z := div(mul(x, y), denominator)
}
}
function mulDivUp(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) { revert(0, 0) }
// If x * y modulo the denominator is strictly greater than 0,
// 1 is added to round up the division of x * y by the denominator.
z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))
}
}
/*//////////////////////////////////////////////////////////////
GENERAL NUMBER UTILITIES
//////////////////////////////////////////////////////////////*/
}
/**
* Created by Pragma Labs
* SPDX-License-Identifier: MIT
*/
pragma solidity 0.8.22;
interface IGuardian {
/**
* @notice Returns if Withdrawals are paused or not.
* @return bool indicating if Withdrawals are paused or not.
*/
function withdrawPaused() external view returns (bool);
/**
* @notice Returns if Deposits are paused or not.
* @return bool indicating if Deposits are paused or not.
*/
function depositPaused() external view returns (bool);
}
/**
* Created by Pragma Labs
* SPDX-License-Identifier: MIT
*/
pragma solidity 0.8.22;
interface ILendingPool {
/**
* @notice Returns the total redeemable amount of liquidity in the underlying asset.
* @return totalLiquidity The total redeemable amount of liquidity in the underlying asset.
*/
function totalLiquidity() external view returns (uint256);
/**
* @notice Deposit assets in the Lending Pool.
* @param assets The amount of assets of the underlying ERC-20 token being deposited.
* @param from The address of the Liquidity Provider who deposits the underlying ERC-20 token via a Tranche.
*/
function depositInLendingPool(uint256 assets, address from) external;
/**
* @notice Withdraw assets from the Lending Pool.
* @param assets The amount of assets of the underlying ERC-20 tokens being withdrawn.
* @param receiver The address of the receiver of the underlying ERC-20 tokens.
*/
function withdrawFromLendingPool(uint256 assets, address receiver) external;
/**
* @notice Returns the redeemable amount of liquidity in the underlying asset of an address.
* @param owner The address of the liquidity provider.
* @return assets The redeemable amount of liquidity in the underlying asset.
*/
function liquidityOf(address owner) external view returns (uint256);
/**
* @notice liquidityOf, but syncs the unrealised interest first.
* @param owner The address of the liquidity provider.
* @return assets The redeemable amount of liquidity in the underlying asset.
*/
function liquidityOfAndSync(address owner) external returns (uint256);
/**
* @notice Repays debt via an auction.
* @param startDebt The amount of debt of the Account the moment the liquidation was initiated.
* @param minimumMargin The minimum margin of the Account.
* @param minimumMargin The minimum margin of the Account.
* @param amount The amount of debt repaid by a bidder during the auction.
* @param account The contract address of the Arcadia Account backing the loan.
* @param bidder The address of the bidder.
* @return earlyTerminate Bool indicating of the full amount of debt was repaid.
*/
function auctionRepay(uint256 startDebt, uint256 minimumMargin, uint256 amount, address account, address bidder)
external
returns (bool);
/**
* @notice Settles the liquidation process for a specific Account.
* @param account The address of the Account undergoing liquidation settlement.
* @param startDebt The initial debt amount of the liquidated Account.
* @param minimumMargin The minimum margin of the Account.
* @param terminator The address of the liquidation terminator.
*/
function settleLiquidationHappyFlow(address account, uint256 startDebt, uint256 minimumMargin, address terminator)
external;
/**
* @notice Settles the liquidation process for a specific Account.
* @param account The address of the Account undergoing liquidation settlement.
* @param startDebt The initial debt amount of the liquidated Account.
* @param minimumMargin The minimum margin of the Account.
* @param terminator The address of the liquidation terminator.
*/
function settleLiquidationUnhappyFlow(address account, uint256 startDebt, uint256 minimumMargin, address terminator)
external;
}
/**
* Created by Pragma Labs
* SPDX-License-Identifier: MIT
*/
pragma solidity 0.8.22;
interface ITranche {
/**
* @notice Locks the tranche in case all liquidity of the tranche is written of due to bad debt.
*/
function lock() external;
/**
* @notice Locks the tranche while an auction is in progress.
* @param auctionInProgress Flag indicating if there are auctions in progress.
*/
function setAuctionInProgress(bool auctionInProgress) external;
}
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event OwnershipTransferred(address indexed user, address indexed newOwner);
/*//////////////////////////////////////////////////////////////
OWNERSHIP STORAGE
//////////////////////////////////////////////////////////////*/
address public owner;
modifier onlyOwner() virtual {
require(msg.sender == owner, "UNAUTHORIZED");
_;
}
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(address _owner) {
owner = _owner;
emit OwnershipTransferred(address(0), _owner);
}
/*//////////////////////////////////////////////////////////////
OWNERSHIP LOGIC
//////////////////////////////////////////////////////////////*/
function transferOwnership(address newOwner) public virtual onlyOwner {
owner = newOwner;
emit OwnershipTransferred(msg.sender, newOwner);
}
}
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
/*//////////////////////////////////////////////////////////////
ETH OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferETH(address to, uint256 amount) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Transfer the ETH and store if it succeeded or not.
success := call(gas(), to, amount, 0, 0, 0, 0)
}
require(success, "ETH_TRANSFER_FAILED");
}
/*//////////////////////////////////////////////////////////////
ERC20 OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument.
mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
require(success, "TRANSFER_FROM_FAILED");
}
function safeTransfer(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "TRANSFER_FAILED");
}
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "APPROVE_FAILED");
}
}
/**
* Created by Pragma Labs
* SPDX-License-Identifier: BUSL-1.1
*/
pragma solidity 0.8.22;
import { Owned } from "../lib/solmate/src/auth/Owned.sol";
import { ERC4626 } from "../lib/solmate/src/mixins/ERC4626.sol";
import { ILendingPool } from "./interfaces/ILendingPool.sol";
import { FixedPointMathLib } from "../lib/solmate/src/utils/FixedPointMathLib.sol";
import { ITranche } from "./interfaces/ITranche.sol";
import { IGuardian } from "./interfaces/IGuardian.sol";
import { TrancheErrors } from "./libraries/Errors.sol";
/**
* @title Tranche
* @author Pragma Labs
* @notice Each Lending Pool has one or more Tranche(s).
* Different Tranches receive different yields, but also have different protections against losses due to bad debt:
* In general the most junior Tranche will have the highest yield,
* but it will be the first Tranche to absorb losses when liquidations result in bad debt.
* The Liquidity Providers do not provide Liquidity directly to the Lending Pool, but via a Tranche.
* As such Liquidity Providers with different risk/reward preferences can provide liquidity to the same Lending Pool
* (benefitting borrowers with deeper liquidity), but via different Tranches.
* @dev Each Tranche contract will do the accounting of the balances of its Liquidity Providers,
* while the Lending Pool will do the accounting of the balances of its Tranches.
* @dev A Tranche is according the ERC4626 standard, with a certain ERC20 as underlying asset.
*/
contract Tranche is ITranche, ERC4626, Owned {
using FixedPointMathLib for uint256;
/* //////////////////////////////////////////////////////////////
CONSTANTS
////////////////////////////////////////////////////////////// */
// The amount of Virtual Assets and Shares.
// Virtual shares/assets (also ghost shares) prevent against inflation attacks of ERC4626 vaults,
// see https://docs.openzeppelin.com/contracts/4.x/erc4626.
uint256 internal immutable VAS;
// The Lending Pool of the underlying ERC20 token, with the lending logic.
ILendingPool public immutable LENDING_POOL;
/* //////////////////////////////////////////////////////////////
STORAGE
////////////////////////////////////////////////////////////// */
// Flag indicating if the Tranche is locked or not.
bool public locked;
// Flag indicating if there is at least one ongoing auction or none.
bool public auctionInProgress;
/* //////////////////////////////////////////////////////////////
EVENTS
////////////////////////////////////////////////////////////// */
event LockSet(bool status);
event AuctionInProgressSet(bool status);
/* //////////////////////////////////////////////////////////////
MODIFIERS
////////////////////////////////////////////////////////////// */
/**
* @dev Functions with this modifier can only be called when the Tranche is not locked.
*/
modifier notLocked() {
if (locked) revert TrancheErrors.Locked();
_;
}
/**
* @dev Certain actions (depositing and withdrawing) can be halted on the most junior tranche while auctions are in progress.
* This prevents front running both in the case there is bad debt (by pulling out the tranche before the bad debt is settled),
* as in the case there are big payouts to the LPs (mitigate Just In Time attacks, where MEV bots front-run the payout of
* Liquidation penalties to the most junior tranche and withdraw immediately after).
*/
modifier notDuringAuction() {
if (auctionInProgress) revert TrancheErrors.AuctionOngoing();
_;
}
/* //////////////////////////////////////////////////////////////
CONSTRUCTOR
////////////////////////////////////////////////////////////// */
/**
* @notice The constructor for a tranche.
* @param lendingPool_ The Lending Pool of the underlying ERC20 token, with the lending logic.
* @param vas The amount of Virtual Assets and Shares.
* @param prefix_ The prefix of the contract name (eg. Senior -> Mezzanine -> Junior).
* @param prefixSymbol_ The prefix of the contract symbol (eg. SR -> MZ -> JR).
* @dev The name and symbol of the tranche are automatically generated, based on the name and symbol of the underlying token.
*/
constructor(address lendingPool_, uint256 vas, string memory prefix_, string memory prefixSymbol_)
ERC4626(
ERC4626(address(lendingPool_)).asset(),
string(abi.encodePacked(prefix_, " ArcadiaV2 ", ERC4626(lendingPool_).asset().name())),
string(abi.encodePacked(prefixSymbol_, "arcV2", ERC4626(lendingPool_).asset().symbol()))
)
Owned(msg.sender)
{
LENDING_POOL = ILendingPool(lendingPool_);
VAS = vas;
}
/*//////////////////////////////////////////////////////////////
LOCKING LOGIC
//////////////////////////////////////////////////////////////*/
/**
* @notice Locks the tranche in case all liquidity of the tranche is written off due to bad debt.
* @dev This function can only be called by the Lending Pool and is triggered exclusively during a severe default event.
*/
function lock() external {
if (msg.sender != address(LENDING_POOL)) revert TrancheErrors.Unauthorized();
emit LockSet(locked = true);
emit AuctionInProgressSet(auctionInProgress = false);
}
/**
* @notice Unlocks the tranche.
* @dev Only the Owner can call this function, since tranches are locked due to complete defaults.
* This function will only be called to partially refund existing share-holders after a default.
*/
function unLock() external onlyOwner {
emit LockSet(locked = false);
}
/**
* @notice Locks the tranche when an auction is in progress.
* @param auctionInProgress_ Flag indicating if there are auctions in progress.
* @dev Only the Lending Pool can call this function.
* This function is to make sure no JIT liquidity is provided during a positive auction,
* and that no liquidity can be withdrawn during a negative auction.
*/
function setAuctionInProgress(bool auctionInProgress_) external {
if (msg.sender != address(LENDING_POOL)) revert TrancheErrors.Unauthorized();
emit AuctionInProgressSet(auctionInProgress = auctionInProgress_);
}
/*//////////////////////////////////////////////////////////////
DEPOSIT/WITHDRAWAL LOGIC
//////////////////////////////////////////////////////////////*/
/**
* @notice Modification of the standard ERC-4626 deposit implementation.
* @param assets The amount of assets of the underlying ERC20 token being deposited.
* @param receiver The address that receives the minted shares.
* @return shares The amount of shares minted.
* @dev This contract does not directly transfer the underlying assets from the sender to the receiver.
* Instead it calls the deposit of the Lending Pool which calls the transferFrom of the underlying assets.
* Hence the sender should not give this contract an allowance to transfer the underlying asset but the Lending Pool instead.
*/
function deposit(uint256 assets, address receiver)
public
override
notLocked
notDuringAuction
returns (uint256 shares)
{
// Check for rounding error since we round down in previewDeposit.
if ((shares = previewDepositAndSync(assets)) == 0) revert TrancheErrors.ZeroShares();
// Need to transfer (via lendingPool.depositInLendingPool()) before minting or ERC777s could reenter.
LENDING_POOL.depositInLendingPool(assets, msg.sender);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
}
/**
* @notice Modification of the standard ERC-4626 mint implementation.
* @param shares The amount of shares minted.
* @param receiver The address that receives the minted shares.
* @return assets The amount of assets of the underlying ERC20 token being deposited.
* @dev This contract does not directly transfer the underlying assets from the sender to the receiver.
* Instead it calls the deposit of the Lending Pool which calls the transferFrom of the underlying assets.
* Hence the sender should not give this contract an allowance to transfer the underlying asset but the Lending Pool instead.
*/
function mint(uint256 shares, address receiver)
public
override
notLocked
notDuringAuction
returns (uint256 assets)
{
// No need to check for rounding error, previewMint rounds up.
assets = previewMintAndSync(shares);
// Need to transfer (via lendingPool.depositInLendingPool()) before minting or ERC777s could reenter.
LENDING_POOL.depositInLendingPool(assets, msg.sender);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
}
/**
* @notice Modification of the standard ERC-4626 withdraw implementation.
* @param assets The amount of assets of the underlying ERC20 token being withdrawn.
* @param receiver The address of the receiver of the underlying ERC20 tokens.
* @param owner_ The address of the owner of the assets being withdrawn.
* @return shares The corresponding amount of shares redeemed.
*/
function withdraw(uint256 assets, address receiver, address owner_)
public
override
notLocked
notDuringAuction
returns (uint256 shares)
{
// No need to check for rounding error, previewWithdraw rounds up.
shares = previewWithdrawAndSync(assets);
if (msg.sender != owner_) {
// Saves gas for limited approvals.
uint256 allowed = allowance[owner_][msg.sender];
if (allowed != type(uint256).max) allowance[owner_][msg.sender] = allowed - shares;
}
_burn(owner_, shares);
LENDING_POOL.withdrawFromLendingPool(assets, receiver);
emit Withdraw(msg.sender, receiver, owner_, assets, shares);
}
/**
* @notice Modification of the standard ERC-4626 redeem implementation.
* @param shares The amount of shares being redeemed.
* @param receiver The address of the receiver of the underlying ERC20 tokens.
* @param owner_ The address of the owner of the shares being redeemed.
* @return assets The corresponding amount of assets withdrawn.
*/
function redeem(uint256 shares, address receiver, address owner_)
public
override
notLocked
notDuringAuction
returns (uint256 assets)
{
if (msg.sender != owner_) {
// Saves gas for limited approvals.
uint256 allowed = allowance[owner_][msg.sender];
if (allowed != type(uint256).max) allowance[owner_][msg.sender] = allowed - shares;
}
// Check for rounding error since we round down in previewRedeem.
if ((assets = previewRedeemAndSync(shares)) == 0) revert TrancheErrors.ZeroAssets();
_burn(owner_, shares);
LENDING_POOL.withdrawFromLendingPool(assets, receiver);
emit Withdraw(msg.sender, receiver, owner_, assets, shares);
}
/*//////////////////////////////////////////////////////////////
ACCOUNTING LOGIC
//////////////////////////////////////////////////////////////*/
/**
* @notice Returns the total amount of underlying assets, to which liquidity providers have a claim.
* @return assets The total amount of underlying assets.
* @dev The Liquidity Pool does the accounting of the outstanding claim on liquidity per tranche.
*/
function totalAssets() public view override returns (uint256 assets) {
assets = LENDING_POOL.liquidityOf(address(this));
}
/**
* @notice Returns the total amount of underlying assets, to which liquidity providers have a claim.
* @return assets The total amount of underlying assets.
* @dev Modification of totalAssets() where interests are realised (state modification).
*/
function totalAssetsAndSync() public returns (uint256 assets) {
assets = LENDING_POOL.liquidityOfAndSync(address(this));
}
/**
* @notice Conversion rate from assets to shares.
* @param assets The amount of underlying assets.
* @return shares The amount of shares.
*/
function convertToShares(uint256 assets) public view override returns (uint256 shares) {
// Cache totalSupply.
uint256 supply = totalSupply;
shares = supply == 0 ? assets : assets.mulDivDown(supply + VAS, totalAssets() + VAS);
}
/**
* @notice Conversion rate from assets to shares.
* @param assets The amount of underlying assets.
* @return shares The amount of shares.
* @dev This function is a modification of convertToShares() where interests are realized (state modification).
*/
function convertToSharesAndSync(uint256 assets) public returns (uint256 shares) {
// Cache totalSupply.
uint256 supply = totalSupply;
shares = supply == 0 ? assets : assets.mulDivDown(supply + VAS, totalAssetsAndSync() + VAS);
}
/**
* @notice Conversion rate from shares to assets.
* @param shares The amount of shares.
* @return assets The amount of underlying assets.
*/
function convertToAssets(uint256 shares) public view override returns (uint256 assets) {
// Cache totalSupply.
uint256 supply = totalSupply;
assets = supply == 0 ? shares : shares.mulDivDown(totalAssets() + VAS, supply + VAS);
}
/**
* @notice Conversion rate from shares to assets.
* @param shares The amount of shares.
* @return assets The amount of underlying assets.
* @dev This function is a modification of convertToAssets() where interests are realized (state modification).
*/
function convertToAssetsAndSync(uint256 shares) public returns (uint256 assets) {
// Cache totalSupply.
uint256 supply = totalSupply;
assets = supply == 0 ? shares : shares.mulDivDown(totalAssetsAndSync() + VAS, supply + VAS);
}
/**
* @notice Returns the amount of shares minted that correspond to a certain amount of underlying assets deposited.
* @param assets The amount of underlying assets deposited.
* @return shares The amount of shares minted.
* @dev This function is a modification of previewDeposit() where interests are realized (state modification).
*/
function previewDepositAndSync(uint256 assets) public returns (uint256 shares) {
shares = convertToSharesAndSync(assets);
}
/**
* @notice Returns the amount of underlying assets deposited that correspond to a certain amount of shares minted.
* @param shares The amount of shares minted.
* @return assets The amount of underlying assets deposited.
*/
function previewMint(uint256 shares) public view override returns (uint256 assets) {
// Cache totalSupply.
uint256 supply = totalSupply;
assets = supply == 0 ? shares : shares.mulDivUp(totalAssets() + VAS, supply + VAS);
}
/**
* @notice Returns the amount of underlying assets deposited that correspond to a certain amount of shares minted.
* @param shares The amount of shares minted.
* @return assets The amount of underlying assets deposited.
* @dev This function is a modification of previewMint() where interests are realized (state modification).
*/
function previewMintAndSync(uint256 shares) public returns (uint256 assets) {
// Cache totalSupply.
uint256 supply = totalSupply;
assets = supply == 0 ? shares : shares.mulDivUp(totalAssetsAndSync() + VAS, supply + VAS);
}
/**
* @notice Returns the amount of shares redeemed that correspond to a certain amount of underlying assets withdrawn.
* @param assets The amount of underlying assets withdrawn.
* @return shares The amount of shares redeemed.
*/
function previewWithdraw(uint256 assets) public view override returns (uint256 shares) {
// Cache totalSupply.
uint256 supply = totalSupply;
shares = supply == 0 ? assets : assets.mulDivUp(supply + VAS, totalAssets() + VAS);
}
/**
* @notice Returns the amount of shares redeemed that correspond to a certain amount of underlying assets withdrawn.
* @param assets The amount of underlying assets withdrawn.
* @return shares The amount of shares redeemed.
* @dev This function is a modification of previewWithdraw() where interests are realized (state modification).
*/
function previewWithdrawAndSync(uint256 assets) public returns (uint256 shares) {
// Cache totalSupply.
uint256 supply = totalSupply;
shares = supply == 0 ? assets : assets.mulDivUp(supply + VAS, totalAssetsAndSync() + VAS);
}
/**
* @notice Returns the amount of underlying assets redeemed that correspond to a certain amount of shares withdrawn.
* @param shares The amount of shares redeemed.
* @return assets The amount of underlying assets withdrawn.
* @dev This function is a modification of previewRedeem() where interests are realized (state modification).
*/
function previewRedeemAndSync(uint256 shares) public returns (uint256 assets) {
assets = convertToAssetsAndSync(shares);
}
/*//////////////////////////////////////////////////////////////
DEPOSIT/WITHDRAWAL LIMIT LOGIC
//////////////////////////////////////////////////////////////*/
/**
* @dev maxDeposit() according the EIP-4626 specification.
*/
function maxDeposit(address) public view override returns (uint256 maxAssets) {
if (locked || auctionInProgress || IGuardian(address(LENDING_POOL)).depositPaused()) return 0;
maxAssets = type(uint128).max - LENDING_POOL.totalLiquidity();
}
/**
* @dev maxMint() according the EIP-4626 specification.
*/
function maxMint(address) public view override returns (uint256 maxShares) {
if (locked || auctionInProgress || IGuardian(address(LENDING_POOL)).depositPaused()) return 0;
maxShares = convertToShares(type(uint128).max - LENDING_POOL.totalLiquidity());
}
/**
* @dev maxWithdraw() according the EIP-4626 specification.
*/
function maxWithdraw(address owner_) public view override returns (uint256 maxAssets) {
if (locked || auctionInProgress || IGuardian(address(LENDING_POOL)).withdrawPaused()) return 0;
uint256 availableAssets = asset.balanceOf(address(LENDING_POOL));
uint256 claimableAssets = convertToAssets(balanceOf[owner_]);
maxAssets = availableAssets < claimableAssets ? availableAssets : claimableAssets;
}
/**
* @dev maxRedeem() according the EIP-4626 specification.
*/
function maxRedeem(address owner_) public view override returns (uint256 maxShares) {
if (locked || auctionInProgress || IGuardian(address(LENDING_POOL)).withdrawPaused()) return 0;
uint256 claimableShares = balanceOf[owner_];
if (claimableShares == 0) return 0;
uint256 availableShares = convertToShares(asset.balanceOf(address(LENDING_POOL)));
maxShares = availableShares < claimableShares ? availableShares : claimableShares;
}
}
{
"compilationTarget": {
"src/Tranche.sol": "Tranche"
},
"evmVersion": "shanghai",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":@openzeppelin/=lib/accounts-v2/lib/openzeppelin-contracts/",
":@uniswap/v3-core/contracts/=lib/accounts-v2/lib/v3-core/contracts/",
":accounts-v2/=lib/accounts-v2/",
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/accounts-v2/lib/openzeppelin-contracts/contracts/",
":solmate/=lib/solmate/src/",
":v3-core/=lib/accounts-v2/lib/v3-core/",
":v3-periphery/=lib/accounts-v2/lib/v3-periphery/contracts/"
]
}
[{"inputs":[{"internalType":"address","name":"lendingPool_","type":"address"},{"internalType":"uint256","name":"vas","type":"uint256"},{"internalType":"string","name":"prefix_","type":"string"},{"internalType":"string","name":"prefixSymbol_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AuctionOngoing","type":"error"},{"inputs":[],"name":"Locked","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"ZeroAssets","type":"error"},{"inputs":[],"name":"ZeroShares","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"AuctionInProgressSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"LockSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LENDING_POOL","outputs":[{"internalType":"contract ILendingPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"auctionInProgress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssetsAndSync","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToSharesAndSync","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"locked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"maxAssets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxMint","outputs":[{"internalType":"uint256","name":"maxShares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"maxShares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"maxWithdraw","outputs":[{"internalType":"uint256","name":"maxAssets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewDepositAndSync","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewMintAndSync","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeemAndSync","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewWithdrawAndSync","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner_","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"auctionInProgress_","type":"bool"}],"name":"setAuctionInProgress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssetsAndSync","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner_","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]