Platform: Code4rena
Start Date: 28/11/2022
Pot Size: $192,500 USDC
Total HM: 33
Participants: 106
Period: 11 days
Judge: LSDan
Total Solo HM: 15
Id: 186
League: ETH
Rank: 78/106
Findings: 1
Award: $103.92
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0x4non, 0x52, 0xAgro, 0xNazgul, 0xSmartContract, 0xackermann, 9svR6w, Awesome, Aymen0909, B2, BRONZEDISC, Bnke0x0, Deekshith99, Deivitto, Diana, Dravee, HE1M, Jeiwan, Kaiziron, KingNFT, Lambda, Mukund, PaludoX0, RaymondFam, Rolezn, Sathish9098, Secureverse, SmartSek, __141345__, ahmedov, ayeslick, brgltd, cccz, ch0bu, chrisdior4, cryptonue, cryptostellar5, csanuragjain, datapunk, delfin454000, erictee, gz627, gzeon, helios, i_got_hacked, ignacio, imare, jadezti, jayphbee, joestakey, kankodu, ksk2345, ladboy233, martin, nadin, nicobevi, oyc_109, pashov, pavankv, pedr02b2, pzeus, rbserver, ronnyx2017, rvierdiiev, shark, unforgiven, xiaoming90, yjrwkk
103.9175 USDC - $103.92
If the intention is for the Ether to be used, the function should call another function, otherwise it should revert. Having no access control on the function means that someone may send Ether to the contract, and have no way to get anything back out, which is a loss of funds.
149 receive() external payable {}
__gap[50]
storage variable to allow for new storage variables in later versionsSee the following link for a description of this storage variable. While some contracts may not currently be sub-classed, adding the variable now protects against forgetting to add it in the future.
19 contract WPunkGateway is 20 ReentrancyGuard, 21 IWPunkGateway, 22 IERC721Receiver, 23 OwnableUpgradeable 24 {
As per OpenZeppelin’s (OZ) recommendation, “The guidelines are now to make it impossible for anyone to run initialize on an implementation contract, by adding an empty constructor with the initializer modifier. So the implementation contract gets initialized automatically upon deployment.”
Note that this behaviour is also incorporated the OZ Wizard since the UUPS vulnerability discovery: “Additionally, we modified the code generated by the Wizard 19 to include a constructor that automatically initializes the implementation when deployed.”
57 function initialize() external initializer {
75 function initialize(IPoolAddressesProvider provider)
36 function initialize(
52 function initialize(
97 function initialize(
Constructors should check the address written in an immutable address variable is not the zero address.
51 constructor(IPoolAddressesProvider provider) { 52 ADDRESSES_PROVIDER = provider; 53 }
64 constructor(IPoolAddressesProvider provider) { 65 ADDRESSES_PROVIDER = provider; 66 }
62 constructor(IPoolAddressesProvider provider) { 63 ADDRESSES_PROVIDER = provider; 64 }
89 constructor(IPoolAddressesProvider provider) { 90 ADDRESSES_PROVIDER = provider; 91 }
32 constructor(IPool pool, address apeCoinStaking) NToken(pool, false) { 33 _apeCoinStaking = ApeCoinStaking(apeCoinStaking); 34 }
43 constructor( 44 address _punk, 45 address _wpunk, 46 address _pool 47 ) { 48 punk = _punk; 49 wpunk = _wpunk; 50 pool = _pool; 51 52 Punk = IPunks(punk); 53 WPunk = IWrappedPunks(wpunk); 54 Pool = IPool(pool); 55 }
49 constructor( 50 IPoolAddressesProvider provider, 51 address[] memory assets, 52 address[] memory sources, 53 address fallbackOracle, 54 address baseCurrency, 55 uint256 baseCurrencyUnit 56 ) { 57 ADDRESSES_PROVIDER = provider; 58 BASE_CURRENCY = baseCurrency; 59 BASE_CURRENCY_UNIT = baseCurrencyUnit; 60 _setFallbackOracle(fallbackOracle); 61 _setAssetsSources(assets, sources); 62 emit BaseCurrencySet(baseCurrency, baseCurrencyUnit); 63 }
23 constructor( 24 address _factory, 25 address _manager, 26 address _addressProvider 27 ) { 28 UNISWAP_V3_FACTORY = IUniswapV3Factory(_factory); 29 UNISWAP_V3_POSITION_MANAGER = INonfungiblePositionManager(_manager); 30 ADDRESSES_PROVIDER = IPoolAddressesProvider(_addressProvider); 31 }
string.concat()
instead of abi.encodePacked(<str>,<str>)
using for
with a list of free functionsAll contracts in scope use version 0.8.10
Code architecture, incentives, and error handling/reporting questions/issues should be resolved before deployment.
238 // TODO using bit shifting for the 2^96
59 makerAsk.price, // TODO: take minPercentageToAsk into account
nonReentrant modifier
should occur before all other modifiersThis is a best-practice to protect against reentrancy in other modifiers.
79 function mint( 80 address onBehalfOf, 81 DataTypes.ERC721SupplyParams[] calldata tokenData 82 ) external virtual override onlyPool nonReentrant returns (uint64, uint64) { ... 87 function burn( 88 address from, 89 address receiverOfUnderlying, 90 uint256[] calldata tokenIds 91 ) external virtual override onlyPool nonReentrant returns (uint64, uint64) { ... 119 function transferOnLiquidation( 120 address from, 121 address to, 122 uint256 value 123 ) external onlyPool nonReentrant { ... 199 function transferUnderlyingTo(address target, uint256 tokenId) 200 external 201 virtual 202 override 203 onlyPool 204 nonReentrant 205 { ... 214 function handleRepayment(address user, uint256 amount) 215 external 216 virtual 217 override 218 onlyPool 219 nonReentrant 220 {
102 function burn( 103 address from, 104 address receiverOfUnderlying, 105 uint256[] calldata tokenIds 106 ) external virtual override onlyPool nonReentrant returns (uint64, uint64) { ... 159 function unstakePositionAndRepay(uint256 tokenId, address incentiveReceiver) 160 external 161 onlyPool 162 nonReentrant 163 {
26 function depositApeCoin(ApeCoinStaking.SingleNft[] calldata _nfts) 27 external 28 onlyPool 29 nonReentrant 30 { ... 39 function claimApeCoin(uint256[] calldata _nfts, address _recipient) 40 external 41 onlyPool 42 nonReentrant 43 { ... 52 function withdrawApeCoin( 53 ApeCoinStaking.SingleNft[] calldata _nfts, 54 address _recipient 55 ) external onlyPool nonReentrant { ... 66 function depositBAKC(ApeCoinStaking.PairNftWithAmount[] calldata _nftPairs) 67 external 68 onlyPool 69 nonReentrant 70 { ... 82 function claimBAKC( 83 ApeCoinStaking.PairNft[] calldata _nftPairs, 84 address _recipient 85 ) external onlyPool nonReentrant { ... 97 function withdrawBAKC( 98 ApeCoinStaking.PairNftWithAmount[] memory _nftPairs, 99 address _apeRecipient 100 ) external onlyPool nonReentrant {
26 function depositApeCoin(ApeCoinStaking.SingleNft[] calldata _nfts) 27 external 28 onlyPool 29 nonReentrant 30 { ... 39 function claimApeCoin(uint256[] calldata _nfts, address _recipient) 40 external 41 onlyPool 42 nonReentrant 43 { ... 52 function withdrawApeCoin( 53 ApeCoinStaking.SingleNft[] calldata _nfts, 54 address _recipient 55 ) external onlyPool nonReentrant { ... 66 function depositBAKC(ApeCoinStaking.PairNftWithAmount[] calldata _nftPairs) 67 external 68 onlyPool 69 nonReentrant 70 { ... 82 function claimBAKC( 83 ApeCoinStaking.PairNft[] calldata _nftPairs, 84 address _recipient 85 ) external onlyPool nonReentrant { ... 97 function withdrawBAKC( 98 ApeCoinStaking.PairNftWithAmount[] memory _nftPairs, 99 address _apeRecipient 100 ) external onlyPool nonReentrant {
40 function burn( 41 address from, 42 address receiverOfUnderlying, 43 uint256[] calldata tokenIds 44 ) external virtual override onlyPool nonReentrant returns (uint64, uint64) {
123 function decreaseUniswapV3Liquidity( 124 address user, 125 uint256 tokenId, 126 uint128 liquidityDecrease, 127 uint256 amount0Min, 128 uint256 amount1Min, 129 bool receiveEthAsWeth 130 ) external onlyPool nonReentrant {
It is best practice to set visibility for state variables.
18 IUniswapV3Factory immutable UNISWAP_V3_FACTORY; 19 INonfungiblePositionManager immutable UNISWAP_V3_POSITION_MANAGER;
21 ApeCoinStaking immutable _apeCoinStaking;
22 uint256 constant BAYC_POOL_ID = 1; 23 uint256 constant MAYC_POOL_ID = 2; 24 uint256 constant BAKC_POOL_ID = 3;
23 bytes32 constant APE_STAKING_DATA_STORAGE_POSITION =
16 bytes32 constant POOL_STORAGE_POSITION =
#0 - c4-judge
2023-01-25T11:48:57Z
dmvt marked the issue as grade-b