编译器
0.8.17+commit.8df45f5f
文件 1 的 10:Auth.sol
pragma solidity 0.8.17;
bytes32 constant CONFIGURATOR_ROLE = keccak256("CONFIGURATOR");
bytes32 constant KEEPER_ROLE = keccak256("KEEPER_ROLE");
bytes32 constant SWAP_KEEPER = keccak256("SWAP_KEEPER");
contract Auth {
error NotAuthorized(bytes32 _role, address _user);
event RoleUpdated(bytes32 indexed role, address indexed user, bool authorized);
bytes32 public constant AUTH_MANAGER_ROLE = keccak256("AUTH_MANAGER");
mapping(bytes32 => mapping(address => bool)) public hasRole;
constructor() {
_updateRole(msg.sender, AUTH_MANAGER_ROLE, true);
}
function updateRole(address _user, bytes32 _role, bool _authorized) external {
onlyRole(AUTH_MANAGER_ROLE, msg.sender);
_updateRole(_user, _role, _authorized);
}
function onlyRole(bytes32 _role, address _user) public view {
if (!hasRole[_role][_user]) {
revert NotAuthorized(_role, _user);
}
}
function _updateRole(address _user, bytes32 _role, bool _authorized) internal {
hasRole[_role][_user] = _authorized;
emit RoleUpdated(_role, _user, _authorized);
}
}
abstract contract GlobalACL {
Auth public immutable AUTH;
constructor(Auth _auth) {
require(address(_auth) != address(0), "GlobalACL: zero address");
AUTH = _auth;
}
modifier onlyConfigurator() {
AUTH.onlyRole(CONFIGURATOR_ROLE, msg.sender);
_;
}
modifier onlyRole(bytes32 _role) {
AUTH.onlyRole(_role, msg.sender);
_;
}
}
文件 2 的 10: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;
}
}
文件 3 的 10:ERC20.sol
pragma solidity >=0.8.0;
abstract contract ERC20 {
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
string public name;
string public symbol;
uint8 public immutable decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender];
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}
文件 4 的 10:ERC4626.sol
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
import {SafeTransferLib} from "../utils/SafeTransferLib.sol";
import {FixedPointMathLib} from "../utils/FixedPointMathLib.sol";
abstract contract ERC4626 is ERC20 {
using SafeTransferLib for ERC20;
using FixedPointMathLib for uint256;
event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed caller,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
ERC20 public immutable asset;
constructor(
ERC20 _asset,
string memory _name,
string memory _symbol
) ERC20(_name, _symbol, _asset.decimals()) {
asset = _asset;
}
function deposit(uint256 assets, address receiver) public virtual returns (uint256 shares) {
require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES");
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
afterDeposit(assets, shares);
}
function mint(uint256 shares, address receiver) public virtual returns (uint256 assets) {
assets = previewMint(shares);
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
afterDeposit(assets, shares);
}
function withdraw(
uint256 assets,
address receiver,
address owner
) public virtual returns (uint256 shares) {
shares = previewWithdraw(assets);
if (msg.sender != owner) {
uint256 allowed = allowance[owner][msg.sender];
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);
}
function redeem(
uint256 shares,
address receiver,
address owner
) public virtual returns (uint256 assets) {
if (msg.sender != owner) {
uint256 allowed = allowance[owner][msg.sender];
if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
}
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);
}
function totalAssets() public view virtual returns (uint256);
function convertToShares(uint256 assets) public view virtual returns (uint256) {
uint256 supply = totalSupply;
return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets());
}
function convertToAssets(uint256 shares) public view virtual returns (uint256) {
uint256 supply = totalSupply;
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;
return supply == 0 ? shares : shares.mulDivUp(totalAssets(), supply);
}
function previewWithdraw(uint256 assets) public view virtual returns (uint256) {
uint256 supply = totalSupply;
return supply == 0 ? assets : assets.mulDivUp(supply, totalAssets());
}
function previewRedeem(uint256 shares) public view virtual returns (uint256) {
return convertToAssets(shares);
}
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];
}
function beforeWithdraw(uint256 assets, uint256 shares) internal virtual {}
function afterDeposit(uint256 assets, uint256 shares) internal virtual {}
}
文件 5 的 10:FixedPointMathLib.sol
pragma solidity >=0.8.0;
library FixedPointMathLib {
uint256 internal constant MAX_UINT256 = 2**256 - 1;
uint256 internal constant WAD = 1e18;
function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, y, WAD);
}
function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, y, WAD);
}
function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, WAD, y);
}
function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, WAD, y);
}
function mulDivDown(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
assembly {
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
revert(0, 0)
}
z := div(mul(x, y), denominator)
}
}
function mulDivUp(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
assembly {
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
revert(0, 0)
}
z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))
}
}
function rpow(
uint256 x,
uint256 n,
uint256 scalar
) internal pure returns (uint256 z) {
assembly {
switch x
case 0 {
switch n
case 0 {
z := scalar
}
default {
z := 0
}
}
default {
switch mod(n, 2)
case 0 {
z := scalar
}
default {
z := x
}
let half := shr(1, scalar)
for {
n := shr(1, n)
} n {
n := shr(1, n)
} {
if shr(128, x) {
revert(0, 0)
}
let xx := mul(x, x)
let xxRound := add(xx, half)
if lt(xxRound, xx) {
revert(0, 0)
}
x := div(xxRound, scalar)
if mod(n, 2) {
let zx := mul(z, x)
if iszero(eq(div(zx, x), z)) {
if iszero(iszero(x)) {
revert(0, 0)
}
}
let zxRound := add(zx, half)
if lt(zxRound, zx) {
revert(0, 0)
}
z := div(zxRound, scalar)
}
}
}
}
}
function sqrt(uint256 x) internal pure returns (uint256 z) {
assembly {
let y := x
z := 181
if iszero(lt(y, 0x10000000000000000000000000000000000)) {
y := shr(128, y)
z := shl(64, z)
}
if iszero(lt(y, 0x1000000000000000000)) {
y := shr(64, y)
z := shl(32, z)
}
if iszero(lt(y, 0x10000000000)) {
y := shr(32, y)
z := shl(16, z)
}
if iszero(lt(y, 0x1000000)) {
y := shr(16, y)
z := shl(8, z)
}
z := shr(18, mul(z, add(y, 65536)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := sub(z, lt(div(x, z), z))
}
}
function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := mod(x, y)
}
}
function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
assembly {
r := div(x, y)
}
}
function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := add(gt(mod(x, y), 0), div(x, y))
}
}
}
文件 6 的 10:IAggregateVault.sol
pragma solidity 0.8.17;
import { ERC20 } from "solmate/tokens/ERC20.sol";
interface IAggregateVault {
function handleWithdraw(ERC20 asset, uint256 _amount, address _account) external;
function handleDeposit(ERC20 asset, uint256 _amount, address _account) external;
function getVaultPPS(address _assetVault) external view returns (uint256);
function previewWithdrawalFee(address token, uint256 _size) external view returns (uint256);
function previewDepositFee(uint256 _size) external view returns (uint256);
function rebalanceOpen() external view returns (bool);
}
文件 7 的 10:Pausable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor() {
_paused = false;
}
modifier whenNotPaused() {
_requireNotPaused();
_;
}
modifier whenPaused() {
_requirePaused();
_;
}
function paused() public view virtual returns (bool) {
return _paused;
}
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 8 的 10:SafeTransferLib.sol
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
library SafeTransferLib {
function safeTransferETH(address to, uint256 amount) internal {
bool success;
assembly {
success := call(gas(), to, amount, 0, 0, 0, 0)
}
require(success, "ETH_TRANSFER_FAILED");
}
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), from)
mstore(add(freeMemoryPointer, 36), to)
mstore(add(freeMemoryPointer, 68), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
require(success, "TRANSFER_FROM_FAILED");
}
function safeTransfer(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to)
mstore(add(freeMemoryPointer, 36), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "TRANSFER_FAILED");
}
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to)
mstore(add(freeMemoryPointer, 36), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "APPROVE_FAILED");
}
}
文件 9 的 10:ShareMath.sol
pragma solidity 0.8.17;
library ShareMath {
uint256 internal constant PLACEHOLDER_UINT = 1;
function assetToShares(uint256 assetAmount, uint256 assetPerShare, uint256 decimals)
internal
pure
returns (uint256)
{
require(assetPerShare > PLACEHOLDER_UINT, "Invalid assetPerShare");
return (assetAmount * 10 ** decimals) / assetPerShare;
}
function sharesToAsset(uint256 shares, uint256 assetPerShare, uint256 decimals) internal pure returns (uint256) {
require(assetPerShare > PLACEHOLDER_UINT, "Invalid assetPerShare");
return (shares * assetPerShare) / 10 ** decimals;
}
function pricePerShare(uint256 totalSupply, uint256 totalBalance, uint256 decimals)
internal
pure
returns (uint256)
{
uint256 singleShare = 10 ** decimals;
return totalSupply > 0 ? (singleShare * totalBalance) / totalSupply : singleShare;
}
}
文件 10 的 10:TimelockBoostToken.sol
pragma solidity 0.8.17;
import { ERC4626 } from "solmate/mixins/ERC4626.sol";
import { ERC20 } from "solmate/tokens/ERC20.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { ShareMath } from "../libraries/ShareMath.sol";
import { Pausable } from "@openzeppelin/contracts/security/Pausable.sol";
import { IAggregateVault } from "../interfaces/IAggregateVault.sol";
import { GlobalACL, Auth } from "../Auth.sol";
contract TimelockBoost is ERC4626, Pausable, GlobalACL {
using SafeTransferLib for ERC20;
uint256 constant LOCK_QUEUE_LIMIT = 5;
address public ZAP;
struct QueuedWithdrawal {
uint256 queuedTimestamp;
uint256 underlyingAmount;
}
struct TokenLockState {
uint256 withdrawDuration;
uint256 activeWithdrawBalance;
}
TokenLockState public lockState;
mapping(address => uint8) public activeWithdrawals;
mapping(address => QueuedWithdrawal[LOCK_QUEUE_LIMIT]) public withdrawalQueue;
event Deposit(address indexed _asset, address _account, uint256 _amount);
event WithdrawInitiated(address indexed _asset, address _account, uint256 _amount, uint256 _duration);
event WithdrawComplete(address indexed _asset, address _account, uint256 _amount);
constructor(ERC20 _asset, string memory _name, string memory _symbol, uint256 _withdrawDuration, Auth _auth)
ERC4626(_asset, _name, _symbol)
GlobalACL(_auth)
{
lockState.withdrawDuration = _withdrawDuration;
}
function deposit(uint256 assets, address receiver) public override whenNotPaused returns (uint256 shares) {
require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES");
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
}
function mint(uint256 shares, address receiver) public override whenNotPaused returns (uint256 assets) {
assets = previewMint(shares);
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
}
function initiateWithdraw(uint256 _assets) external whenNotPaused returns (uint256 shares) {
shares = convertToShares(_assets);
_initiateWithdrawShares(shares, _assets);
}
function initiateRedeem(uint256 _shares) external whenNotPaused returns (uint256 _assets) {
_assets = convertToAssets(_shares);
_initiateWithdrawShares(_shares, _assets);
}
function claimWithdrawals(address _receiver) external whenNotPaused returns (uint256 _totalWithdraw) {
require(activeWithdrawals[msg.sender] > 0, "TimelockBoost: !activeWithdrawals");
QueuedWithdrawal[LOCK_QUEUE_LIMIT] storage accountWithdrawals = withdrawalQueue[msg.sender];
uint256 withdrawAmount;
for (uint256 i = 0; i < LOCK_QUEUE_LIMIT; i++) {
if (
accountWithdrawals[i].queuedTimestamp + lockState.withdrawDuration < block.timestamp
&& accountWithdrawals[i].queuedTimestamp != 0
) {
withdrawAmount = _removeWithdrawForAccount(msg.sender, i);
_decrementActiveWithdraws(msg.sender, withdrawAmount);
_totalWithdraw += withdrawAmount;
}
}
if (_totalWithdraw > 0) {
asset.safeTransfer(_receiver, _totalWithdraw);
}
emit WithdrawComplete(address(asset), msg.sender, _totalWithdraw);
}
function claimWithdrawalsFor(address _account, address _receiver)
external
whenNotPaused
onlyZap
returns (uint256 _totalWithdraw)
{
require(activeWithdrawals[_account] > 0, "TimelockBoost: !activeWithdrawals");
QueuedWithdrawal[LOCK_QUEUE_LIMIT] storage accountWithdrawals = withdrawalQueue[_account];
uint256 withdrawAmount;
for (uint256 i = 0; i < LOCK_QUEUE_LIMIT; i++) {
if (
accountWithdrawals[i].queuedTimestamp + lockState.withdrawDuration < block.timestamp
&& accountWithdrawals[i].queuedTimestamp != 0
) {
withdrawAmount = _removeWithdrawForAccount(_account, i);
_decrementActiveWithdraws(_account, withdrawAmount);
_totalWithdraw += withdrawAmount;
}
}
if (_totalWithdraw > 0) {
asset.safeTransfer(_receiver, _totalWithdraw);
}
emit WithdrawComplete(address(asset), _account, _totalWithdraw);
}
function totalAssets() public view override returns (uint256) {
return asset.balanceOf(address(this)) - lockState.activeWithdrawBalance;
}
function pps() public view returns (uint256 pricePerShare) {
uint256 supply = totalSupply;
return supply == 0 ? 10 ** decimals : (totalAssets() * 10 ** decimals) / supply;
}
function convertToShares(uint256 _assets) public view override returns (uint256) {
uint256 supply = totalSupply;
return supply == 0 ? _assets : ShareMath.assetToShares(_assets, pps(), decimals);
}
function convertToAssets(uint256 _shares) public view override returns (uint256) {
uint256 supply = totalSupply;
return supply == 0 ? _shares : ShareMath.sharesToAsset(_shares, pps(), decimals);
}
function previewDeposit(uint256 _assets) public view override returns (uint256) {
return convertToShares(_assets);
}
function previewMint(uint256 _shares) public view override returns (uint256 _mintAmount) {
uint256 supply = totalSupply;
_mintAmount = supply == 0 ? _shares : ShareMath.sharesToAsset(_shares, pps(), decimals);
}
function previewWithdraw(uint256 _assets) public view override returns (uint256 _withdrawAmount) {
uint256 supply = totalSupply;
_withdrawAmount = supply == 0 ? _assets : ShareMath.assetToShares(_assets, pps(), decimals);
}
function withdrawRequests(address _account) public view returns (QueuedWithdrawal[LOCK_QUEUE_LIMIT] memory) {
QueuedWithdrawal[LOCK_QUEUE_LIMIT] memory accountWithdrawals = withdrawalQueue[_account];
return accountWithdrawals;
}
function getLockState() external view returns (TokenLockState memory state) {
return lockState;
}
function underlyingBalance(address _account) external view returns (uint256 _underlyingBalance) {
return convertToAssets(balanceOf[_account]);
}
function maxDeposit(address) public view override returns (uint256) {
return asset.totalSupply();
}
function maxMint(address) public view override returns (uint256) {
return convertToShares(asset.totalSupply());
}
function maxWithdraw(address owner) public view override returns (uint256) {
return convertToAssets(balanceOf[owner]);
}
function _initiateWithdrawShares(uint256 _shares, uint256 _assets) internal {
require(activeWithdrawals[msg.sender] < LOCK_QUEUE_LIMIT, "TimelockBoost: > LOCK_QUEUE_LIMIT");
_incrementActiveWithdraws(msg.sender, _assets);
_addWithdrawForAccount(msg.sender, _assets);
_burn(msg.sender, _shares);
emit WithdrawInitiated(address(asset), msg.sender, _assets, lockState.withdrawDuration);
}
function _incrementActiveWithdraws(address _account, uint256 _assets) internal {
lockState.activeWithdrawBalance += _assets;
activeWithdrawals[_account] += 1;
require(activeWithdrawals[_account] <= LOCK_QUEUE_LIMIT, "TimelockBoost: !activeWithdrawalsLength");
}
function _decrementActiveWithdraws(address _account, uint256 _assets) internal {
lockState.activeWithdrawBalance -= _assets;
activeWithdrawals[_account] -= 1;
}
function _addWithdrawForAccount(address _account, uint256 _assets) internal {
QueuedWithdrawal[LOCK_QUEUE_LIMIT] storage accountWithdrawals = withdrawalQueue[_account];
for (uint256 i = 0; i < LOCK_QUEUE_LIMIT; i++) {
if (accountWithdrawals[i].queuedTimestamp == 0) {
accountWithdrawals[i].queuedTimestamp = block.timestamp;
accountWithdrawals[i].underlyingAmount = _assets;
return;
}
}
}
function _removeWithdrawForAccount(address _account, uint256 _index) internal returns (uint256 underlyingAmount) {
QueuedWithdrawal[LOCK_QUEUE_LIMIT] storage accountWithdrawals = withdrawalQueue[_account];
require(
accountWithdrawals[_index].queuedTimestamp + lockState.withdrawDuration < block.timestamp,
"TimelockBoost: !withdrawalDuration"
);
underlyingAmount = accountWithdrawals[_index].underlyingAmount;
delete accountWithdrawals[_index];
}
function setZap(address _zap) external onlyConfigurator {
require(_zap != address(0), "TimelockBoost: ZAP set");
ZAP = _zap;
}
function setWithdrawalDuration(uint256 _withdrawalDuration) external onlyConfigurator {
lockState.withdrawDuration = _withdrawalDuration;
}
function pauseDepositWithdraw() external onlyConfigurator {
_pause();
}
function unpauseDepositWithdraw() external onlyConfigurator {
_unpause();
}
modifier onlyZap() {
require(msg.sender == ZAP, "TimelockBoost: !ZAP");
_;
}
}
{
"compilationTarget": {
"src/peripheral/TimelockBoostToken.sol": "TimelockBoost"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 888
},
"remappings": [
":@chainlink/=lib/chainlink/",
":@openzeppelin/=lib/openzeppelin-contracts/",
":@solady/=lib/solady/src/",
":chainlink/=lib/chainlink/integration-tests/contracts/ethereum/src/",
":ds-test/=lib/forge-std/lib/ds-test/src/",
":forge-std/=lib/forge-std/src/",
":gmx-contracts/=lib/gmx-contracts/contracts/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":solady/=lib/solady/",
":solmate/=lib/solmate/src/"
]
}
[{"inputs":[{"internalType":"contract ERC20","name":"_asset","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_withdrawDuration","type":"uint256"},{"internalType":"contract Auth","name":"_auth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"address","name":"_account","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"address","name":"_account","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"WithdrawComplete","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"address","name":"_account","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"WithdrawInitiated","type":"event"},{"inputs":[],"name":"AUTH","outputs":[{"internalType":"contract Auth","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ZAP","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"activeWithdrawals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"claimWithdrawals","outputs":[{"internalType":"uint256","name":"_totalWithdraw","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"claimWithdrawalsFor","outputs":[{"internalType":"uint256","name":"_totalWithdraw","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getLockState","outputs":[{"components":[{"internalType":"uint256","name":"withdrawDuration","type":"uint256"},{"internalType":"uint256","name":"activeWithdrawBalance","type":"uint256"}],"internalType":"struct TimelockBoost.TokenLockState","name":"state","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"initiateRedeem","outputs":[{"internalType":"uint256","name":"_assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assets","type":"uint256"}],"name":"initiateWithdraw","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockState","outputs":[{"internalType":"uint256","name":"withdrawDuration","type":"uint256"},{"internalType":"uint256","name":"activeWithdrawBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseDepositWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pps","outputs":[{"internalType":"uint256","name":"pricePerShare","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assets","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"_mintAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assets","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"_withdrawAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_withdrawalDuration","type":"uint256"}],"name":"setWithdrawalDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_zap","type":"address"}],"name":"setZap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"underlyingBalance","outputs":[{"internalType":"uint256","name":"_underlyingBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpauseDepositWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"withdrawRequests","outputs":[{"components":[{"internalType":"uint256","name":"queuedTimestamp","type":"uint256"},{"internalType":"uint256","name":"underlyingAmount","type":"uint256"}],"internalType":"struct TimelockBoost.QueuedWithdrawal[5]","name":"","type":"tuple[5]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"withdrawalQueue","outputs":[{"internalType":"uint256","name":"queuedTimestamp","type":"uint256"},{"internalType":"uint256","name":"underlyingAmount","type":"uint256"}],"stateMutability":"view","type":"function"}]