https://eips.ethereum.org/EIP...Abstract 以下标准允许为代表单个底层 ERC-20 份额的保险库实施标准 API。 该标准是 ERC-20 代币的扩展,它提供了存取代币和读取余额的基本功能。
Motivation 代币化保险库缺乏标准化,导致实施细节多样化。 一些不同的例子包括借贷市场、聚合器和具有内在利息的代币。 这使得需要符合许多标准的协议在聚合器或插件层难以集成,并迫使每个协议实现自己的适配器,这些适配器容易出错并浪费开发资源。代币化保险库的标准将降低收益保险库的集成工作量,同时创建更加一致和强大的实施模式。
Code Events
Deposit事件:
event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);
Withdraw事件:
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;
}
Main Logic
Deposit函数:
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);
}
Mint函数:
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);
}
Withdraw函数:
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);
}
Redeem函数:
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);
}
Account Logic
function totalAssets() public view virtual returns (uint256);
function convertToShares(uint256 assets) public view 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 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];
}
Hooks Logic
function beforeWithdraw(uint256 assets, uint256 shares) internal virtual {}function afterDeposit(uint256 assets, uint256 shares) internal virtual {}
参考文章 【EIP-4626: Tokenized Vault Standard (金库标准化)】https://ethereum-magicians.or...
https://github.com/Rari-Capit...