Skip to content

Commit

Permalink
Add interfaces and ERC-165 support
Browse files Browse the repository at this point in the history
  • Loading branch information
hieronx committed Oct 26, 2023
1 parent d57fc34 commit 682bc71
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 8 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# ERC-4626 Reference Implementations • [![CI](https://github.com/transmissions11/foundry-template/actions/workflows/tests.yml/badge.svg)](https://github.com/transmissions11/foundry-template/actions/workflows/tests.yml)
# ERC-7540 Reference Implementations • [![CI](https://github.com/transmissions11/foundry-template/actions/workflows/tests.yml/badge.svg)](https://github.com/transmissions11/foundry-template/actions/workflows/tests.yml)

Includes sample reference implementations for [ERC-7540](https://ethereum-magicians.org/t/eip-7540-asynchronous-erc-4626-tokenized-vaults/16153) async deposit and withdraw for different use cases.
Includes sample reference implementations for [ERC-7540](https://ethereum-magicians.org/t/eip-7540-asynchronous-erc-4626-tokenized-vaults/16153) async deposit and redeem for different use cases.
9 changes: 6 additions & 3 deletions src/ERC7540AsyncDepositExample.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity 0.8.15;

import "solmate/mixins/ERC4626.sol";
import "solmate/auth/Owned.sol";
import {IERC7540Deposit, IERC165} from "./interfaces/IERC7540Deposit.sol";

// THIS VAULT IS AN UNOPTIMIZED, POTENTIALLY UNSECURE REFERENCE EXAMPLE AND IN NO WAY MEANT TO BE USED IN PRODUCTION

Expand All @@ -16,7 +17,7 @@ import "solmate/auth/Owned.sol";
* To allow partial claims, the deposit and mint functions would need to allow for pro rata claims.
* Conversions between claimable assets/shares should be checked for rounding safety.
*/
contract ERC7540AsyncDepositExample is ERC4626, Owned {
contract ERC7540AsyncDepositExample is ERC4626, Owned, IERC7540Deposit {
using SafeTransferLib for ERC20;

mapping(address => PendingDeposit) internal _pendingDeposit;
Expand All @@ -32,8 +33,6 @@ contract ERC7540AsyncDepositExample is ERC4626, Owned {
uint256 shares;
}

event DepositRequest(address indexed sender, address indexed operator, uint256 assets);

constructor(ERC20 _asset, string memory _name, string memory _symbol)
ERC4626(_asset, _name, _symbol)
Owned(msg.sender)
Expand Down Expand Up @@ -67,6 +66,10 @@ contract ERC7540AsyncDepositExample is ERC4626, Owned {
assets = _pendingDeposit[operator].assets;
}

function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
return interfaceId == type(IERC165).interfaceId || interfaceId == type(IERC7540Deposit).interfaceId;
}

/*//////////////////////////////////////////////////////////////
DEPOSIT FULFILLMENT LOGIC
//////////////////////////////////////////////////////////////*/
Expand Down
13 changes: 10 additions & 3 deletions src/ERC7540AsyncRedeemExample.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity 0.8.15;

import "solmate/mixins/ERC4626.sol";
import {IERC7540Redeem, IERC165} from "./interfaces/IERC7540Redeem.sol";

// THIS VAULT IS AN UNOPTIMIZED, POTENTIALLY UNSECURE REFERENCE EXAMPLE AND IN NO WAY MEANT TO BE USED IN PRODUCTION

Expand All @@ -19,7 +20,7 @@ import "solmate/mixins/ERC4626.sol";
To allow partial claims, the redeem and withdraw functions would need to allow for pro rata claims.
Conversions between claimable assets/shares should be checked for rounding safety.
*/
contract ERC7540AsyncRedeemExample is ERC4626 {
contract ERC7540AsyncRedeemExample is ERC4626, IERC7540Redeem {

mapping(address => RedemptionRequest) internal _pendingRedemption;
uint256 internal _totalPendingAssets;
Expand All @@ -32,8 +33,6 @@ contract ERC7540AsyncRedeemExample is ERC4626 {

uint32 public constant REDEEM_DELAY_SECONDS = 3 days;

event RedeemRequest(address indexed sender, address indexed operator, address indexed owner, uint256 shares);

constructor(
ERC20 _asset,
string memory _name,
Expand Down Expand Up @@ -84,6 +83,10 @@ event RedeemRequest(address indexed sender, address indexed operator, address in
}
}

function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {
return interfaceId == type(IERC165).interfaceId || interfaceId == type(IERC7540Redeem).interfaceId;
}

/*//////////////////////////////////////////////////////////////
ERC4626 OVERRIDDEN LOGIC
//////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -135,6 +138,8 @@ event RedeemRequest(address indexed sender, address indexed operator, address in
if (request.claimableTimestamp <= block.timestamp) {
return request.assets;
}

return 0;
}

function maxRedeem(address operator) public view override returns (uint256) {
Expand All @@ -144,6 +149,8 @@ event RedeemRequest(address indexed sender, address indexed operator, address in
if (request.claimableTimestamp <= block.timestamp) {
return request.shares;
}

return 0;
}

// Preview functions always revert for async flows
Expand Down
21 changes: 21 additions & 0 deletions src/interfaces/IERC165.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
27 changes: 27 additions & 0 deletions src/interfaces/IERC7540Deposit.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

import {IERC165} from "./IERC165.sol";

interface IERC7540Deposit is IERC165 {
event DepositRequest(address indexed sender, address indexed operator, uint256 assets);

/**
* @dev Transfers assets from msg.sender into the Vault and submits a Request for asynchronous deposit/mint.
*
* - MUST support ERC-20 approve / transferFrom on asset as a deposit Request flow.
* - MUST revert if all of assets cannot be requested for deposit/mint.
*
* NOTE: most implementations will require pre-approval of the Vault with the Vault's underlying asset token.
*/
function requestDeposit(uint256 assets, address operator) external;

/**
* @dev Returns the amount of requested assets in Pending state for the operator to deposit or mint.
*
* - MUST NOT include any assets in Claimable state for deposit or mint.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
*/
function pendingDepositRequest(address operator) external view returns (uint256 assets);
}
26 changes: 26 additions & 0 deletions src/interfaces/IERC7540Redeem.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

import {IERC165} from "./IERC165.sol";

interface IERC7540Redeem is IERC165 {
event RedeemRequest(address indexed sender, address indexed operator, address indexed owner, uint256 shares);

/**
* @dev Assumes control of shares from owner and submits a Request for asynchronous redeem/withdraw.
*
* - MUST support a redeem Request flow where the control of shares is taken from owner directly
* where msg.sender has ERC-20 approval over the shares of owner.
* - MUST revert if all of shares cannot be requested for redeem / withdraw.
*/
function requestRedeem(uint256 shares, address operator, address owner) external;

/**
* @dev Returns the amount of requested shares in Pending state for the operator to redeem or withdraw.
*
* - MUST NOT include any shares in Claimable state for redeem or withdraw.
* - MUST NOT show any variations depending on the caller.
* - MUST NOT revert unless due to integer overflow caused by an unreasonably large input.
*/
function pendingRedeemRequest(address operator) external view returns (uint256 shares);
}

0 comments on commit 682bc71

Please sign in to comment.