Geegs Smart Contract Audit

Last audited: 15th Oct 2023

Note: This report excludes informational issues.

Summary

  • arbitrary-send-eth (1 results) (High)

  • uninitialized-state (1 results) (High)

  • divide-before-multiply (8 results) (Medium)

  • uninitialized-local (1 results) (Medium)

  • unused-return (1 results) (Medium)

  • events-maths (3 results) (Low)

  • missing-zero-check (1 results) (Low)

  • reentrancy-benign (2 results) (Low)

  • reentrancy-events (4 results) (Low)

  • timestamp (1 results) (Low)

arbitrary-send-eth

Impact: High, Confidence: Medium

  • ID-0 Geegs._resolve(Geegs.Resolver,address[2],uint256) sends eth to arbitrary user Dangerous calls:

    • (success_scope_2,data_scope_3) = address(msg.sender).call{value: fees}()

    geegs-contract/contracts/Geegs.sol#L471-L508

uninitialized-state

Impact: High, Confidence: High

  • ID-1 Geegs.transferAllowance is never initialized. It is used in:

    geegs-contract/contracts/Geegs.sol#L109

divide-before-multiply

Impact: Medium, Confidence: Medium

  • ID-2 MathUpgradeable.mulDiv(uint256,uint256,uint256) performs a multiplication on the result of a division:

    • denominator = denominator / twos

    • inverse *= 2 - denominator * inverse

    geegs-contract/node_modules/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#L55-L135

  • ID-3 MathUpgradeable.mulDiv(uint256,uint256,uint256) performs a multiplication on the result of a division:

    • denominator = denominator / twos

    • inverse *= 2 - denominator * inverse

    geegs-contract/node_modules/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#L55-L135

  • ID-4 MathUpgradeable.mulDiv(uint256,uint256,uint256) performs a multiplication on the result of a division:

    • denominator = denominator / twos

    • inverse = (3 * denominator) ^ 2

    geegs-contract/node_modules/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#L55-L135

  • ID-5 MathUpgradeable.mulDiv(uint256,uint256,uint256) performs a multiplication on the result of a division:

    • prod0 = prod0 / twos

    • result = prod0 * inverse

    geegs-contract/node_modules/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#L55-L135

  • ID-6 MathUpgradeable.mulDiv(uint256,uint256,uint256) performs a multiplication on the result of a division:

    • denominator = denominator / twos

    • inverse *= 2 - denominator * inverse

    geegs-contract/node_modules/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#L55-L135

  • ID-7 MathUpgradeable.mulDiv(uint256,uint256,uint256) performs a multiplication on the result of a division:

    • denominator = denominator / twos

    • inverse *= 2 - denominator * inverse

    geegs-contract/node_modules/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#L55-L135

  • ID-8 MathUpgradeable.mulDiv(uint256,uint256,uint256) performs a multiplication on the result of a division:

    • denominator = denominator / twos

    • inverse *= 2 - denominator * inverse

    geegs-contract/node_modules/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#L55-L135

  • ID-9 MathUpgradeable.mulDiv(uint256,uint256,uint256) performs a multiplication on the result of a division:

    • denominator = denominator / twos

    • inverse *= 2 - denominator * inverse

    geegs-contract/node_modules/@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol#L55-L135

uninitialized-local

Impact: Medium, Confidence: Medium

  • ID-10 Geegs.resolveProlongedDispute(Geegs.Resolver).signature is a local variable never initialized

    geegs-contract/contracts/Geegs.sol#L426

unused-return

Impact: Medium, Confidence: Medium

  • ID-11 Geegs.burn(uint256) ignores return value by (fees) = feeStructure.calculateFee(doc.wage,doc.platformFee)

    geegs-contract/contracts/Geegs.sol#L326-L342

events-maths

Impact: Low, Confidence: Medium

  • ID-12 FeeStructure.setDisputeFee(uint256) should emit an event for:

    • disputeFee = feePercent

    geegs-contract/contracts/FeeStructure.sol#L40-L42

  • ID-13 Geegs.setGracePeriod(uint256) should emit an event for:

    • gracePeriod = daysNo * 86400

    geegs-contract/contracts/Geegs.sol#L196-L198

  • ID-14 FeeStructure.setPlatformFee(uint256) should emit an event for:

    • platformFee = feePercent

    geegs-contract/contracts/FeeStructure.sol#L34-L36

