Skip to content

Commit

Permalink
natspec, cosmetic changes
Browse files Browse the repository at this point in the history
  • Loading branch information
bxmmm1 committed Jun 17, 2024
1 parent d21f0e6 commit 95f14c2
Show file tree
Hide file tree
Showing 8 changed files with 313 additions and 69 deletions.
6 changes: 6 additions & 0 deletions mainnet-contracts/src/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,9 @@ error Unauthorized();
* @dev Signature "0xe6c4247b"
*/
error InvalidAddress();

/**
* @notice Thrown when amount is not valid
* @dev Signature "0x2c5211c6"
*/
error InvalidAmount();
71 changes: 45 additions & 26 deletions mainnet-contracts/src/PufLocker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { IPufLocker } from "./interface/IPufLocker.sol";
import { ERC20Permit } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { Permit } from "./structs/Permit.sol";
import { InvalidAmount } from "./Errors.sol";

/**
* @title PufLocker
Expand Down Expand Up @@ -37,29 +38,8 @@ contract PufLocker is AccessManagedUpgradeable, IPufLocker, PufLockerStorage {
}

/**
* @notice Creates a new staking token contract
* @dev Restricted to Puffer DAO
*/
function setIsAllowedToken(address token, bool allowed) external restricted {
PufLockerData storage $ = _getPufLockerStorage();
$.allowedTokens[token] = allowed;
emit SetTokenIsAllowed(token, allowed);
}

/**
* @notice Creates a new staking token contract
* @dev Restricted to Puffer DAO
* @inheritdoc IPufLocker
*/
function setLockPeriods(uint128 minLock, uint128 maxLock) external restricted {
if (minLock > maxLock) {
revert InvalidLockPeriod();
}
PufLockerData storage $ = _getPufLockerStorage();
emit LockPeriodsChanged($.minLockPeriod, minLock, $.maxLockPeriod, maxLock);
$.minLockPeriod = minLock;
$.maxLockPeriod = maxLock;
}

