编译器
0.8.17+commit.8df45f5f
文件 1 的 8:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 2 的 8:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 3 的 8:IMintableBurnableERC20.sol
pragma solidity 0.8.17;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IMintableBurnableERC20 is IERC20 {
function mint(address _to, uint256 _amount) external;
function burn(uint256 _amount) external;
function transferOwner(address _owner) external;
function setMinter(address _minter, bool _status) external;
}
文件 4 的 8:IStETH.sol
pragma solidity 0.8.17;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IStETH is IERC20 {
function submit(address _referral) external payable returns (uint _recievedShares);
}
文件 5 的 8:IVault.sol
pragma solidity 0.8.17;
import "./IVaultFactory.sol";
interface IVault {
function initialize(address) external;
function factory() external view returns (IVaultFactory);
function owner() external view returns (address);
function deposited() external view returns (uint);
function minted() external view returns (uint);
function availableBalance() external view returns (uint);
function pendingYield() external view returns (uint);
function mintRatio() external view returns (uint);
function deposit(uint) external returns (uint);
function withdraw(uint) external;
function mint(uint) external;
function burn(uint) external;
function redeem(uint) external;
function claim() external;
}
文件 6 的 8:IVaultFactory.sol
pragma solidity 0.8.17;
import "./IMintableBurnableERC20.sol";
interface IVaultFactory {
function collateral() external view returns (IERC20);
function token() external view returns (IMintableBurnableERC20);
function feeManager() external view returns (address);
function createVault(address) external returns (address);
function getVault(address) external view returns (address);
function allVaults(uint) external view returns (address);
function isVault(address) external view returns (bool);
function isVaultManager(address) external view returns (bool);
function vaultsLength() external view returns (uint);
}
文件 7 的 8:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 8 的 8:VaultManager.sol
pragma solidity 0.8.17;
import "@openzeppelin/contracts/access/Ownable.sol";
import "../interfaces/IVaultFactory.sol";
import "../interfaces/IVault.sol";
import "../interfaces/IStETH.sol";
contract VaultManager is Ownable {
IVaultFactory public immutable factory;
constructor(address _factory) {
factory = IVaultFactory(_factory);
}
function depositAndMintWithETH(uint _mintAmount) external payable {
IStETH stETH = IStETH(address(factory.collateral()));
uint before = factory.collateral().balanceOf(address(this));
if (msg.value > 0) {
stETH.submit{value: msg.value}(address(0));
}
uint actualDepositedAmount = factory.collateral().balanceOf(address(this)) - before;
_depositAndMint(actualDepositedAmount, _mintAmount);
}
function depositAndMint(uint _depositAmount, uint _mintAmount) external {
uint before = factory.collateral().balanceOf(address(this));
factory.collateral().transferFrom(msg.sender, address(this), _depositAmount);
uint actualDepositedAmount = factory.collateral().balanceOf(address(this)) - before;
_depositAndMint(actualDepositedAmount, _mintAmount);
}
function _depositAndMint(uint _depositAmount, uint _mintAmount) internal {
IVault vault = IVault(factory.getVault(msg.sender));
require(address(vault) != address(0), "vault not exist");
if (_depositAmount > 0) {
factory.collateral().approve(address(vault), _depositAmount);
vault.deposit(_depositAmount);
}
uint available = vault.availableBalance();
_mintAmount = _mintAmount > available ? available : _mintAmount;
if (_mintAmount > 0) {
vault.mint(_mintAmount);
}
}
function burnAndWithdraw(uint _burnAmount, uint _withdrawAmount) external {
IVault vault = IVault(factory.getVault(msg.sender));
require(address(vault) != address(0), "vault not exist");
if (_burnAmount > 0) {
factory.token().transferFrom(msg.sender, address(this), _burnAmount);
factory.token().approve(address(vault), _burnAmount);
vault.burn(_burnAmount);
}
if (_withdrawAmount > 0) {
vault.withdraw(_withdrawAmount);
}
}
function redeem(uint _amount, IVault[] calldata vaults) external {
uint vaultManagerCollateralBefore = factory.collateral().balanceOf(address(this));
factory.token().transferFrom(msg.sender, address(this), _amount);
for (uint i=0; i<vaults.length; i++) {
uint amountToRedeem = _amount > vaults[i].minted() ? vaults[i].minted() : _amount;
if (amountToRedeem > 0) {
factory.token().approve(address(vaults[i]), amountToRedeem);
vaults[i].redeem(amountToRedeem);
_amount -= amountToRedeem;
}
if (_amount == 0) break;
}
uint redeemed = factory.collateral().balanceOf(address(this)) - vaultManagerCollateralBefore;
factory.collateral().transfer(msg.sender, redeemed);
require(_amount == 0, "VaultManager: insufficient vault balance to redeem");
}
function rescue(address _token, address _recipient) external onlyOwner {
uint _balance = IERC20(_token).balanceOf(address(this));
IERC20(_token).transfer(_recipient, _balance);
}
}
{
"compilationTarget": {
"contracts/peripheral/VaultManager.sol": "VaultManager"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_factory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"uint256","name":"_burnAmount","type":"uint256"},{"internalType":"uint256","name":"_withdrawAmount","type":"uint256"}],"name":"burnAndWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_depositAmount","type":"uint256"},{"internalType":"uint256","name":"_mintAmount","type":"uint256"}],"name":"depositAndMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintAmount","type":"uint256"}],"name":"depositAndMintWithETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract IVaultFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"contract IVault[]","name":"vaults","type":"address[]"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"rescue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]