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: 56/144
Findings: 3
Award: $55.69
π Selected for report: 0
π Solo Findings: 0
0.0184 USDC - $0.02
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/enforcer/PA1D.sol#L432-L439
Some tokens will revert on transfers of zero amount. If one of these tokens has the amount zero and it's used during payouts for PA1D._payoutTokens()
, the entire transaction will fail.
Lack of checks for amount zero during ERC20 token transfers in PA1D.sol
. Note that the balance is checked to be bigger than 10000, but it's possible for bsp[i]
to be zero, which would result in the variable sending
to be zero.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/enforcer/PA1D.sol#L432-L439
Only execute the token transfer if bps[i]
is not zero. E.g.
diff --git a/PA1D.sol.orig b/PA1D.sol --- a/PA1D.sol.orig +++ b/PA1D.sol @@ -435,8 +435,10 @@ contract PA1D is Admin, Owner, Initializable { for (uint256 i = 0; i < addresses.length; i++) { - sending = ((bps[i] * balance) / 10000); - require(erc20.transfer(addresses[i], sending), "PA1D: Couldn't transfer token"); + if (bps[i] != 0) { + sending = ((bps[i] * balance) / 10000); + require(erc20.transfer(addresses[i], sending), "PA1D: Couldn't transfer token"); + }
#0 - gzeoneth
2022-10-30T14:59:21Z
Duplicate of #454
#1 - ACC01ADE
2022-11-09T14:51:55Z
Low severity, but will add a check for zero
0.0184 USDC - $0.02
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/enforcer/PA1D.sol#L439
Some ERC20 tokens (USDT, BNB, OMG) do not return a boolean on succesful transfer. Checking the returned value of transfer for these tokens will always fail.
Usage of ERC20 interface and require statement in PA1D.sol
.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/enforcer/PA1D.sol#L439
Implement a custom function to transfer tokens by checking if the contract exist and making a a low level call using the ERC20 interface selector. E.g.
function _safeTransfer(address token, address to, uint256 value) private { require(token.code.length > 0); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(ERC20.transfer.selector, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool)))); }
Alternatively, use OpenZeppelin SafeERC20.
#0 - gzeoneth
2022-10-30T16:54:22Z
Duplicate of #456
π 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
HolographERC20.permit()
is using ECDSA.recover. However, HolographFactory._verifySigner()
is using ecrecover. Consider using only ECDSA.recover
on all instances for signature verification. The function ecrecover is vulnarable to replay attacks and signature malleability.
Usage of ecrecover in HolographFactory
.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographFactory.sol#L333-L334
Replace ecrecover with ECDSA.recover
. Note that the return of both ECDSA.recover
and ecrecover need checks for returned address different than zero. In HolographFactory.verifySigner
if the hash signature returns address zero, and the signer
suppplied at HolographFactory.deployHolographableContract
is also zero, the validation will pass causing slient failures.
The following change is recommended:
diff --git a/HolographFactory.sol.orig b/HolographFactory.sol --- a/HolographFactory.sol.orig +++ b/HolographFactory.sol - return (ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)), v, r, s) == signer || - ecrecover(hash, v, r, s) == signer); + return signer != address(0) && ( + ECDSA.recover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)), v, r, s) == signer || + ECDSA.recover(hash, v, r, s) == signer + );
_mint
to validate if the recipient is able to receive ERC721HolographERC721_mint()
and HolographERC721.bridgeIn()
will not check if the to
address is capable of receiving the ERC721. This could lead to loss of funds/assets.
HolographERC721.bridgeIn()
and HolographERC721_mint()
won't check the receiver address.
Implement checks on the recipient address to validate if it's capable of receiving NFTs. This link contains OpenZeppelin implementation.
block.number
and block.timestamp
are not strong sources of entropyRandomness is not a trivial task on the blockchain. Using block.number
and block.timestamp
is not recommended.
Usage of block.number
and block.timestamp
for entropy in HolographOperator.crossChainMessage()
.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L484-L539
Evaluate the usage of a system such as chainlink to provide stronger randomness guarantees and prevent randomness bugs for the Holograph operator cross chain messaging.
The project makes heavy usage of assembly and v0.8.13 of solidity has a issue related to the yul optimizer mistakenly removing memory writes.
Multiple assembly blocks with memory writes.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L445-L455
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L550-L555
Detail description of the bug.
Update the project to use solidity >0.8.15, which solves the assembly issue.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L949
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L240-L245
If a variable gets configured with address zero, failure to immediately reset the value can result in unexpected behavior for the project.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L949
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L969
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L1009
Lack of two-step procedure for critical operations leaves them error-prone. Consider adding two step procedure on the critical functions.
Consider adding a two-steps pattern on critical changes to avoid mistakenly transferring ownership of roles or critial functionalities to the wrong address.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L949
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L969
Adding events will faciliate offchain monitoring.
Some commends are using /**/, while other are using ///. E.g.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L492-L498
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L459-L468
Consider using the same approach to write comments throughout the codebase.
10**18 = 10e18
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L256
rever = revert
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L553
msg.value is computed three times in HologaphOperator.send()
. Consider caching this value in the beginning of the function.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L595
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L640
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L645
The solidity documentation recommends the following order for functions:
constructor receive function (if exists) fallback function (if exists) external public internal private
The following instances shows internal above external.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/abstract/ERC721H.sol#L159
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/abstract/ERC721H.sol#L174
Consider adding NATSPEC on all functions to improve documentation.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/enforcer/HolographERC20.sol#L580
Consider removing or resolving commended code sections.
Todo's should be resolved before mainnet deployment.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L701
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/enforcer/HolographERC20.sol#L347
π 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
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L781
It can save 30-40 gas per loop.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L378
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L382
Using the addition operator instead of plus-equals saves 113 gas.
Caching of a state variable replace each Gwarmaccess (100 gas) with a cheaper stack read.
For example, on the following instances, _bondedOperators[operator]
should be cached.
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L903
https://github.com/code-423n4/2022-10-holograph/blob/main/contracts/HolographOperator.sol#L928
#0 - alexanderattar
2022-11-08T22:32:13Z
Nice finds π