Platform: Code4rena
Start Date: 23/06/2023
Pot Size: $60,500 USDC
Total HM: 31
Participants: 132
Period: 10 days
Judge: 0xean
Total Solo HM: 10
Id: 254
League: ETH
Rank: 58/132
Findings: 2
Award: $122.46
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xnev
Also found by: 0xRobocop, 0xbrett8571, 0xkazim, 0xnacho, 3agle, 8olidity, ABAIKUNANBAEV, Bauchibred, Co0nan, CrypticShepherd, D_Auditor, DelerRH, HE1M, Iurii3, Kaysoft, MrPotatoMagic, RedOneN, RedTiger, Rolezn, SanketKogekar, Sathish9098, Timenov, Toshii, Vagner, bart1e, bytes032, codetilda, devival, halden, hals, kutugu, m_Rassska, naman1778, nonseodion, seth_lawson, solsaver, squeaky_cactus, totomanov, y51r, yudan, zaevlad
57.9031 USDC - $57.90
IPeUSD
The interface used is IEUSD
, but it can be IPeUSD
.
55: IEUSD public peUSD;
tokenMinerChanges
should be renamed to TokenMinerChanges
to be consistent with the naming convention of other event70: event tokenMinerChanges(address indexed pool, bool status);
initToken
can actually be called twiceThe documentation states that the following function can only be executed once, but in reality it can be called twice if we set one address to non-zero address at a time, like initToken(0, 0x123); initToken(0x123, 0);
95: /** 96: * @notice Initializes the eUSD and peUSD address. This function can only be executed once. 97: */ 98: function initToken(address _eusd, address _peusd) external onlyRole(DAO) { 99: if (address(EUSD) == address(0)) EUSD = IEUSD(_eusd); 100: if (address(peUSD) == address(0)) peUSD = IEUSD(_peusd); 101: }
IPeUSD
The interface used is IEUSD
, but it can be IPeUSD
.
100: if (address(peUSD) == address(0)) peUSD = IEUSD(_peusd);
assetAmount
Must be higher than 0." is actually implemented as >= 1 ethThe documentation states that the assetAmount
should be higher than 0, but the actual check in the code is that the amount should be greater than 1 ether.
73: require(assetAmount >= 1 ether, "Deposit should not be less than 1 stETH.");
59: require(assetAmount >= 1 ether, "Deposit should not be less than 1 collateral asset.");
amount
is higher than 0The documentation states that amount
should be higher than 0, but there are no checks in place for it.
132: /** 133: * @notice Burn the amount of EUSD and payback the amount of minted EUSD 134: * Emits a `Burn` event. 135: * Requirements: 136: * - `onBehalfOf` cannot be the zero address. 137: * - `amount` Must be higher than 0. 138: * @dev Calling the internal`_repay`function. 139: */ 140: function burn(address onBehalfOf, uint256 amount) external { 141: require(onBehalfOf != address(0), "BURN_TO_THE_ZERO_ADDRESS"); 142: _repay(msg.sender, onBehalfOf, amount); 143: }
require
statements should always include some relevant error messages if the requirements fails ot get satisfied
62: require(collateralAsset.balanceOf(address(this)) >= preBalance + assetAmount, "");
MintPaused
should be MintNotPaused
83: modifier MintPaused() { 84: require(!configurator.vaultMintPaused(msg.sender), "MPP"); 85: _; 86: }
Link: https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/EUSD.sol#L83-L86
BurnPaused
should be BurnNotPaused
87: modifier BurnPaused() { 88: require(!configurator.vaultBurnPaused(msg.sender), "BPP"); 89: _; 90: }
Link: https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/EUSD.sol#L87-L90
The links should be updated to use:
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/cb4bf950df5ae43356c4935b3900446f6dc20261/contracts/token/ERC20/IERC20.sol#L62 or https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#approve
240: * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol#L42
Link: https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/EUSD.sol#L240
259: * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol#L42
Link: https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/EUSD.sol#L259
_sharesAmount
but cannot find it anywhere in the codeThe documentation states that "Creates _sharesAmount
shares", but this is not found in the code.
402: /** 403: * @notice Creates `_sharesAmount` shares and assigns them to `_recipient`, increasing the total amount of shares. 404: * @dev This operation also increases the total supply of tokens. 405: * 406: * Requirements: 407: * 408: * - `_recipient` cannot be the zero address. 409: * - the contract must not be paused. 410: */ 411: function mint(address _recipient, uint256 _mintAmount) external onlyMintVault MintPaused returns (uint256 newTotalShares) { 412: require(_recipient != address(0), "MINT_TO_THE_ZERO_ADDRESS"); 413: 414: uint256 sharesAmount = getSharesByMintedEUSD(_mintAmount); 415: if (sharesAmount == 0) { 416: //EUSD totalSupply is 0: assume that shares correspond to EUSD 1-to-1 417: sharesAmount = _mintAmount; 418: } 419: 420: newTotalShares = _totalShares.add(sharesAmount); 421: _totalShares = newTotalShares; 422: 423: shares[_recipient] = shares[_recipient].add(sharesAmount); 424: 425: _totalSupply += _mintAmount; 426: 427: emit Transfer(address(0), _recipient, _mintAmount); 428: }
Link: https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/EUSD.sol#L402-L428
#0 - c4-pre-sort
2023-07-27T19:43:47Z
JeffCX marked the issue as high quality report
#1 - c4-judge
2023-07-27T23:56:17Z
0xean marked the issue as grade-a
#2 - c4-sponsor
2023-07-29T09:36:53Z
LybraFinance marked the issue as sponsor confirmed
🌟 Selected for report: Sathish9098
Also found by: 0x3b, 0xbrett8571, ABAIKUNANBAEV, K42, MrPotatoMagic, hl_, ktg, peanuts, solsaver
64.5593 USDC - $64.56
The codebase was decent sized, and it took me the whole duration to get a hang of the contract and find possible issues. Missing tests did pose some testing challenges and slowdown, but I was able to write up some tests from scratch to validate the possible issues.
There were several possible centralization as pointed out in the automated findings: https://gist.github.com/liveactionllama/27513952718ec3cbcf9de0fda7fef49c#m04-the-owner-is-a-single-point-of-failure-and-a-centralization-risk
Since the start date, I have spent around 3-4 hours everyday days on this codebase after my work. I spent time on this codebase everyday, so almost clocking in 30-35 hours on this. I might have spent additional 5 hours on the documentation. I had to spent a day to figure out how to write the tests in hardhat, but that wasnt too bad.
40 hours
#0 - c4-sponsor
2023-07-27T08:42:13Z
LybraFinance marked the issue as sponsor confirmed
#1 - c4-judge
2023-07-28T17:08:03Z
0xean marked the issue as grade-b
#2 - c4-judge
2023-07-28T17:13:53Z
0xean marked the issue as satisfactory