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: 42/144
Findings: 2
Award: $82.02
🌟 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
Use (e.g. 1e6) rather than decimal literals (e.g. 1000000), for better code readability.
Total:11
291: require(balance - gasCost > 10000, "PA1D: Not enough ETH to transfer");
296: sending = ((bps[i] * balance) / 10000);
312: require(balance > 10000, "PA1D: Not enough tokens to transfer");
316: sending = ((bps[i] * balance) / 10000);
336: require(balance > 10000, "PA1D: Not enough tokens to transfer");
339: sending = ((bps[i] * balance) / 10000);
378: require(totalBp == 10000, "PA1D: bps down't equal 10000");
452: return (_getDefaultReceiver(), (_getDefaultBp() * value) / 10000);
454: return (_getReceiver(tokenId), (_getBp(tokenId) * value) / 10000);
542: return (_getDefaultBp() * amount) / 10000;
544: return (_getBp(tokenId) * amount) / 10000;
It is bad practice to use numbers directly in code without explanation.
Total:58
223: revert(add(payload, 0x20), mload(payload))
452: jobNonce := add(sload(_jobNonceSlot), 0x0000000000000000000000000000000000000000000000000000000000000001)
127: uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), hash, keccak256(holographerBytecode)))))
140: sourceContractAddress := create2(0, add(sourceByteCode, 0x20), mload(sourceByteCode), saltInt)
146: holographerAddress := create2(0, add(holographerBytecode, 0x20), mload(holographerBytecode), saltInt)
215: return (codehash != 0x0 && codehash != precomputekeccak256(""));
228: if (v < 27) {
229: v += 27;
217: gasLimit := calldataload(sub(add(bridgeInRequestPayload.offset, bridgeInRequestPayload.length), 0x40))
221: gasPrice := calldataload(sub(add(bridgeInRequestPayload.offset, bridgeInRequestPayload.length), 0x20))
259: if (timeDifference < 6) {
352: calldatacopy(0, payload.offset, sub(payload.length, 0x20))
356: mstore(0x84, msgSender)
362: mload(sub(payload.length, 0x40)),
370: sub(payload.length, 0x40),
424: ((pod + 1) << 248) |
425: (uint256(_operatorTempStorageCounter) << 216) |
428: (_randomBlockHash(random, podSize, 2) << 144) |
429: (_randomBlockHash(random, podSize, 3) << 128) |
430: (_randomBlockHash(random, podSize, 4) << 112) |
431: (_randomBlockHash(random, podSize, 5) << 96) |
452: calldatacopy(0, bridgeInRequestPayload.offset, sub(bridgeInRequestPayload.length, 0x40))
456: mstore8(0xE3, 0x00)
457: let result := call(gas(), sload(_bridgeSlot), callvalue(), 0, sub(bridgeInRequestPayload.length, 0x40), 0, 0)
468: mstore(0x00, gas())
469: return(0x00, 0x20)
598: uint8(packed >> 248),
600: _operatorTempStorage[uint32(packed >> 216)],
609: uint16(packed >> 96)
1015: jobNonce := add(sload(_jobNonceSlot), 0x0000000000000000000000000000000000000000000000000000000000000001)
1104: return (codehash != 0x0 && codehash != precomputekeccak256(""));
62: sender := calldataload(sub(calldatasize(), 0x20))
122: mstore(0x80, 0x0000000000000000000000000000000000000000000000000000000000000001)
123: return(0x80, 0x20)
126: revert(0x00, 0x00)
62: sender := calldataload(sub(calldatasize(), 0x20))
122: mstore(0x80, 0x0000000000000000000000000000000000000000000000000000000000000001)
123: return(0x80, 0x20)
126: revert(0x00, 0x00)
123: sstore(_reentrantSlot, 0x0000000000000000000000000000000000000000000000000000000000000001)
162: let result := call(gas(), sload(_sourceContractSlot), callvalue(), 0, add(calldatasize(), 32), 0, 0)
548: if (ERC165(recipient).supportsInterface(0x534f5876)) {
622: return (codehash != 0x0 && codehash != precomputekeccak256(""));
817: return (codehash != 0x0 && codehash != precomputekeccak256(""));
856: 0x0000000000000000000000000000000000000000000000000000000050413144
890: let result := call(gas(), sload(_sourceContractSlot), callvalue(), 0, add(calldatasize(), 32), 0, 0)
96: mstore(0x80, 0x08c379a000000000000000000000000000000000000000000000000000000000)
97: mstore(0xa0, 0x0000002000000000000000000000000000000000000000000000000000000000)
98: mstore(0xc0, 0x0000001b484f4c4f47524150483a204c5a206f6e6c7920656e64706f696e7400)
99: mstore(0xe0, 0x0000000000000000000000000000000000000000000000000000000000000000)
100: revert(0x80, 0xc4)
102: let ptr := mload(0x40)
103: calldatacopy(add(ptr, 0x0c), _srcAddress.offset, _srcAddress.length)
112: mstore(0x80, 0x08c379a000000000000000000000000000000000000000000000000000000000)
113: mstore(0xa0, 0x0000002000000000000000000000000000000000000000000000000000000000)
114: mstore(0xc0, 0x0000001e484f4c4f47524150483a20756e617574686f72697a65642073656e64)
115: mstore(0xe0, 0x6572000000000000000000000000000000000000000000000000000000000000)
116: revert(0x80, 0xc4)
It is not necessary to have both a named return and a return statement.
Total:5
82: ) external pure returns (bytes4 selector, bytes memory data) {
618: function getTotalPods() external view returns (uint256 totalPods) {
705: function getBondedAmount(address operator) external view returns (uint256 amount) {
715: function getBondedPod(address operator) external view returns (uint256 pod) {
550: try ERC20Receiver(recipient).onERC20Received(address(this), account, amount, data) returns (bytes4 retval) {
reveive()/fallback()
functionThe following contracts define a payable receive function but have no way of withdrawing or utilizing the sent Ether, resulting in Ether being locked in the contracts. If the intention is to use the Ether that functionality should be added to the function, otherwise it should revert.
Total:18
485: fallback() external payable {
248: fallback() external payable {
260: uint256 podIndex = uint256(job.fallbackOperators[timeDifference - 1]);
265: address fallbackOperator = _operatorPods[pod][podIndex];
269: require(fallbackOperator == msg.sender, "HOLOGRAPH: invalid fallback");
1110: receive() external payable {}
1115: fallback() external payable {
113: receive() external payable {}
118: fallback() external payable {
113: receive() external payable {}
118: fallback() external payable {
152: receive() external payable {}
158: fallback() external payable {
863: receive() external payable {}
869: fallback() external payable {
124: receive() external payable {}
129: fallback() external payable {
324: fallback() external payable {
decimals()
not part of ERC20 standardCode architecture, incentives, and error handling/reporting questions/issues should be resolved before deployment.
Total:2
174: function decimals() public view returns (uint8) {
553: function decimals() external pure returns (uint256) {
approve
should be replaced with safeIncreaseAllowance()
or safeDecreaseAllowance()
approve
is subject to a known front-running attack. Consider using safeIncreaseAllownce()
or safeDecreaseAllowance()
instead
Total:7
227: function approve(address spender, uint256 amount) public returns (bool) {
231: _approve(msg.sender, spender, amount);
274: _approve(msg.sender, spender, newAllowance);
333: _approve(msg.sender, spender, newAllowance);
387: _approve(account, spender, amount);
516: function _approve(
269: function approve(address to, uint256 tokenId) external payable {
When changing state variables events are not emitted. Emitting events allows monitoring activities with off-chain monitoring tools.
Total:20
353: function setFactory(address factory) external onlyAdmin {
373: function setHolograph(address holograph) external onlyAdmin {
403: function setOperator(address operator) external onlyAdmin {
423: function setRegistry(address registry) external onlyAdmin {
181: function setHolograph(address holograph) external onlyAdmin {
201: function setRegistry(address registry) external onlyAdmin {
850: function setBridge(address bridge) external onlyAdmin {
870: function setHolograph(address holograph) external onlyAdmin {
890: function setInterfaces(address interfaces) external onlyAdmin {
910: function setMessagingModule(address messagingModule) external onlyAdmin {
930: function setRegistry(address registry) external onlyAdmin {
950: function setUtilityToken(address utilityToken) external onlyAdmin {
384: function setApprovalForAll(address to, bool approved) external {
430: function setRoyalties(
221: function setBridge(address bridge) external onlyAdmin {
241: function setInterfaces(address interfaces) external onlyAdmin {
261: function setLZEndpoint(address lZEndpoint) external onlyAdmin {
281: function setOperator(address operator) external onlyAdmin {
342: function setBaseGas(uint256 baseGas) external onlyAdmin {
371: function setGasPerByte(uint256 gasPerByte) external onlyAdmin { `
🌟 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
26.3525 USDC - $26.35
If a function modifier such as onlyOwner is used, the function will revert if a normal user tries to pay the function. Marking the function as payable will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided.
Total:33
353: function setFactory(address factory) external onlyAdmin {
373: function setHolograph(address holograph) external onlyAdmin {
403: function setOperator(address operator) external onlyAdmin {
423: function setRegistry(address registry) external onlyAdmin {
181: function setHolograph(address holograph) external onlyAdmin {
201: function setRegistry(address registry) external onlyAdmin {
186: ) external onlyAdmin {
850: function setBridge(address bridge) external onlyAdmin {
870: function setHolograph(address holograph) external onlyAdmin {
890: function setInterfaces(address interfaces) external onlyAdmin {
910: function setMessagingModule(address messagingModule) external onlyAdmin {
930: function setRegistry(address registry) external onlyAdmin {
950: function setUtilityToken(address utilityToken) external onlyAdmin {
281: function bridgeIn(uint32 fromChain, bytes calldata payload) external onlyBridge returns (bytes4) {
297: ) external onlyBridge returns (bytes4 selector, bytes memory data) {
316: function holographBridgeMint(address to, uint256 amount) external onlyBridge returns (bytes4) {
450: function sourceBurn(address from, uint256 amount) external onlySource {
457: function sourceMint(address to, uint256 amount) external onlySource {
464: function sourceMintBatch(address[] calldata wallets, uint256[] calldata amounts) external onlySource {
477: ) external onlySource {
300: function bridgeIn(uint32 fromChain, bytes calldata payload) external onlyBridge returns (bytes4) {
318: ) external onlyBridge returns (bytes4 selector, bytes memory data) {
401: function sourceBurn(uint256 tokenId) external onlySource {
409: function sourceMint(address to, uint224 tokenId) external onlySource {
478: function sourceTransfer(address to, uint256 tokenId) external onlySource {
372: function configurePayouts(address payable[] memory addresses, uint256[] memory bps) public onlyOwner {
434: ) public onlyOwner {
221: function setBridge(address bridge) external onlyAdmin {
241: function setInterfaces(address interfaces) external onlyAdmin {
261: function setLZEndpoint(address lZEndpoint) external onlyAdmin {
281: function setOperator(address operator) external onlyAdmin {
342: function setBaseGas(uint256 baseGas) external onlyAdmin {
371: function setGasPerByte(uint256 gasPerByte) external onlyAdmin {
The code should be refactored such that they no longer exist, or the block should do something useful, such as emitting an event or reverting.
Total:16
56: constructor() {}
37: constructor() {}
134: constructor() {}
1110: receive() external payable {}
34: constructor() {}
113: receive() external payable {}
34: constructor() {}
113: receive() external payable {}
112: constructor() {}
152: receive() external payable {}
132: constructor() {}
863: receive() external payable {}
41: constructor() {}
124: receive() external payable {}
67: constructor() {}
52: constructor() {}
It is not necessary to have both a named return and a return statement.
Total:5
82: ) external pure returns (bytes4 selector, bytes memory data) {
618: function getTotalPods() external view returns (uint256 totalPods) {
705: function getBondedAmount(address operator) external view returns (uint256 amount) {
715: function getBondedPod(address operator) external view returns (uint256 pod) {
550: try ERC20Receiver(recipient).onERC20Received(address(this), account, amount, data) returns (bytes4 retval) {
Saves 6 gas per instance if using assemlby to check for address(0)
Total:14
234: if (job.operator != address(0)) {
521: require(account != address(0), "ERC20: account is zero address");
522: require(spender != address(0), "ERC20: spender is zero address");
528: require(account != address(0), "ERC20: account is zero address");
585: require(to != address(0), "ERC20: minting to burn address");
596: require(account != address(0), "ERC20: account is zero address");
597: require(recipient != address(0), "ERC20: recipient is zero address");
320: require(to != address(0), "ERC721: zero address");
540: require(wallet != address(0), "ERC721: zero address");
558: return _tokenOwner[tokenId] != address(0);
590: require(tokenOwner != address(0), "ERC721: token does not exist");
717: require(to != address(0), "ERC721: minting to burn address");
771: require(to != address(0), "ERC721: use burn instead");
796: return tokenOwner != address(0);
When fetching data from a storage location, assigning the data to a memory variable causes all fields of the struct/array to be read from storage, which incurs a Goldsload (2100 gas) for each field of the struct/array. If the fields are read from the new memory variable, they incur an additional MLOAD rather than a cheap stack read.
Total:15
284: address payable[] memory addresses = _getPayoutAddresses();
285: uint256[] memory bps = _getPayoutBps();
307: address payable[] memory addresses = _getPayoutAddresses();
308: uint256[] memory bps = _getPayoutBps();
328: address payable[] memory addresses = _getPayoutAddresses();
329: uint256[] memory bps = _getPayoutBps();
353: address payable[] memory addresses = _getPayoutAddresses();
442: address[] memory receivers = new address[](1);
444: uint256[] memory bps = new uint256[](1);
460: uint256[] memory bps = new uint256[](1);
471: address payable[] memory receivers = new address payable[](1);
492: address payable[] memory receivers = new address payable[](1);
493: uint256[] memory bps = new uint256[](1);
506: address payable[] memory receivers = new address payable[](1);
507: uint256[] memory bps = new uint256[](1);
If the functions are required by an interface, the contract should inherit from that interface and use the override keyword.
Total:2
104: function _setOwner(address ownerAddress) internal {
104: function _setOwner(address ownerAddress) internal { `