missing-zero-check

Impact: Low, Confidence: Medium

  • ID-15 Geegs.setFeeWallet(address).wallet lacks a zero-check on :

    • feeWallet = wallet

    geegs-contract/contracts/Geegs.sol#L188

reentrancy-benign

Impact: Low, Confidence: Medium

  • ID-16 Reentrancy in Geegs.createDocument(Geegs.Document,uint256): External calls:

    • (success,data) = address(feeWallet).call{value: fees}()

    State variables written after the call(s):

    • _mint(msg.sender,_next)

    • _balances[from] -= batchSize

    • _balances[to] += 1

    • _balances[to] += batchSize

    • _mint(msg.sender,_next)

    • _owners[tokenId] = to

    • approve(doc.talent,_next)

    • _tokenApprovals[tokenId] = to

    • documents[_next] = doc

    • documents[_next].platformFee = feeBasis

    • nextTokenId ++

    geegs-contract/contracts/Geegs.sol#L242-L270

  • ID-17 Reentrancy in Geegs.mintPastExperience(bytes32,bytes32,bytes32[],bool,uint256,Geegs.MINT): External calls:

    • (success,data) = address(feeWallet).call{value: msg.value}()

    State variables written after the call(s):

    • _mint(msg.sender,nextTokenId)

    • _balances[from] -= batchSize

    • _balances[to] += 1

    • _balances[to] += batchSize

    • _mint(msg.sender,nextTokenId)

    • _owners[tokenId] = to

    • exps[nextTokenId] = ExperienceBadge(jobTitle_,hirer_,false)

    • nextTokenId ++

    geegs-contract/contracts/Geegs.sol#L272-L315

reentrancy-events

Impact: Low, Confidence: Medium

  • ID-18 Reentrancy in Geegs._resolve(Geegs.Resolver,address[2],uint256): External calls:

    • (success,data) = address(parties[0]).call{value: resolver.payableA}()

    • (success_scope_0,data_scope_1) = address(parties[1]).call{value: resolver.payableB}()

    • (success_scope_2,data_scope_3) = address(msg.sender).call{value: fees}()

    Event emitted after the call(s):

    • Resolved(resolver.id,resolver.payableA,resolver.payableB)

    geegs-contract/contracts/Geegs.sol#L471-L508

  • ID-19 Reentrancy in Geegs.createDocument(Geegs.Document,uint256): External calls:

    • (success,data) = address(feeWallet).call{value: fees}()

    Event emitted after the call(s):

    • Approval(ERC721Upgradeable.ownerOf(tokenId),to,tokenId)

    • approve(doc.talent,_next)

    • TecCreated(_next,offChainId,doc.wage)

    • Transfer(address(0),to,tokenId)

    • _mint(msg.sender,_next)

    geegs-contract/contracts/Geegs.sol#L242-L270

  • ID-20 Reentrancy in Geegs.markComplete(uint256,Geegs.STATUS): External calls:

    • address(doc.talent).sendValue(payout)

    Event emitted after the call(s):

    • Completed(id,doc.wage)

    geegs-contract/contracts/Geegs.sol#L377-L392

  • ID-21 Reentrancy in Geegs.mintPastExperience(bytes32,bytes32,bytes32[],bool,uint256,Geegs.MINT): External calls:

    • (success,data) = address(feeWallet).call{value: msg.value}()

    Event emitted after the call(s):

    • PastMint(nextTokenId,offChainId)

    • Transfer(address(0),to,tokenId)

    • _mint(msg.sender,nextTokenId)

    geegs-contract/contracts/Geegs.sol#L272-L315

timestamp

Impact: Low, Confidence: Medium

  • ID-22 Geegs.resolveProlongedDispute(Geegs.Resolver) uses timestamp for comparisons Dangerous comparisons:

    • doc.disputedAt + gracePeriod > block.timestamp

    geegs-contract/contracts/Geegs.sol#L420-L444

Last updated