Platform: Code4rena
Start Date: 18/10/2022
Pot Size: $75,000 USDC
Total HM: 27
Participants: 144
Period: 7 days
Judge: gzeon
Total Solo HM: 13
Id: 170
League: ETH
Rank: 65/144
Findings: 2
Award: $55.67
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Rolezn
Also found by: 0x1f8b, 0x52, 0x5rings, 0xNazgul, 0xSmartContract, 0xZaharina, 0xhunter, 0xzh, 8olidity, Amithuddar, Aymen0909, B2, Bnke0x0, Chom, Deivitto, Diana, Diraco, Dravee, Franfran, JC, Jeiwan, Josiah, JrNet, Jujic, KingNFT, KoKo, Lambda, Margaret, Migue, Ocean_Sky, PaludoX0, Picodes, Rahoz, RaoulSchaffranek, RaymondFam, RedOneN, ReyAdmirado, Shinchan, Tagir2003, Trust, Waze, Yiko, __141345__, a12jmx, adriro, ajtra, arcoun, aysha, ballx, bin2chen, bobirichman, brgltd, bulej93, catchup, catwhiskeys, caventa, cccz, cdahlheimer, ch0bu, chaduke, chrisdior4, cloudjunky, cryptostellar5, cryptphi, csanuragjain, cylzxje, d3e4, delfin454000, djxploit, durianSausage, erictee, fatherOfBlocks, francoHacker, gianganhnguyen, gogo, hansfriese, i_got_hacked, ignacio, imare, karanctf, kv, leosathya, louhk, lukris02, lyncurion, m_Rassska, malinariy, martin, mcwildy, mics, minhtrng, nicobevi, oyc_109, pashov, peanuts, pedr02b2, peiw, rbserver, ret2basic, rotcivegaf, rvierdiiev, ryshaw, sakman, sakshamguruji, saneryee, securerodd, seyni, sikorico, svskaushik, teawaterwire, tnevler, w0Lfrum
55.6726 USDC - $55.67
HolographOperator.sol
825: function topupUtilityToken(address operator, uint256 amount) external { 826: /** 827: * @dev check that an operator is currently bonded 828: */ 829: require(_bondedOperators[operator] != 0, "HOLOGRAPH: operator not bonded"); 830: unchecked { 831: /** 832: * @dev add the additional amount to operator 833: */ 834: _bondedAmounts[operator] += amount; 835: } 836: /** 837: * @dev transfer tokens last, to prevent reentrancy attacks 838: */ 839: require(_utilityToken().transferFrom(msg.sender, address(this), amount), "HOLOGRAPH: token transfer failed"); 840: }
function unbondUtilityToken(address operator, address recipient) external { /** * @dev validate that operator is currently bonded */ require(_bondedOperators[operator] != 0, "HOLOGRAPH: operator not bonded"); /** * @dev check if sender is not actual operator */ if (msg.sender != operator) { /** * @dev check if operator is a smart contract */ require(_isContract(operator), "HOLOGRAPH: operator not contract"); /** * @dev check if smart contract is owned by sender */ require(Ownable(operator).isOwner(msg.sender), "HOLOGRAPH: sender not owner"); } /** * @dev get current bonded amount by operator */ uint256 amount = _bondedAmounts[operator]; /** * @dev unset operator bond amount before making a transfer */ _bondedAmounts[operator] = 0; /** * @dev remove all operator references */ _popOperator(_bondedOperators[operator] - 1, _operatorPodIndex[operator]); /** * @dev transfer tokens to recipient */ //@audit-issue low check nonzero amount require(_utilityToken().transfer(recipient, amount), "HOLOGRAPH: token transfer failed"); }
call()
instead of deprecated transfer()
This is reported as QA since the receiver is not a user, ie the receive/fallback function on the receiver end is known.
HolographOperator.sol
582: function send( 583: uint256 gasLimit, 584: uint256 gasPrice, 585: uint32 toChain, 586: address msgSender, 587: uint256 nonce, 588: address holographableContract, 589: bytes calldata bridgeOutPayload 590: ) external payable { 591: require(msg.sender == _bridge(), "HOLOGRAPH: bridge only call"); 592: CrossChainMessageInterface messagingModule = _messagingModule(); 593: uint256 hlgFee = messagingModule.getHlgFee(toChain, gasLimit, gasPrice); 594: address hToken = _registry().getHToken(_holograph().getHolographChainId()); 595: require(hlgFee < msg.value, "HOLOGRAPH: not enough value"); 596: payable(hToken).transfer(hlgFee); //@audit-issue QA use call() instead of transfer() 597: bytes memory encodedData = abi.encodeWithSelector(
It is a good practice to include 0 address check when setting important addresses. It would be good to have non-zero address check for the addresses set within the init()
functions.
HolographOperator.sol
412: /** 413: * @dev ensure that there is enough has left for the job //@audit-issue nc typo has->gas 414: */ 415: require(gasleft() > gasLimit, "HOLOGRAPH: not enough gas left");
HolographOperator.sol
275: * @dev temp function, used for quicker updates/resets during development 276: * NOT PART OF FINAL CODE !!! 277: */
701: // TODO: move the bit-shifting around to have it be sequential
🌟 Selected for report: oyc_109
Also found by: 0x040, 0x1f8b, 0x5rings, 0xNazgul, 0xSmartContract, 0xZaharina, 0xsam, 0xzh, 2997ms, Amithuddar, Aymen0909, B2, Bnke0x0, Deivitto, Diana, Dinesh11G, Franfran, JC, JrNet, Jujic, KingNFT, KoKo, Mathieu, Metatron, Mukund, Olivierdem, PaludoX0, Pheonix, Picodes, RaymondFam, RedOneN, ReyAdmirado, Rolezn, Saintcode_, Satyam_Sharma, Shinchan, Tagir2003, Tomio, Waze, Yiko, __141345__, adriro, ajtra, aysha, ballx, beardofginger, bobirichman, brgltd, bulej93, catchup, catwhiskeys, cdahlheimer, ch0bu, chaduke, chrisdior4, cryptostellar5, cylzxje, d3e4, delfin454000, dharma09, djxploit, durianSausage, emrekocak, erictee, exolorkistis, fatherOfBlocks, gianganhnguyen, gogo, halden, hxzy, i_got_hacked, iepathos, karanctf, leosathya, lucacez, lukris02, lyncurion, m_Rassska, martin, mcwildy, mics, nicobevi, peanuts, peiw, rbserver, ret2basic, rotcivegaf, ryshaw, sakman, sakshamguruji, saneryee, sikorico, skyle, svskaushik, tnevler, vv7, w0Lfrum, zishansami
0 USDC - $0.00
init()
function. They are also set in the resetOperator()
function, but that function is commented to be not part of the final code.Therefore they can be made constant and given their value at declaration.
158: uint256 private _blockTime; //@audit gas can be made constant. Only set in init() except resetOperator() which is not part of final code 168: uint256 private _podMultiplier; //@audit gas can be made constant. Only set in init() except resetOperator() which is not part of final code 173: uint256 private _operatorThreshold; //@audit gas can be made constant. Only set in init() except resetOperator() which is not part of final code 178: uint256 private _operatorThresholdStep; //@audit gas can be made constant. Only set in init() except resetOperator() which is not part of final code 183: uint256 private _operatorThresholdDivisor; //@audit gas can be made constant. Only set in init() except resetOperator() which is not part of final code