function deposit(address token, uint128 lockPeriod, Permit calldata permitData) external isAllowedToken(token) {
if (permitData.amount == 0) {
revert InvalidAmount();
Expand Down Expand Up @@ -90,24 +70,28 @@ contract PufLocker is AccessManagedUpgradeable, IPufLocker, PufLockerStorage {
emit Deposited(msg.sender, token, uint128(permitData.amount), releaseTime);
}

/**
* @inheritdoc IPufLocker
*/
function withdraw(address token, uint256[] calldata depositIndexes, address recipient) external {
if (recipient == address(0)) {
revert InvalidRecipientAddress();
}

PufLockerData storage $ = _getPufLockerStorage();

uint128 totalAmount = 0;
Deposit[] storage userDeposits = $.deposits[msg.sender][token];

for (uint256 i = 0; i < depositIndexes.length; i++) {
for (uint256 i = 0; i < depositIndexes.length; ++i) {
uint256 index = depositIndexes[i];
if (index >= userDeposits.length) {
revert InvalidDepositIndex();
}

Deposit storage userDeposit = userDeposits[index];
if (userDeposit.releaseTime > uint128(block.timestamp)) {
revert DepositStillLocked();
revert DepositLocked();
}

totalAmount += userDeposit.amount;
Expand All @@ -120,9 +104,36 @@ contract PufLocker is AccessManagedUpgradeable, IPufLocker, PufLockerStorage {

IERC20(token).safeTransfer(recipient, totalAmount);

emit Withdrawn(msg.sender, token, totalAmount, recipient);
emit Withdrawn({ user: msg.sender, token: token, amount: totalAmount, recipient: recipient });
}

/**
* @notice Creates a new staking token contract
* @dev Restricted to Puffer DAO
*/
function setIsAllowedToken(address token, bool allowed) external restricted {
PufLockerData storage $ = _getPufLockerStorage();
$.allowedTokens[token] = allowed;
emit SetTokenIsAllowed(token, allowed);
}

/**
* @notice Creates a new staking token contract
* @dev Restricted to Puffer DAO
*/
function setLockPeriods(uint128 minLock, uint128 maxLock) external restricted {
if (minLock > maxLock) {
revert InvalidLockPeriod();
}
PufLockerData storage $ = _getPufLockerStorage();
emit LockPeriodsChanged($.minLockPeriod, minLock, $.maxLockPeriod, maxLock);
$.minLockPeriod = minLock;
$.maxLockPeriod = maxLock;
}

/**
* @inheritdoc IPufLocker
*/
function getDeposits(address user, address token, uint256 start, uint256 limit)
external
view
Expand All @@ -141,13 +152,21 @@ contract PufLocker is AccessManagedUpgradeable, IPufLocker, PufLockerStorage {
uint256 count = end - start;

depositPage = new Deposit[](count);
for (uint256 i = 0; i < count; i++) {
for (uint256 i = 0; i < count; ++i) {
depositPage[i] = userDeposits[start + i];
}

return depositPage;
}

/**
* @inheritdoc IPufLocker
*/
function getAllDeposits(address token, address depositor) external view returns (Deposit[] memory) {
PufLockerData storage $ = _getPufLockerStorage();
return $.deposits[token][depositor];
}

/**
* @inheritdoc IPufLocker
*/
Expand Down
2 changes: 1 addition & 1 deletion mainnet-contracts/src/PufLockerStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ abstract contract PufLockerStorage {
/// @custom:storage-location erc7201:PufLocker.storage
struct PufLockerData {
mapping(address token => bool isAllowed) allowedTokens;
mapping(address token => mapping(address depositor => IPufLocker.Deposit[])) deposits;
mapping(address depositor => mapping(address token => IPufLocker.Deposit[])) deposits;
uint128 minLockPeriod;
uint128 maxLockPeriod;
}
Expand Down
18 changes: 10 additions & 8 deletions mainnet-contracts/src/PufToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { SignatureChecker } from "@openzeppelin/contracts/utils/cryptography/Sig
import { PufferL2Depositor } from "./PufferL2Depositor.sol";
import { IMigrator } from "./interface/IMigrator.sol";
import { IPufStakingPool } from "./interface/IPufStakingPool.sol";
import { Unauthorized, InvalidAmount } from "./Errors.sol";

/**
* @title Puf token
Expand Down Expand Up @@ -101,7 +102,7 @@ contract PufToken is IPufStakingPool, ERC20, ERC20Permit {
}

/**
* @notice Deposits the underlying token to receive pufToken to the `account`
* @inheritdoc IPufStakingPool
*/
function deposit(address from, address account, uint256 amount)
external
Expand All @@ -112,22 +113,21 @@ contract PufToken is IPufStakingPool, ERC20, ERC20Permit {
}

/**
* @notice Deposits the underlying token to receive pufToken to the `account`
* @inheritdoc IPufStakingPool
*/
function withdraw(address recipient, uint256 amount) external validateAddressAndAmount(recipient, amount) {
_burn(msg.sender, amount);

uint256 deNormalizedAmount = _denormalizeAmount(amount);

// Send him the token
TOKEN.safeTransfer(recipient, deNormalizedAmount);

// Using the original deposit amount in the event (in this case it is denormalized amount)
emit Withdrawn(msg.sender, recipient, deNormalizedAmount);
}

/**
* @notice Migrates the `amount` of tokens using the allowlsited `migratorContract` to the `destination` address
* @inheritdoc IPufStakingPool
*/
function migrate(uint256 amount, address migratorContract, address destination)
external
Expand All @@ -139,7 +139,7 @@ contract PufToken is IPufStakingPool, ERC20, ERC20Permit {
}

/**
* @notice Migrates the tokens using the allowlisted migrator contract using the EIP712 signature from the depositor
* @inheritdoc IPufStakingPool
*/
function migrateWithSignature(
address depositor,
Expand Down Expand Up @@ -173,13 +173,15 @@ contract PufToken is IPufStakingPool, ERC20, ERC20Permit {
_migrate({ depositor: depositor, amount: amount, destination: destination, migratorContract: migratorContract });
}

/**
* @notice Sets the underlying token deposit cap
*/
function setDepositCap(uint256 newDepositCap) external onlyPufferFactory {
uint256 deNormalizedTotalSupply = _denormalizeAmount(totalSupply());

if (newDepositCap < deNormalizedTotalSupply) {
if (newDepositCap < totalSupply()) {
revert InvalidAmount();
}

emit DepositCapChanged(totalDepositCap, newDepositCap);
totalDepositCap = newDepositCap;
}

Expand Down
120 changes: 106 additions & 14 deletions mainnet-contracts/src/interface/IPufLocker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,131 @@ pragma solidity >=0.8.0 <0.9.0;

import { Permit } from "../structs/Permit.sol";

/**
* @title IPufStakingPool
* @author Puffer Finance
* @custom:security-contact security@puffer.fi
*/
interface IPufLocker {
// Custom error messages
struct Deposit {
uint128 amount;
uint128 releaseTime;
}

/**
* @notice Thrown when the token is not allowed
* @dev Signature "0xa29c4986"
*/
error TokenNotAllowed();
error InvalidAmount();

/**
* @notice Thrown when lock period is not in the valid range
* @dev Signature "0x2a82a34f"
*/
error InvalidLockPeriod();

/**
* @notice Thrown index of the deposit is invalid
* @dev Signature "0x6d97cdda"
*/
error InvalidDepositIndex();
error DepositStillLocked();

/**
* @notice Thrown when the deposit is locked
* @dev Signature "0xf38b9b5b"
*/
error DepositLocked();

/**
* @notice Thrown when there is no withdrawable amount
* @dev Signature "0x1b1d7861"
*/
error NoWithdrawableAmount();

/**
* @notice Thrown when the recipient address is invalid
* @dev Signature "0x44d99fea"
*/
error InvalidRecipientAddress();

// Events
/**
* @notice Event emitted when a token is allowed or disallowed
* @param token The address of the token
* @param allowed Whether the token is allowed or not
*/
event SetTokenIsAllowed(address indexed token, bool allowed);

/**
* @notice Event emitted when funds are deposited into the locker
* @param user The address of the user who initiated the deposit
* @param token The address of the token being deposited
* @param amount The amount of tokens being deposited
* @param releaseTime The release time of the deposit
*/
event Deposited(address indexed user, address indexed token, uint128 amount, uint128 releaseTime);
event Withdrawn(address indexed user, address indexed token, uint128 amount, address recipient);
event LockPeriodsChanged(uint128 previousMinLock, uint128 newMinLock, uint128 previousMaxLock, uint128 newMaxLock);

// Functions
function setIsAllowedToken(address token, bool allowed) external;
/**
* @notice Event emitted when funds are withdrawn from the locker
* @param user The address of the user who initiated the withdrawal
* @param token The address of the token being withdrawn
* @param amount The amount of tokens being withdrawn
* @param recipient The address that will receive the withdrawn funds
*/
event Withdrawn(address indexed user, address indexed token, uint128 amount, address indexed recipient);

function setLockPeriods(uint128 minLockPeriod, uint128 maxLockPeriod) external;
/**
* @notice Event emitted when the lock periods are changed
* @param previousMinLock The previous minimum lock period
* @param newMinLock The new minimum lock period
* @param previousMaxLock The previous maximum lock period
* @param newMaxLock The new maximum lock period
*/
event LockPeriodsChanged(uint128 previousMinLock, uint128 newMinLock, uint128 previousMaxLock, uint128 newMaxLock);

/**
* @notice Deposit tokens into the locker
* @param token The address of the token to deposit
* @param lockPeriod The lock period for the deposit
* @param permitData The permit data for the deposit
*/
function deposit(address token, uint128 lockPeriod, Permit calldata permitData) external;

/**
* @notice Withdraws specified deposits for a given token and transfers the funds to the recipient
* @dev If the deposit is still locked, the function will revert
* @param token The address of the token
* @param depositIndexes An array of deposit indexes to be withdrawn
* @param recipient The address to receive the withdrawn funds
*/
function withdraw(address token, uint256[] calldata depositIndexes, address recipient) external;

/**
* @notice Get deposits for a specific user and token
* @dev Amount == 0 && releaseTime > 0 = the deposit got withdrawn
* @param user The address of the user
* @param token The address of the token
* @param start The starting index of the deposits
* @param limit The maximum number of deposits to retrieve
* @return deposits An array of Deposit structs representing the deposits
*/
function getDeposits(address user, address token, uint256 start, uint256 limit)
external
view
returns (Deposit[] memory);
function getLockPeriods() external view returns (uint128, uint128);

struct Deposit {
uint128 amount;
uint128 releaseTime;
}
/**
* @notice Get all deposits for a specific token and depositor
* @dev Amount == 0 && releaseTime > 0 = the deposit got withdrawn
* @param token The address of the token
* @param depositor The address of the depositor
* @return deposits An array of Deposit structs representing the deposits
*/
function getAllDeposits(address token, address depositor) external view returns (Deposit[] memory);

/**
* @notice Get the minimum and maximum lock periods allowed for deposits
* @return minLock The minimum lock period
* @return maxLock The maximum lock period
*/
function getLockPeriods() external view returns (uint128 minLock, uint128 maxLock);
}
Loading

0 comments on commit 95f14c2

Please sign in to comment.