Skip to content

Commit

Permalink
ERC-7540 - Add ERC7540 - review updates
Browse files Browse the repository at this point in the history
  • Loading branch information
DeeJayElly committed Jan 30, 2025
1 parent 6135402 commit 94ce32b
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 66 deletions.
22 changes: 0 additions & 22 deletions contracts/interfaces/IERC7540.sol
Original file line number Diff line number Diff line change
Expand Up @@ -114,26 +114,4 @@ interface IERC7540 is IERC4626 {
* @return status Whether the operator is approved.
*/
function isOperator(address controller, address operator) external view returns (bool status);

/**
* @dev Gets the details of a pending deposit request.
* @param controller The address of the controller.
* @param requestId The unique identifier for the deposit request.
* @return request The request object containing amount and claimable details.
*/
function getPendingDepositRequest(
address controller,
uint256 requestId
) external view returns (Request memory request);

/**
* @dev Gets the details of a pending redeem request.
* @param controller The address of the controller.
* @param requestId The unique identifier for the redeem request.
* @return request The request object containing amount and claimable details.
*/
function getPendingRedeemRequest(
address controller,
uint256 requestId
) external view returns (Request memory request);
}
28 changes: 1 addition & 27 deletions contracts/mocks/token/ERC7540Mock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,7 @@ import {ERC4626} from "../../token/ERC20/extensions/ERC4626.sol";
contract ERC7540Mock is ERC7540 {
constructor(IERC20 asset) ERC20("ERC4626Mock", "E4626M") ERC7540(asset) {}

function processPendingDeposit(uint256 requestId, address controller) external view {
Request memory request = getPendingDepositRequest(controller, requestId);
require(request.amount > 0, "No pending deposit request");

request.claimable += request.amount;
request.amount = 0;
}

function processPendingRedeem(uint256 requestId, address controller) external view {
Request memory request = getPendingRedeemRequest(controller, requestId);
require(request.amount > 0, "No pending redeem request");

request.claimable += request.amount;
request.amount = 0;
}

function _processPendingRequests(uint256 requestId, address controller) internal view override {
Request memory depositRequest = getPendingDepositRequest(controller, requestId);
if (depositRequest.amount > 0) {
depositRequest.claimable += depositRequest.amount;
depositRequest.amount = 0;
}

Request memory redeemRequest = getPendingRedeemRequest(controller, requestId);
if (redeemRequest.amount > 0) {
redeemRequest.claimable += redeemRequest.amount;
redeemRequest.amount = 0;
}
// ToDo
}
}
41 changes: 24 additions & 17 deletions contracts/token/ERC20/extensions/ERC7540.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pragma solidity ^0.8.20;

import {IERC7540} from "../../../interfaces/IERC7540.sol";
import {IERC4626} from "../../../interfaces/IERC4626.sol";
import {IERC20} from "../../../interfaces/IERC20.sol";
import {ERC4626} from "./ERC4626.sol";
import {SafeERC20} from "../utils/SafeERC20.sol";
Expand All @@ -15,11 +16,13 @@ abstract contract ERC7540 is ERC4626, IERC7540 {
using SafeERC20 for IERC20;
using Math for uint256;

uint256 public constant VESTING_DURATION = 48 hours;

// Mappings to track pending and claimable requests
mapping(address => mapping(uint256 => Request)) private _pendingDepositRequests;
mapping(address => mapping(uint256 => Request)) private _pendingRedeemRequests;

mapping(address => mapping(address => bool)) private _operators;
mapping(uint256 => uint256) private _vestingTimestamps;

/**
* @dev Set the underlying asset contract.
Expand All @@ -46,7 +49,9 @@ abstract contract ERC7540 is ERC4626, IERC7540 {

requestId = _generateRequestId(controller, assets);

_pendingDepositRequests[controller][requestId].amount += assets;
uint256 shares = previewDeposit(assets);

_pendingDepositRequests[controller][requestId].amount += shares;

IERC20(asset()).safeTransferFrom(owner, address(this), assets);

Expand All @@ -62,6 +67,7 @@ abstract contract ERC7540 is ERC4626, IERC7540 {
address owner
) external override returns (uint256 requestId) {
address sender = _msgSender();

if (shares == 0) {
revert ERC7540ZeroSharesNotAllowed(sender, shares);
}
Expand All @@ -72,9 +78,14 @@ abstract contract ERC7540 is ERC4626, IERC7540 {

requestId = _generateRequestId(controller, shares);

uint256 assets = previewRedeem(shares);

_burn(owner, shares);

_pendingRedeemRequests[controller][requestId].amount += shares;
_pendingRedeemRequests[controller][requestId].amount += assets;

// Set vesting unlock time
_vestingTimestamps[requestId] = block.timestamp + VESTING_DURATION;

emit RedeemRequest(controller, owner, requestId, sender, shares);
}
Expand Down Expand Up @@ -107,6 +118,16 @@ abstract contract ERC7540 is ERC4626, IERC7540 {
return _pendingRedeemRequests[controller][requestId].claimable;
}

/** @dev See {IERC4626-maxWithdraw}. */
function maxWithdraw(address) public pure override(ERC4626, IERC4626) returns (uint256) {
return 0; // Withdrawals are only possible through requestRedeem
}

/** @dev See {IERC4626-maxRedeem}. */
function maxRedeem(address) public pure override(ERC4626, IERC4626) returns (uint256) {
return 0; // Redemptions are only possible through requestRedeem
}

/**
* @dev Sets or revokes an operator for the given controller.
*/
Expand All @@ -124,20 +145,6 @@ abstract contract ERC7540 is ERC4626, IERC7540 {
return _operators[controller][operator];
}

/**
* @dev Function to return pending deposit request.
*/
function getPendingDepositRequest(address controller, uint256 requestId) public view returns (Request memory) {
return _pendingDepositRequests[controller][requestId];
}

/**
* @dev Function to return pending redeem request.
*/
function getPendingRedeemRequest(address controller, uint256 requestId) public view returns (Request memory) {
return _pendingRedeemRequests[controller][requestId];
}

/**
* @dev Internal function to generates a request ID. Requests created within the same block,
* for the same controller, input, and sender, are cumulative.
Expand Down

0 comments on commit 94ce32b

Please sign in to comment.