Skip to content

Commit

Permalink
feat: the pounder now compiles
Browse files Browse the repository at this point in the history
  • Loading branch information
0xtekgrinder committed Nov 14, 2023
1 parent 15f77b4 commit 41ec980
Show file tree
Hide file tree
Showing 12 changed files with 568 additions and 24 deletions.
5 changes: 2 additions & 3 deletions contracts/src/abstracts/AIncentiveClaimer.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
//SPDX-License-Identifier GPL-3.0-or-later
pragma solidity 0.8.20;

import "interfaces/IIncentivizedLocker.sol";
import {
IQuestDistributor,
IDelegationDistributor,
IVotiumDistributor,
IHiddenHandDistributor
} from "warlord/interfaces/external/incentives/IIncentivesDistributors.sol";
} from "../external/incentives/IIncentivesDistributors.sol";
import { Errors } from "utils/Errors.sol";
import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol";
import { ERC20 } from "solady/tokens/ERC20.sol";
Expand All @@ -18,7 +17,7 @@ import { ReentrancyGuard } from "solmate/utils/ReentrancyGuard.sol";
* @author Paladin
* @notice Locker contract capable of claiming vote rewards from different sources
*/
abstract contract AIncentiveClaimer is IIncentivizedLocker, ReentrancyGuard {
abstract contract AIncentiveClaimer is ReentrancyGuard {
/**
* @notice Claims voting rewards from Quest
* @param distributor Address of the contract distributing the rewards
Expand Down
133 changes: 113 additions & 20 deletions contracts/src/abstracts/APounder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,106 @@ import { AIncentiveClaimer } from "./AIncentiveClaimer.sol";
import { AProtocolClaimer } from "./AProtocolClaimer.sol";
import { Ownable } from "solady/auth/Ownable.sol";
import { ERC20 } from "solady/tokens/ERC20.sol";
import { ERC1155 } from "solady/tokens/ERC1155.sol";
import { CvxLockerV2 } from "../external/convex/vlCvx.sol";

abstract contract APounder is ERC20, AIncentiveClaimer, AProtocolClaimer, Ownable {
using SafeTransferLib for ERC20;

CvxLockerV2 public cvxLocker;

address public asset;
address public swapper;
ERC1155 public upxCvx;

enum Fees {
Reward,
RedemptionMax,
RedemptionMin,
Developers
}

// Convex voting round duration (1,209,600 seconds)
uint32 public constant EPOCH_DURATION = 2 weeks;

// Fee denominator
uint32 public constant FEE_DENOMINATOR = 1_000_000;

// Fee maximum
uint32 public constant FEE_MAX = 100_000;

// Maximum wait time for a CVX redemption (10,281,600 seconds)
uint32 public constant MAX_REDEMPTION_TIME = 17 weeks;

// Unused ERC1155 `data` param value
bytes private constant UNUSED_1155_DATA = "";

mapping(Fees => uint32) public fees;

// Convex unlock timestamps mapped to amount being redeemed
mapping(uint256 => uint256) public redemptions;

event SetFee(Fees indexed f, uint32 fee);
event AddDeveloper(address developer);
event RemoveDeveloper(address developer);
event Deposit(
uint256 assets,
address indexed receiver,
bool indexed shouldCompound,
address indexed developer
);
event InitiateRedemptions(
uint256[] lockIndexes,
uint256[] assets,
address indexed receiver
);
event Redeem(
uint256[] unlockTimes,
uint256[] assets,
address indexed receiver,
bool legacy
);
event Stake(
uint256 rounds,
uint256 assets,
address indexed receiver
);
event Unstake(uint256 id, uint256 assets, address indexed receiver);
// event ClaimMiscRewards(uint256 timestamp, ConvexReward[] rewards);
event ClaimVotiumReward(
address indexed token,
uint256 index,
uint256 amount
);
event RedeemSnapshotRewards(
uint256 indexed epoch,
uint256[] rewardIndexes,
address indexed receiver,
uint256 snapshotBalance,
uint256 snapshotSupply
);
event InitializeEmergencyExecutor(address _emergencyExecutor);
// event SetEmergencyMigration(EmergencyMigration _emergencyMigration);
event SetUpxCvxDeprecated(bool state);
event ExecuteEmergencyMigration(address recipient, address[] tokens);

error ZeroAmount();
error BeforeUnlock();
error AlreadyRedeemed();
error InsufficientRedemptionAllowance();
error PastExchangePeriod();
error InvalidFee();
error BeforeEffectiveTimestamp();
error BeforeStakingExpiry();
error InvalidEpoch();
error EmptyArray();
error MismatchedArrayLengths();
error NoRewards();
error RedeemClosed();
error NoEmergencyExecutor();
error InvalidEmergencyMigration();
error NotAuthorized();
error ZeroAddress();
/**
* @notice Address of the voting power delegate
*/
Expand Down Expand Up @@ -52,12 +148,11 @@ abstract contract APounder is ERC20, AIncentiveClaimer, AProtocolClaimer, Ownabl

/**
* @dev Locks the tokens in the vlToken contract
* @param amount Amount to lock
*/
function lock() external {
_processUnlock();

uint256 balance = asset.balanceOf(address(this));
uint256 balance = ERC20(asset).balanceOf(address(this));
bool balanceGreaterThanRedemptions = balance > outstandingRedemptions;

// Lock CVX if the balance is greater than outstanding redemptions or if there are pending locks
Expand Down Expand Up @@ -97,8 +192,7 @@ abstract contract APounder is ERC20, AIncentiveClaimer, AProtocolClaimer, Ownabl
}

function _initiateRedemption(
ICvxLocker.LockedBalance memory lockData,
Futures f,
CvxLockerV2.LockedBalance memory lockData,
uint256 assets,
address receiver,
uint256 feeMin,
Expand Down Expand Up @@ -132,26 +226,24 @@ abstract contract APounder is ERC20, AIncentiveClaimer, AProtocolClaimer, Ownabl
outstandingRedemptions += postFeeAmount;

// Mint upxCVX with unlockTime as the id - validates `to`
upxCvx.mint(receiver, unlockTime, postFeeAmount, UNUSED_1155_DATA);
// upxCvx.mint(receiver, unlockTime, postFeeAmount, UNUSED_1155_DATA);

return feeAmount;
}

function initiateRedemptions(
uint256[] calldata lockIndexes,
Futures f,
uint256[] calldata assets,
address receiver
) external whenNotPaused nonReentrant {
) external nonReentrant {
uint256 lockLen = lockIndexes.length;

if (lockLen == 0) revert EmptyArray();
if (lockLen != assets.length) revert MismatchedArrayLengths();

emit InitiateRedemptions(lockIndexes, f, assets, receiver);
emit InitiateRedemptions(lockIndexes, assets, receiver);

(, , , ICvxLocker.LockedBalance[] memory lockData) = cvxLocker
.lockedBalances(address(this));
(, , , CvxLockerV2.LockedBalance[] memory lockData) = cvxLocker.lockedBalances(address(this));
uint256 totalAssets;
uint256 feeAmount;
uint256 feeMin = fees[Fees.RedemptionMin];
Expand All @@ -161,7 +253,6 @@ abstract contract APounder is ERC20, AIncentiveClaimer, AProtocolClaimer, Ownabl
totalAssets += assets[i];
feeAmount += _initiateRedemption(
lockData[lockIndexes[i]],
f,
assets[i],
receiver,
feeMin,
Expand All @@ -170,14 +261,16 @@ abstract contract APounder is ERC20, AIncentiveClaimer, AProtocolClaimer, Ownabl
}

// Burn pxCVX - reverts if sender balance is insufficient
pxCvx.burn(msg.sender, totalAssets - feeAmount);
_burn(msg.sender, totalAssets - feeAmount);

if (feeAmount != 0) {
/*
// Allow PirexFees to distribute fees directly from sender
pxCvx.operatorApprove(msg.sender, address(pirexFees), feeAmount);
// Distribute fees
pirexFees.distributeFees(msg.sender, address(pxCvx), feeAmount);
*/
}
}

Expand All @@ -198,36 +291,36 @@ abstract contract APounder is ERC20, AIncentiveClaimer, AProtocolClaimer, Ownabl
uint256 totalAssets;

for (uint256 i; i < unlockLen; ++i) {
uint256 asset = assets[i];
uint256 assett = assets[i];

if (!legacy && unlockTimes[i] > block.timestamp)
revert BeforeUnlock();
if (asset == 0) revert ZeroAmount();
if (assett == 0) revert ZeroAmount();

totalAssets += asset;
totalAssets += assett;
}

// Perform unlocking and locking procedure to ensure enough CVX is available
if (!legacy) {
_lock();
_lock(totalAssets);
}

// Subtract redemption amount from outstanding CVX amount
outstandingRedemptions -= totalAssets;

// Reverts if sender has an insufficient upxCVX balance for any `unlockTime` id
upxCvx.burnBatch(msg.sender, unlockTimes, assets);
// upxCvx.burnBatch(msg.sender, unlockTimes, assets);

// Validates `to`
asset.safeTransfer(receiver, totalAssets);
SafeTransferLib.safeTransfer(asset, receiver, totalAssets);
}

function redeem(
uint256[] calldata unlockTimes,
uint256[] calldata assets,
address receiver
) external whenNotPaused nonReentrant {
if (upxCvxDeprecated) revert RedeemClosed();
) external nonReentrant {
// if (upxCvxDeprecated) revert RedeemClosed();

_redeem(unlockTimes, assets, receiver, false);
}
Expand Down
8 changes: 8 additions & 0 deletions contracts/src/external/IDelegateRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: Unlicensed
pragma solidity ^0.8.0;

interface IDelegateRegistry {
function delegation(address delegator, bytes32 id) external view returns (address);
function setDelegate(bytes32 id, address delegate) external;
function clearDelegate(bytes32 id) external;
}
47 changes: 47 additions & 0 deletions contracts/src/external/aura/AuraBalStaker.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: Unlicensed
pragma solidity ^0.8.0;

interface BaseRewardPool {
event RewardAdded(uint256 reward);
event RewardPaid(address indexed user, uint256 reward);
event Staked(address indexed user, uint256 amount);
event Transfer(address indexed from, address indexed to, uint256 value);
event Withdrawn(address indexed user, uint256 amount);

function addExtraReward(address _reward) external returns (bool);
function balanceOf(address account) external view returns (uint256);
function clearExtraRewards() external;
function currentRewards() external view returns (uint256);
function duration() external view returns (uint256);
function earned(address account) external view returns (uint256);
function extraRewards(uint256) external view returns (address);
function extraRewardsLength() external view returns (uint256);
function getReward() external returns (bool);
function getReward(address _account, bool _claimExtras) external returns (bool);
function historicalRewards() external view returns (uint256);
function lastTimeRewardApplicable() external view returns (uint256);
function lastUpdateTime() external view returns (uint256);
function newRewardRatio() external view returns (uint256);
function operator() external view returns (address);
function periodFinish() external view returns (uint256);
function pid() external view returns (uint256);
function processIdleRewards() external;
function queueNewRewards(uint256 _rewards) external returns (bool);
function queuedRewards() external view returns (uint256);
function rewardManager() external view returns (address);
function rewardPerToken() external view returns (uint256);
function rewardPerTokenStored() external view returns (uint256);
function rewardRate() external view returns (uint256);
function rewardToken() external view returns (address);
function rewards(address) external view returns (uint256);
function stake(uint256 _amount) external returns (bool);
function stakeAll() external returns (bool);
function stakeFor(address _for, uint256 _amount) external returns (bool);
function stakingToken() external view returns (address);
function totalSupply() external view returns (uint256);
function userRewardPerTokenPaid(address) external view returns (uint256);
function withdraw(uint256 amount, bool claim) external returns (bool);
function withdrawAll(bool claim) external;
function withdrawAllAndUnwrap(bool claim) external;
function withdrawAndUnwrap(uint256 amount, bool claim) external returns (bool);
}
14 changes: 14 additions & 0 deletions contracts/src/external/aura/AuraDepositor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: Unlicensed
pragma solidity ^0.8.0;

interface CrvDepositorWrapper {
function BAL() external view returns (address);
function BALANCER_POOL_TOKEN() external view returns (address);
function BALANCER_VAULT() external view returns (address);
function BAL_ETH_POOL_ID() external view returns (bytes32);
function WETH() external view returns (address);
function crvDeposit() external view returns (address);
function deposit(uint256 _amount, uint256 _minOut, bool _lock, address _stakeAddress) external;
function getMinOut(uint256 _amount, uint256 _outputBps) external view returns (uint256);
function setApprovals() external;
}
17 changes: 17 additions & 0 deletions contracts/src/external/aura/IRewards.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: Unlicensed
pragma solidity ^0.8.0;

interface IRewards {
function stake(address, uint256) external;
function stakeFor(address, uint256) external;
function withdraw(address, uint256) external;
function exit(address) external;
function getReward(address) external;
function queueNewRewards(uint256) external;
function notifyRewardAmount(uint256) external;
function addExtraReward(address) external;
function extraRewardsLength() external view returns (uint256);
function stakingToken() external view returns (address);
function rewardToken() external view returns (address);
function earned(address account) external view returns (uint256);
}
Loading

0 comments on commit 41ec980

Please sign in to comment.