A governance lending protocol transforming users voting power into a new money lego.
Platform: Code4rena
Start Date: 27/10/2022
End Date: 30/10/2022
Period: 3 days
Status: Completed
Pot Size: $33,500 USDC
Participants: 96
Reporter: itsmetechjay
Judge: kirk-baird
Id: 176
League: ETH
0x52 | 1/96 | $5,767.74 | 5 | 0 | 0 | 4 | 0 | Grade B | 0 | 0 |
cccz | 2/96 | $5,659.22 | 4 | 0 | 0 | 3 | 1 | Grade B | 0 | 0 |
Trust | 3/96 | $3,013.36 | 5 | 0 | 0 | 4 | 0 | Grade B | 0 | 0 |
bin2chen | 4/96 | $1,863.05 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
Chom | 5/96 | $1,314.86 | 3 | 0 | 0 | 2 | 0 | Grade B | 0 | 0 |
pashov | 6/96 | $1,308.38 | 3 | 0 | 0 | 2 | 0 | Grade A | 0 | 0 |
indijanc | 7/96 | $1,241.67 | 2 | 0 | 0 | 1 | 0 | 0 | Grade A | 0 |
Jeiwan | 8/96 | $1,192.69 | 4 | 0 | 0 | 3 | 0 | Grade B | 0 | 0 |
Picodes | 9/96 | $795.60 | 4 | 0 | 0 | 2 | 0 | Grade B | Grade B | 0 |
KingNFT | 10/96 | $754.53 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
Auditor per page
The C4audit output for the contest can be found here.
Note for C4 wardens: Anything included in the C4udit output is considered a publicly known issue and is ineligible for awards.
Paladin builds different products revolving around tokenomics, voting power delegation & veTokens (more info on the website). Warden is a system focusing on veTokens, with the Warden Boost market to purchase boosting power from veCRV holders to optimize your Curve LP rewards distribution, and Quest to offer a better system for Gauge votes acquisition (more info on Quest here). This Contest is aimed at the new piece to be added to the Warden system, called Pledge, with the goal of providing another type of marketplace for veCRV boosting power, through a new logic that mixes pieces from the Boost market and from Quest. (The Pledge smart contract is based on the logic of Curve's veBoost, by using the BoostV2 contract to delegate boosting power that has been approved to Warden Pledge by the veCRV holder. The Curve veBoost contracts & tests can be found here).
There is only 1 contract in the scope of this contest: WardenPledge
WardenPledge is a contract supposed to receive ERC20 incentives (ERC20 tokens must be whitelisted before being deposited) that will be distributed to users that delegate veCRV boost power (using the Boostv2 contract) through the Warden Pledge contract. DAOs/Protocols/etc.. will be able to set a Pledge with a given reward per vote delegated, for a fixed duration, and pay only for the boost effectively received (delegators rewards calculations take in account the boost delegation decrease over time).
For more info, see "System Overview".
External Calls:
ERC20
contracts (through the SafeERC20
lib):
IERC20(pledgeParams.rewardToken).safeTransfer(user, rewardAmount);
IERC20(rewardToken).safeTransferFrom(creator, address(this), vars.totalRewardAmount);
IERC20(rewardToken).safeTransferFrom(creator, chestAddress, vars.feeAmount);
IERC20(pledgeParams.rewardToken).safeTransferFrom(creator, address(this), totalRewardAmount);
IERC20(pledgeParams.rewardToken).safeTransferFrom(creator, chestAddress, feeAmount);
IERC20(pledgeParams.rewardToken).safeTransferFrom(creator, address(this), totalRewardAmount);
IERC20(pledgeParams.rewardToken).safeTransferFrom(creator, chestAddress, feeAmount);
IERC20(pledgeParams.rewardToken).safeTransfer(receiver, remainingAmount);
IERC20(pledgeParams.rewardToken).safeTransfer(receiver, remainingAmount);
IERC20(token).balanceOf(address(this));
IERC20(token).safeTransfer(owner(), amount);
veCRV
(0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2
):
uint256 amount = (votingEscrow.balanceOf(msg.sender) * percent) / MAX_PCT;
vars.votesDifference = targetVotes - votingEscrow.balanceOf(receiver);
BoostV2
(0xD0921691C7DEBc698e6e372c6f74dc01fc9d3778
):
delegationBoost.checkpoint_user(user);
delegationBoost.delegable_balance(user)
delegationBoost.adjusted_balance_of(pledgeParams.receiver);
delegationBoost.boost(pledgeParams.receiver,amount,endTimestamp,user);
Libraires & Dependencies:
IERC20.sol
(openzeppelin)SafeERC20.sol
(openzeppelin)Ownable.sol
(openzeppelin) => turned into 2-step system in Owner.sol
Pausable.sol
(openzeppelin)ReentrancyGuard.sol
(openzeppelin)New version of the Warden Boost Market, based on a mix between the current Warden v2 logic and Warden Quest base logic (see our Docs for more info on Warden & Quest).
Reward tokens (ERC20
) must be whitelisted before being used as a rewards for Pledges.
Pledges have a target amount of veCRV to reach (sum of the receiving address veCRV balance + any veCRV delegated through the veBoost system) and an amount of rewards for each veCRV delegated through the Pledge. Users joining the Pledge (delegating to the Pledge receiver address) will always receive a fix amount rewards, based on the decreasing amount of veCRV delegated in their Boost (meaning that for a Boost of 100 veCRV over 2 weeks, the user rewards are calculated based on the decrease from 100 to 0 delegated through the 2 weeks).
Each Pledge has an end timestamp
after which the Pledge is expired
and will not accept any new delegation, and all Boost for that Pledge will also end at maximum at that end timestamp
. Pledge's creators can also close a Pledge before it is expired
, and retrieve all undistributed rewards. All undistributed rewards from the Pledge can also be retrieved after the Pledge is expired
.
All rewards for delegation are paid when the user joins the Pledge, because the veBoost is not cancelable.
!! This contract cannot update the receiver Gauge checkpoints when receiving new delegated veBoost (so the newly delegated amount is accounted for CRV farming in Gauges), and will require an update to be done manually.
To start, make sure you have node
& npm
installed :
node
- tested with v16npm
- tested with v8.1Then, copy .env.example
and fill all variables.
Then, run :
npm install
This will install Hardhat
, Ethers v5
, and all the hardhat plugins used in this project.
! Follow the steps in "Set up environment" before trying to run the tests.
Tests can be found in the ./test
directory.
To run the tests :
npm run build npm run test