Skip to content

Instantly share code, notes, and snippets.

@CloudEllie
Created July 6, 2023 16:26
Show Gist options
  • Save CloudEllie/eafeb9865761200397c00d70febe5f9d to your computer and use it in GitHub Desktop.
Save CloudEllie/eafeb9865761200397c00d70febe5f9d to your computer and use it in GitHub Desktop.
Tapioca Code4rena audit: winning bot race report by IllIllI

Note: There is a section for disputed findings below the gas report section

Summary

Medium Risk Issues

Issue Instances
[M‑01] The owner is a single point of failure and a centralization risk 85
[M‑02] Excess funds sent via msg.value not refunded 1
[M‑03] Contracts are vulnerable to fee-on-transfer accounting-related issues 4
[M‑04] Unsafe use of transfer()/transferFrom() with IERC20 4
[M‑05] Use of transferFrom() rather than safeTransferFrom() for NFTs in will lead to the loss of NFTs 1
[M‑06] Return values of transfer()/transferFrom() not checked 6
[M‑07] _safeMint() should be used rather than _mint() wherever possible 3

Total: 104 instances over 7 issues

Low Risk Issues

Issue Instances
[L‑01] Some tokens may revert when zero value transfers are made 19
[L‑02] calc_token_amount() has slippage added on top of Curve's calculated slippage 1
[L‑03] approve()/safeApprove() may revert if the current approval is not zero 20
[L‑04] Missing contract-existence checks before low-level calls 29
[L‑05] External call recipient may consume all transaction gas 12
[L‑06] Multiplication on the result of a division 8
[L‑07] Division by zero not prevented 13
[L‑08] External calls in an un-bounded for-loop may result in a DOS 61
[L‑09] State variables not capped at reasonable values 3
[L‑10] Missing checks for address(0x0) when assigning values to address state variables 46
[L‑11] Allowed fees/rates should be capped by smart contracts 2
[L‑12] Solidity version 0.8.20 may not work on other chains due to PUSH0 67
[L‑13] Consider implementing two-step procedure for updating protocol addresses 7
[L‑14] Unsafe downcast 64
[L‑15] Loss of precision 121
[L‑16] Array lengths not checked 9
[L‑17] Empty receive()/payable fallback() function does not authorize requests 10
[L‑18] Draft imports may break in new minor versions 7
[L‑19] Functions calling contracts/addresses with transfer hooks are missing reentrancy guards 8
[L‑20] Use Ownable2Step rather than Ownable 4
[L‑21] addRewardToken() does note remove old entries before adding new ones 2
[L‑22] Signature use at deadlines should be allowed 3
[L‑23] NFT doesn't handle hard forks 2
[L‑24] decimals() is not a part of the ERC-20 standard 4
[L‑25] tokenURI() does not follow EIP-721 2
[L‑26] Open TODOs 10
[L‑27] Calls to _get() will revert when totalSupply() returns zero 1
[L‑28] latestAnswer() is deprecated 5
[L‑29] safeApprove() is deprecated 1
[L‑30] Use of a single-step ownership transfer 1

Total: 542 instances over 30 issues

Non-critical Issues

Issue Instances
[N‑01] Events are missing sender information 21
[N‑02] Variables need not be initialized to zero 129
[N‑03] Consider using named mappings 57
[N‑04] Contract uses both require()/revert() as well as custom errors 4
[N‑05] Consider adding a block/deny-list 55
[N‑06] Non-external/public variable and function names should begin with an underscore 89
[N‑07] Large numeric literals should use underscores for readability 15
[N‑08] Unused contract variables 4
[N‑09] Use abi.encodeCall() instead of abi.encodeSignature()/abi.encodeSelector() 58
[N‑10] Constants in comparisons should appear on the left side 92
[N‑11] Consider disabling renounceOwnership() 24
[N‑12] Consider adding emergency-stop functionality 18
[N‑13] Events may be emitted out of order due to reentrancy 23
[N‑14] Function names should use lowerCamelCase 17
[N‑15] Consider bounding input array length 29
[N‑16] Consider moving msg.sender checks to a common authorization modifier 10
[N‑17] Imports could be organized more systematically 27
[N‑18] Overridden function has no body 4
[N‑19] Use OpenZeppelin's or Solady's Ownable, rather than re-inventing the wheel 20
[N‑20] Array is push()ed but not pop()ed 5
[N‑21] Long functions should be refactored into multiple, smaller, functions 7
[N‑22] Mixed usage of int/uint with int256/uint256 7
[N‑23] Unsafe conversion from unsigned to signed values 10
[N‑24] public functions not called by the contract should be declared external instead 74
[N‑25] constants should be defined rather than using magic numbers 194
[N‑26] Event is not properly indexed 22
[N‑27] Duplicated require()/revert() checks should be refactored to a modifier or function 33
[N‑28] Vulnerable versions of packages are being used 6
[N‑29] Import declarations should import specific identifiers, rather than the whole file 345
[N‑30] Return values of approve() not checked 45
[N‑31] Contract implements interface without extending the interface 9
[N‑32] override function arguments that are unused should have the variable name removed or commented out to avoid compiler warnings 5
[N‑33] Cast is more restrictive than the type of the variable being assigned 8
[N‑34] Events that mark critical parameter changes should contain both the old and the new value 59
[N‑35] Constant redefined elsewhere 23
[N‑36] Use @inheritdoc rather than using a non-standard annotation 5
[N‑37] Inconsistent spacing in comments 315
[N‑38] Lines are too long 361
[N‑39] Variable names that consist of all capital letters should be reserved for constant/immutable variables 6
[N‑40] Non-library/interface files should use fixed compiler versions, not floating ones 59
[N‑41] Typos 31
[N‑42] NatSpec @param is missing 329
[N‑43] NatSpec @return argument is missing 168
[N‑44] Avoid the use of sensitive terms 60
[N‑45] Function ordering does not follow the Solidity style guide 81
[N‑46] Contract does not follow the Solidity style guide's suggested layout ordering 15
[N‑47] Control structures do not follow the Solidity Style Guide 5
[N‑48] Expressions for constant values such as a call to keccak256(), should use immutable rather than constant 5
[N‑49] Numeric values having to do with time should use time units for readability 14
[N‑50] Consider using delete rather than assigning zero/false to clear values 19
[N‑51] Contracts should have full test coverage 6
[N‑52] Large or complicated code bases should implement invariant tests 6
[N‑53] Enable IR-based code generation 6
[N‑54] private functions not called by the contract should be removed 1
[N‑55] internal functions not called by the contract should be removed 1
[N‑56] Unused error definition 1
[N‑57] Contract names should use CamelCase 1
[N‑58] Cast to bytes or bytes32 for clearer semantic meaning 2
[N‑59] Custom error has no error details 23
[N‑60] Variable names don't follow the Solidity style guide 4
[N‑61] Contracts containing only utility functions should be made into libraries 2
[N‑62] Unused struct definition 8
[N‑63] if-statement can be converted to a ternary 6
[N‑64] Adding a return statement when the function defines a named return variable, is redundant 3
[N‑65] 2**<n> - 1 should be re-written as type(uint<n>).max 1
[N‑66] require()/revert() statements should have descriptive reason strings 2
[N‑67] Non-assembly method available 2
[N‑68] Missing event and or timelock for critical parameter change 5
[N‑69] Constructor visibility is ignored 1
[N‑70] Visibility should be set explicitly rather than defaulting to internal 10
[N‑71] Memory-safe annotation preferred over comment variant 2
[N‑72] Interfaces should be defined in separate files from their usage 2
[N‑73] Duplicate import statements 1
[N‑74] Using >/>= without specifying an upper bound is unsafe 1
[N‑75] File is missing NatSpec 4
[N‑76] addresss shouldn't be hard-coded 1
[N‑77] pragma experimental ABIEncoderV2 is deprecated 3
[N‑78] Use scientific notation (e.g. 1e18) rather than exponentiation (e.g. 10**18) 2
[N‑79] else-block not required 3
[N‑80] Use a more recent version of solidity 1
[N‑81] Use a more recent version of solidity 3
[N‑82] Strings should use double quotes rather than single quotes 7

Total: 3142 instances over 82 issues

Gas Optimizations

Issue Instances Total Gas Saved
[G‑01] Reduce gas usage by moving to Solidity 0.8.19 or later 68 -
[G‑02] Using bools for storage incurs overhead 17 290700
[G‑03] Avoid updating storage when the value hasn't changed 26 20800
[G‑04] unchecked {} can be used on the division of two uints in order to save gas 76 1520
[G‑05] Remove or replace unused state variables 3 -
[G‑06] Multiple address/ID mappings can be combined into a single mapping of an address/ID to a struct, where appropriate 10 420
[G‑07] State variables only set in the constructor should be declared immutable 27 56619
[G‑08] State variables can be packed into fewer storage slots 6 12000
[G‑09] Using storage instead of memory for structs/arrays saves gas 18 75600
[G‑10] State variables should be cached in stack variables rather than re-reading them from storage 156 15132
[G‑11] <x> += <y> costs more gas than <x> = <x> + <y> for state variables 5 565
[G‑12] Add unchecked {} for subtractions where the operands cannot underflow because of a previous require() or if-statement 21 1785
[G‑13] <array>.length should not be looked up in every loop of a for-loop 24 72
[G‑14] ++i/i++ should be unchecked{++i}/unchecked{i++} when it is not possible for them to overflow, as is the case when used in for- and while-loops 27 1620
[G‑15] private functions not called by the contract should be removed to save deployment gas 1 -
[G‑16] Optimize names to save gas 54 1188
[G‑17] >= costs less gas than > 2 6
[G‑18] internal functions not called by the contract should be removed to save deployment gas 1 -
[G‑19] ++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too) 41 205
[G‑20] Splitting require() statements that use && saves gas 7 21
[G‑21] Using private rather than public for constants, saves gas 17 -
[G‑22] Don't compare boolean expressions to boolean literals 6 54
[G‑23] Multiple if-statements with mutually-exclusive conditions should be changed to if-else statements 2 -
[G‑24] require() or revert() statements that check input arguments should be at the top of the function 3 -
[G‑25] Empty blocks should be removed or emit something 23 -
[G‑26] Superfluous event fields 1 34
[G‑27] Use custom errors rather than revert()/require() strings to save gas 244 -
[G‑28] Functions guaranteed to revert when called by normal users can be marked payable 87 1827
[G‑29] Constructors can be marked payable 50 1050
[G‑30] Structs can be packed into fewer storage slots 5 10000
[G‑31] Inverting the condition of an if-else-statement wastes gas 1 -
[G‑32] Division by two should use bit shifting 3 60
[G‑33] Structs can be packed into fewer storage slots by truncating timestamp bytes 1 2000
[G‑34] Multiple accesses of a mapping/array should use a local variable cache 10 420
[G‑35] internal functions only called once can be inlined to save gas 26 520
[G‑36] require()/revert() strings longer than 32 bytes cost extra gas 23 69
[G‑37] keccak256() should only need to be called on a specific string literal once 3 126
[G‑38] Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead 5 110
[G‑39] Stack variable used as a cheaper cache for a state variable is only used once 1 3
[G‑40] Consider using bytes32 rather than a string 8 -
[G‑41] The result of function calls should be cached rather than re-calling the function 8 -
[G‑42] Use a more recent version of solidity 2 -
[G‑43] Not using the named return variables anywhere in the function is confusing 69 -
[G‑44] Avoid contract existence checks by using low level calls 2 200
[G‑45] String literals passed to abi.encode()/abi.encodePacked() should not be split by commas 1 21

Total: 1191 instances over 45 issues with 494747 gas saved

Gas totals are estimates based on data from the Ethereum Yellowpaper. The estimates use the lower bounds of ranges and count two iterations of each for-loop. All values above are runtime, not deployment, values; deployment values are listed in the individual issue descriptions. The table above as well as its gas numbers do not include any of the excluded findings.

Disputed Issues

The issues below may be reported by other bots/wardens, but can be penalized/ignored since either the rule or the specified instances are invalid

Issue Instances
[D‑01] Storage Write Removal Bug On Conditional Early Termination 16
[D‑02] Do not calculate constant variables, which will save gas 5
[D‑03] Use delete instead of setting mapping/state variable to zero, to save gas 16
[D‑04] abi.encode() is less efficient than abi.encodepacked() 17
[D‑05] Contracts do not work with fee-on-transfer tokens 72
[D‑06] Tokens may be minted to address(0x0) 10
[D‑07] Contracts are not using their OZ Upgradeable counterparts 59
[D‑08] Change public function visibility to external to save gas 70
[D‑09] Save gas with the use of specific import statements 324
[D‑10] safeTransfer function does not check for contract existence 2
[D‑11] Shorten the array rather than copying to a new one 7

Total: 598 instances over 11 issues

Medium Risk Issues

[M‑01] The owner is a single point of failure and a centralization risk

Having a single EOA as the only owner of contracts is a large centralization risk and a single point of failure. A single private key may be taken in a hack, or the sole holder of the key may become unable to retrieve the key when necessary. Consider changing to a multi-signature setup, or having a role-based authorization model.

There are 85 instances of this issue:

see instances
File: contracts/Penrose.sol

256:     function setBigBangEthMarketDebtRate(uint256 _rate) external onlyOwner {

263:     function setBigBangEthMarket(address _market) external onlyOwner {

281:     function setConservator(address _conservator) external onlyOwner {

291:     function setUsdoToken(address _usdoToken) external onlyOwner {

317      function registerSingularityMasterContract(
318          address mcAddress,
319          IPenrose.ContractType contractType_
320:     ) external onlyOwner {

339      function registerBigBangMasterContract(
340          address mcAddress,
341          IPenrose.ContractType contractType_
342:     ) external onlyOwner {

362      function registerSingularity(
363          address mc,
364          bytes calldata data,
365          bool useCreate2
366      )
367          external
368          payable
369          onlyOwner
370          registeredSingularityMasterContract(mc)
371          returns (address _contract)
372:     {

381      function addSingularity(
382          address mc,
383          address _contract
384:     ) external onlyOwner registeredSingularityMasterContract(mc) {

395      function registerBigBang(
396          address mc,
397          bytes calldata data,
398          bool useCreate2
399      )
400          external
401          payable
402          onlyOwner
403          registeredBigBangMasterContract(mc)
404          returns (address _contract)
405:     {

414      function addBigBang(
415          address mc,
416          address _contract
417:     ) external onlyOwner registeredBigBangMasterContract(mc) {

424      function executeMarketFn(
425          address[] calldata mc,
426          bytes[] memory data,
427          bool forceSuccess
428      )
429          external
430          onlyOwner
431          notPaused
432          returns (bool[] memory success, bytes[] memory result)
433:     {

455:     function setFeeTo(address feeTo_) external onlyOwner {

464:     function setSwapper(ISwapper swapper, bool enable) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L256-L256

File: contracts/markets/Market.sol

142:     function setBorrowOpeningFee(uint256 _val) external onlyOwner {

151:     function setBorrowCap(uint256 _cap) external notPaused onlyOwner {

158      function setMarketConfig(
159          uint256 _borrowOpeningFee,
160          IOracle _oracle,
161          bytes calldata _oracleData,
162          address _conservator,
163          uint256 _callerFee,
164          uint256 _protocolFee,
165          uint256 _liquidationBonusAmount,
166          uint256 _minLiquidatorReward,
167          uint256 _maxLiquidatorReward,
168          uint256 _totalBorrowCap,
169          uint256 _collateralizationRate
170:     ) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L142-L142

File: contracts/markets/bigBang/BigBang.sol

442      function refreshPenroseFees(
443          address
444:     ) external onlyOwner notPaused returns (uint256 feeShares) {

466      function setBigBangConfig(
467          uint256 _minDebtRate,
468          uint256 _maxDebtRate,
469          uint256 _debtRateAgainstEthMarket,
470          uint256 _liquidationMultiplier
471:     ) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L442-L444

File: contracts/markets/singularity/Singularity.sol

477      function refreshPenroseFees(
478          address feeTo
479:     ) external onlyOwner notPaused returns (uint256 feeShares) {

489      function setSingularityConfig(
490          uint256 _lqCollateralizationRate,
491          uint256 _liquidationMultiplier,
492          uint256 _minimumTargetUtilization,
493          uint256 _maximumTargetUtilization,
494          uint64 _minimumInterestPerSecond,
495          uint64 _maximumInterestPerSecond,
496          uint256 _interestElasticity
497:     ) external onlyOwner {

576      function setLiquidationQueueConfig(
577          ILiquidationQueue _liquidationQueue,
578          address _bidExecutionSwapper,
579          address _usdoSwapper
580:     ) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L477-L479

File: contracts/usd0/BaseUSDO.sol

88:      function setMaxFlashMintable(uint256 _val) external onlyOwner {

96:      function setFlashMintFee(uint256 _val) external onlyOwner {

105:     function setConservator(address _conservator) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDO.sol#L88-L88

File: contracts/Balancer.sol

172      function rebalance(
173          address payable _srcOft,
174          uint16 _dstChainId,
175          uint256 _slippage,
176          uint256 _amount,
177          bytes memory _ercData
178      )
179          external
180          payable
181          onlyOwner
182          onlyValidDestination(_srcOft, _dstChainId)
183          onlyValidSlippage(_slippage)
184:     {

219      function initConnectedOFT(
220          address _srcOft,
221          uint16 _dstChainId,
222          address _dstOft,
223          bytes memory _ercData
224:     ) external onlyOwner {

250      function addRebalanceAmount(
251          address _srcOft,
252          uint16 _dstChainId,
253          uint256 _amount
254:     ) external onlyValidDestination(_srcOft, _dstChainId) onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L172-L184

File: contracts/TapiocaWrapper.sol

115      function executeTOFT(
116          address _toft,
117          bytes calldata _bytecode,
118          bool _revertOnFailure
119:     ) external payable onlyOwner returns (bool success, bytes memory result) {

131      function executeCalls(
132          ExecutionCall[] calldata _call
133      )
134          external
135          payable
136          onlyOwner
137          returns (bool success, bytes[] memory results)
138:     {

154      function createTOFT(
155          address _erc20,
156          bytes calldata _bytecode,
157          bytes32 _salt,
158          bool _linked
159:     ) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L115-L119

File: contracts/tOFT/mTapiocaOFT.sol

116      function updateConnectedChain(
117          uint256 _chain,
118          bool _status
119:     ) external onlyOwner {

131      function updateBalancerState(
132          address _balancer,
133          bool _status
134:     ) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol#L116-L119

File: contracts/Vesting.sol

130:     function registerUser(address _user, uint256 _amount) external onlyOwner {

151:     function init(IERC20 _token, uint256 _seededAmount) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L130-L130

File: contracts/governance/twTAP.sol

455:     function addRewardToken(IERC20 token) external onlyOwner returns (uint256) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L455-L455

File: contracts/option-airdrop/AirdropBroker.sol

308      function setTapOracle(
309          IOracle _tapOracle,
310          bytes calldata _tapOracleData
311:     ) external onlyOwner {

318      function setPhase2MerkleRoots(
319          bytes32[4] calldata _merkleRoots
320:     ) external onlyOwner {

324      function registerUserForPhase(
325          uint256 _phase,
326          address[] calldata _users,
327          uint256[] calldata _amounts
328:     ) external onlyOwner {

344      function setPaymentToken(
345          ERC20 _paymentToken,
346          IOracle _oracle,
347          bytes calldata _oracleData
348:     ) external onlyOwner {

357      function setPaymentTokenBeneficiary(
358          address _paymentTokenBeneficiary
359:     ) external onlyOwner {

365      function collectPaymentTokens(
366          address[] calldata _paymentTokens
367:     ) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L308-L311

File: contracts/options/TapiocaOptionBroker.sol

446      function setTapOracle(
447          IOracle _tapOracle,
448          bytes calldata _tapOracleData
449:     ) external onlyOwner {

458      function setPaymentToken(
459          ERC20 _paymentToken,
460          IOracle _oracle,
461          bytes calldata _oracleData
462:     ) external onlyOwner {

471      function setPaymentTokenBeneficiary(
472          address _paymentTokenBeneficiary
473:     ) external onlyOwner {

479      function collectPaymentTokens(
480          address[] calldata _paymentTokens
481:     ) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L446-L449

File: contracts/options/TapiocaOptionLiquidityProvision.sol

259      function setSGLPoolWEight(
260          IERC20 singularity,
261          uint256 weight
262:     ) external onlyOwner updateTotalSGLPoolWeights {

276      function registerSingularity(
277          IERC20 singularity,
278          uint256 assetID,
279          uint256 weight
280:     ) external onlyOwner updateTotalSGLPoolWeights {

297      function unregisterSingularity(
298          IERC20 singularity
299:     ) external onlyOwner updateTotalSGLPoolWeights {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L259-L262

File: contracts/tokens/BaseTapOFT.sol

326:     function setTwTap(address _twTap) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L326-L326

File: contracts/tokens/LTap.sol

53:      function setLockedUntil(uint256 _lockedUntil) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L53-L53

File: contracts/tokens/TapOFT.sol

140      function setGovernanceChainIdentifier(
141          uint256 _identifier
142:     ) external onlyOwner {

152:     function updatePause(bool val) external onlyOwner {

160:     function setMinter(address _minter) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L140-L142

File: contracts/Swapper/UniswapV3Swapper.sol

61:      function setPoolFee(uint24 _newFee) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L61-L61

File: contracts/aave/AaveStrategy.sol

122:     function setDepositThreshold(uint256 amount) external onlyOwner {

129:     function setMultiSwapper(address _swapper) external onlyOwner {

209:     function emergencyWithdraw() external onlyOwner returns (uint256 result) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L122-L122

File: contracts/balancer/BalancerStrategy.sol

109:     function setDepositThreshold(uint256 amount) external onlyOwner {

120:     function emergencyWithdraw() external onlyOwner returns (uint256 result) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L109-L109

File: contracts/compound/CompoundStrategy.sol

89:      function setDepositThreshold(uint256 amount) external onlyOwner {

100:     function emergencyWithdraw() external onlyOwner returns (uint256 result) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L89-L89

File: contracts/convex/ConvexTricryptoStrategy.sol

148:     function emergencyWithdraw() external onlyOwner returns (uint256 result) {

163:     function setDepositThreshold(uint256 amount) external onlyOwner {

170:     function setMultiSwapper(address _swapper) external onlyOwner {

179:     function setTricryptoLPGetter(address _lpGetter) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L148-L148

File: contracts/curve/TricryptoLPStrategy.sol

134:     function setDepositThreshold(uint256 amount) external onlyOwner {

141:     function setMultiSwapper(address _swapper) external onlyOwner {

150:     function setTricryptoLPGetter(address _lpGetter) external onlyOwner {

199:     function emergencyWithdraw() external onlyOwner returns (uint256 result) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L134-L134

File: contracts/curve/TricryptoNativeStrategy.sol

125:     function setDepositThreshold(uint256 amount) external onlyOwner {

132:     function setMultiSwapper(address _swapper) external onlyOwner {

141:     function setTricryptoLPGetter(address _lpGetter) external onlyOwner {

182:     function emergencyWithdraw() external onlyOwner returns (uint256 result) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L125-L125

File: contracts/glp/GlpStrategy.sol

104:     function harvestGmx(uint256 priceNum, uint256 priceDenom) public onlyOwner {

113:     function setFeeRecipient(address recipient) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L104-L104

File: contracts/lido/LidoEthStrategy.sol

93:      function setDepositThreshold(uint256 amount) external onlyOwner {

104:     function emergencyWithdraw() external onlyOwner returns (uint256 result) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L93-L93

File: contracts/stargate/StargateStrategy.sol

142:     function setDepositThreshold(uint256 amount) external onlyOwner {

149:     function setMultiSwapper(address _swapper) external onlyOwner {

193:     function emergencyWithdraw() external onlyOwner returns (uint256 result) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L142-L142

File: contracts/yearn/YearnStrategy.sol

90:      function setDepositThreshold(uint256 amount) external onlyOwner {

101:     function emergencyWithdraw() external onlyOwner returns (uint256 result) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L90-L90

File: contracts/NativeTokenFactory.sol

56:      function transferOwnership(uint256 tokenId, address newOwner, bool direct, bool renounce) public onlyOwner(tokenId) {

109:     function mint(uint256 tokenId, address to, uint256 amount) public onlyOwner(tokenId) {

127:     function batchMint(uint256 tokenId, address[] calldata tos, uint256[] calldata amounts) public onlyOwner(tokenId) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L56-L56

[M‑02] Excess funds sent via msg.value not refunded

The code below allows the caller to provide Ether, but does not refund the amount in excess of what's required, leaving funds stranded in the contract. The condition should be changed to check for equality, or the code should refund the excess.

There is one instance of this issue:

File: contracts/Balancer.sol

201          bool _isNative = ITapiocaOFT(_srcOft).erc20() == address(0);
202          if (_isNative) {
203              if (msg.value <= _amount) revert FeeAmountNotSet();
204              _sendNative(_srcOft, _amount, _dstChainId, _slippage);
205          } else {
206              if (msg.value == 0) revert FeeAmountNotSet();
207              _sendToken(_srcOft, _amount, _dstChainId, _slippage, _ercData);
208          }
209  
210          connectedOFTs[_srcOft][_dstChainId].rebalanceable -= _amount;
211          emit Rebalanced(_srcOft, _dstChainId, _slippage, _amount, _isNative);
212:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L201-L212

[M‑03] Contracts are vulnerable to fee-on-transfer accounting-related issues

The functions below transfer funds from the caller to the receiver via transferFrom(), but do not ensure that the actual number of tokens received is the same as the input amount to the transfer. If the token is a fee-on-transfer token, the balance after the transfer will be smaller than expected, leading to accounting issues. Even if there are checks later, related to a secondary transfer, an attacker may be able to use latent funds (e.g. mistakenly sent by another user) in order to get a free credit. One way to solve this problem is to measure the balance before and after the transfer, and use the difference as the amount, rather than the stated amount.

There are 4 instances of this issue:

File: contracts/option-airdrop/AirdropBroker.sol

487      function _processOTCDeal(
488          ERC20 _paymentToken,
489          PaymentTokenOracle memory _paymentTokenOracle,
490          uint256 tapAmount,
491          uint256 discount
492      ) internal {
493          // Get TAP valuation
494          uint256 otcAmountInUSD = tapAmount * epochTAPValuation;
495  
496          // Get payment token valuation
497          (, uint256 paymentTokenValuation) = _paymentTokenOracle.oracle.get(
498              _paymentTokenOracle.oracleData
499          );
500  
501          // Calculate payment amount and initiate the transfers
502          uint256 discountedPaymentAmount = _getDiscountedPaymentAmount(
503              otcAmountInUSD,
504              paymentTokenValuation,
505              discount,
506              _paymentToken.decimals()
507          );
508  
509          _paymentToken.transferFrom(
510              msg.sender,
511              address(this),
512              discountedPaymentAmount
513          );
514          tapOFT.transfer(msg.sender, tapAmount);
515:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L487-L515

File: contracts/options/TapiocaOptionBroker.sol

508      function _processOTCDeal(
509          ERC20 _paymentToken,
510          PaymentTokenOracle memory _paymentTokenOracle,
511          uint256 tapAmount,
512          uint256 discount
513      ) internal {
514          // Get TAP valuation
515          uint256 otcAmountInUSD = tapAmount * epochTAPValuation;
516  
517          // Get payment token valuation
518          (, uint256 paymentTokenValuation) = _paymentTokenOracle.oracle.get(
519              _paymentTokenOracle.oracleData
520          );
521  
522          // Calculate payment amount and initiate the transfers
523          uint256 discountedPaymentAmount = _getDiscountedPaymentAmount(
524              otcAmountInUSD,
525              paymentTokenValuation,
526              discount,
527              _paymentToken.decimals()
528          );
529  
530          _paymentToken.transferFrom(
531              msg.sender,
532              address(this),
533              discountedPaymentAmount
534          );
535          tapOFT.extractTAP(msg.sender, tapAmount);
536:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L508-L536

File: contracts/Magnetar/modules/MagnetarMarketModule.sol

792      function _extractTokens(
793          address _from,
794          address _token,
795          uint256 _amount
796      ) private {
797          IERC20(_token).safeTransferFrom(_from, address(this), _amount);
798:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L792-L798

File: contracts/Swapper/BaseSwapper.sol

144      function _extractTokens(
145          ISwapper.YieldBoxData calldata ybData,
146          IYieldBox _yieldBox,
147          address token,
148          uint256 tokenId,
149          uint256 amount,
150          uint256 share
151      ) internal returns (uint256) {
152          if (ybData.withdrawFromYb) {
153              (amount, share) = _yieldBox.withdraw(
154                  tokenId,
155                  address(this),
156                  address(this),
157                  amount,
158                  share
159              );
160              return amount;
161          }
162          IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
163          return amount;
164:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol#L144-L164

[M‑04] Unsafe use of transfer()/transferFrom() with IERC20

Some tokens do not implement the ERC20 standard properly but are still accepted by most code that accepts ERC20 tokens. For example Tether (USDT)'s transfer() and transferFrom() functions on L1 do not return booleans as the specification requires, and instead have no return value. When these sorts of tokens are cast to IERC20, their function signatures do not match and therefore the calls made, revert (see this link for a test case). Use OpenZeppelin’s SafeERC20's safeTransfer()/safeTransferFrom() instead

There are 4 instances of this issue:

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

377                   paymentToken.transfer(
378                       paymentTokenBeneficiary,
379                       paymentToken.balanceOf(address(this))
380:                  );

509           _paymentToken.transferFrom(
510               msg.sender,
511               address(this),
512               discountedPaymentAmount
513:          );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L377-L380

File: tap-token-audit/contracts/options/TapiocaOptionBroker.sol

491                   paymentToken.transfer(
492                       paymentTokenBeneficiary,
493                       paymentToken.balanceOf(address(this))
494:                  );

530           _paymentToken.transferFrom(
531               msg.sender,
532               address(this),
533               discountedPaymentAmount
534:          );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L491-L494

[M‑05] Use of transferFrom() rather than safeTransferFrom() for NFTs in will lead to the loss of NFTs

The EIP-721 standard says the following about transferFrom():

    /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
    ///  TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
    ///  THEY MAY BE PERMANENTLY LOST
    /// @dev Throws unless `msg.sender` is the current owner, an authorized
    ///  operator, or the approved address for this NFT. Throws if `_from` is
    ///  not the current owner. Throws if `_to` is the zero address. Throws if
    ///  `_tokenId` is not a valid NFT.
    /// @param _from The current owner of the NFT
    /// @param _to The new owner
    /// @param _tokenId The NFT to transfer
    function transferFrom(address _from, address _to, uint256 _tokenId) external payable;

https://github.com/ethereum/EIPs/blob/78e2c297611f5e92b6a5112819ab71f74041ff25/EIPS/eip-721.md?plain=1#L103-L113 Code must use the safeTransferFrom() flavor if it hasn't otherwise verified that the receiving address can handle it

There is one instance of this issue:

File: tap-token-audit/contracts/options/TapiocaOptionBroker.sol

342:          tOLP.transferFrom(address(this), otapOwner, oTAPPosition.tOLP);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L342

[M‑06] Return values of transfer()/transferFrom() not checked

Not all IERC20 implementations revert() when there's a failure in transfer()/transferFrom(). The function signature has a boolean return value and they indicate errors that way instead. By not checking the return value, operations that should have marked as failed, may potentially go through without actually making a payment

There are 6 instances of this issue:

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

377                   paymentToken.transfer(
378                       paymentTokenBeneficiary,
379                       paymentToken.balanceOf(address(this))
380:                  );

509           _paymentToken.transferFrom(
510               msg.sender,
511               address(this),
512               discountedPaymentAmount
513:          );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L377-L380

File: tap-token-audit/contracts/options/TapiocaOptionBroker.sol

491                   paymentToken.transfer(
492                       paymentTokenBeneficiary,
493                       paymentToken.balanceOf(address(this))
494:                  );

530           _paymentToken.transferFrom(
531               msg.sender,
532               address(this),
533               discountedPaymentAmount
534:          );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L491-L494

File: tap-token-audit/contracts/tokens/LTap.sol

42:           tapToken.transferFrom(msg.sender, address(this), amount);

50:           tapToken.transfer(msg.sender, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L42

[M‑07] _safeMint() should be used rather than _mint() wherever possible

_mint() is discouraged in favor of _safeMint() which ensures that the recipient is either an EOA or implements IERC721Receiver. Both OpenZeppelin and solmate have versions of this function. In the cases below, _mint() does not call ERC721TokenReceiver.onERC721Received() on the recipient.

There are 3 instances of this issue:

File: YieldBox/contracts/YieldBox.sol

139:          _mint(to, assetId, share);

178:          _mint(to, assetId, 1);

204:          _mint(to, assetId, share);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L139

Low Risk Issues

[L‑01] Some tokens may revert when zero value transfers are made

In spite of the fact that EIP-20 states that zero-valued transfers must be accepted, some tokens, such as LEND will revert if this is attempted, which may cause transactions that involve other tokens (such as batch operations) to fully revert. Consider skipping the transfer if the amount is zero, which will also save gas.

There are 19 instances of this issue:

see instances
File: contracts/tOFT/BaseTOFT.sol

356                  "TOFT_allowed"
357              );
358          }
359:         IERC20(erc20).safeTransferFrom(_fromAddress, address(this), _amount);

371          if (erc20 == address(0)) {
372              _safeTransferETH(_toAddress, _amount);
373          } else {
374:             IERC20(erc20).safeTransfer(_toAddress, _amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFT.sol#L356-L359

File: contracts/tOFT/mTapiocaOFT.sol

145          if (_isNative) {
146              _safeTransferETH(msg.sender, _amount);
147          } else {
148:             IERC20(erc20).safeTransfer(msg.sender, _amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol#L145-L148

File: contracts/tOFT/modules/BaseTOFTLeverageModule.sol

272          if (erc20 == address(0)) {
273              _safeTransferETH(_toAddress, _amount);
274          } else {
275:             IERC20(erc20).safeTransfer(_toAddress, _amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L272-L275

File: contracts/Vesting.sol

116          users[msg.sender].claimed += _claimable;
117          users[msg.sender].latestClaimTimestamp = block.timestamp;
118  
119:         token.safeTransfer(msg.sender, _claimable);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L116-L119

File: contracts/governance/twTAP.sol

445          totals.totalDistPerVote[_rewardTokenId] +=
446              (_amount * DIST_PRECISION) /
447              uint256(totals.netActiveVotes);
448:         rewardToken.safeTransferFrom(msg.sender, address(this), _amount);

489                  if (amount > 0) {
490                      // Math is safe: `amount` calculated safely in `claimable()`
491                      claimed[_tokenId][i] += amount;
492:                     rewardTokens[i].safeTransfer(_to, amount);

511                  if (amount > 0) {
512                      // Math is safe: `amount` calculated safely in `claimable()`
513                      claimed[_tokenId][claimableIndex] += amount;
514:                     rewardTokens[claimableIndex].safeTransfer(_to, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L445-L448

File: contracts/option-airdrop/AirdropBroker.sol

374          unchecked {
375              for (uint256 i = 0; i < len; ++i) {
376                  ERC20 paymentToken = ERC20(_paymentTokens[i]);
377                  paymentToken.transfer(
378                      paymentTokenBeneficiary,
379                      paymentToken.balanceOf(address(this))
380:                 );

506              _paymentToken.decimals()
507          );
508  
509          _paymentToken.transferFrom(
510              msg.sender,
511              address(this),
512              discountedPaymentAmount
513:         );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L374-L380

File: contracts/options/TapiocaOptionBroker.sol

488          unchecked {
489              for (uint256 i = 0; i < len; ++i) {
490                  ERC20 paymentToken = ERC20(_paymentTokens[i]);
491                  paymentToken.transfer(
492                      paymentTokenBeneficiary,
493                      paymentToken.balanceOf(address(this))
494:                 );

527              _paymentToken.decimals()
528          );
529  
530          _paymentToken.transferFrom(
531              msg.sender,
532              address(this),
533              discountedPaymentAmount
534:         );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L488-L494

File: contracts/Magnetar/modules/MagnetarMarketModule.sol

420              (uint256 tOLPSglAssetId, , ) = ITapiocaOptionLiquidityProvision(
421                  lockData.target
422              ).activeSingularities(address(singularity));
423              IERC20(address(singularity)).safeTransferFrom(
424                  user,
425                  address(this),
426                  fraction
427:             );

794          address _token,
795          uint256 _amount
796      ) private {
797:         IERC20(_token).safeTransferFrom(_from, address(this), _amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L420-L427

File: contracts/Swapper/BaseSwapper.sol

159              );
160              return amount;
161          }
162:         IERC20(token).safeTransferFrom(msg.sender, address(this), amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol#L159-L162

File: contracts/Swapper/CurveSwapper.sol

137                  0
138              );
139          } else {
140:             IERC20(tokenOut).safeTransfer(to, amountOut);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol#L137-L140

File: contracts/glp/GlpStrategy.sol

145              glpVester.withdraw();
146          }
147          // Call this first; `_vestByGlp()` will lock the GLP again
148:         IERC20(contractAddress).safeTransfer(to, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L145-L148

File: contracts/YieldBox.sol

141          // Interactions
142          if (asset.tokenType == TokenType.ERC20) {
143              // For ERC20 tokens, use the safe helper function to deal with broken ERC20 implementations. This actually calls transferFrom on the ERC20 contract.
144:             IERC20(asset.contractAddress).safeTransferFrom(from, address(asset.strategy), amount);

206          // Interactions
207          wrappedNative.deposit{ value: amount }();
208          // Strategies always receive wrappedNative (supporting both wrapped and raw native tokens adds too much complexity)
209:         wrappedNative.safeTransfer(address(asset.strategy), amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L141-L144

[L‑02] calc_token_amount() has slippage added on top of Curve's calculated slippage

According to the Curve docs, StableSwap.calc_token_amount() already includes slippage but not fees, so adding extra slippage on top of the returned result, as is done by the caller of functions higher up the caller chain, is an incorrect operation.

There is one instance of this issue:

File: contracts/curve/TricryptoLPGetter.sol

/// @audit TricryptoNativeStrategy._addLiquidityAndStake()
200      function _calcDepositInOneCoin(
201          uint256[3] memory arr
202      ) private view returns (uint256) {
203:         return liquidityPool.calc_token_amount(arr, true);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPGetter.sol#L200-L203

[L‑03] approve()/safeApprove() may revert if the current approval is not zero

Calling approve() without first calling approve(0) if the current approval is non-zero will revert with some tokens, such as Tether (USDT). While Tether is known to do this, it applies to other tokens as well, which are trying to protect against this attack vector. safeApprove() itself also implements this protection. Always reset the approval to zero before changing it to a new value, or use safeIncreaseAllowance()/safeDecreaseAllowance()

There are 20 instances of this issue:

see instances
File: contracts/markets/bigBang/BigBang.sol

450:             asset.approve(address(yieldBox), totalFees);

761:         asset.approve(address(yieldBox), amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L450-L450

File: contracts/Balancer.sol

321:         erc20.approve(address(router), _amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L321-L321

File: contracts/tOFT/modules/BaseTOFTLeverageModule.sol

215:         IERC20(erc20).approve(externalData.swapper, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L215-L215

File: contracts/tOFT/modules/BaseTOFTStrategyModule.sol

184:         _erc20.approve(address(yieldBox), _amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol#L184-L184

File: contracts/Magnetar/modules/MagnetarMarketModule.sol

157:             IERC20(collateralAddress).approve(

234:             IERC20(assetAddress).approve(address(yieldBox), depositAmount);

339:                 IERC20(bbCollateralAddress).approve(

386:             IERC20(sglAssetAddress).approve(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L157-L157

File: contracts/aave/AaveStrategy.sol

76:          rewardToken.approve(_multiSwapper, type(uint256).max);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L76-L76

File: contracts/convex/ConvexTricryptoStrategy.sol

108:         rewardToken.approve(_multiSwapper, type(uint256).max);

172:         rewardToken.approve(address(swapper), 0);

174:         rewardToken.approve(_swapper, type(uint256).max);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L108-L108

File: contracts/curve/TricryptoLPStrategy.sol

79:          lpToken.approve(_lpGauge, type(uint256).max);

81:          rewardToken.approve(_multiSwapper, type(uint256).max);

143:         rewardToken.approve(address(swapper), 0);

144:         rewardToken.approve(_swapper, type(uint256).max);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L79-L79

File: contracts/curve/TricryptoNativeStrategy.sol

80:          rewardToken.approve(_multiSwapper, type(uint256).max);

134:         rewardToken.approve(address(swapper), 0);

135:         rewardToken.approve(_swapper, type(uint256).max);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L80-L80

[L‑04] Missing contract-existence checks before low-level calls

Low-level calls return success if there is no code present at the specified address. In addition to the zero-address checks, add a check to verify that <address>.code.length > 0

There are 29 instances of this issue:

see instances
File: contracts/Penrose.sol

444              (success[i], result[i]) = mc[i].call(data[i]);
445              if (forceSuccess) {
446                  require(success[i], _getRevertMsg(result[i]));
447              }
448              ++i;
449:         }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L444-L449

File: contracts/markets/bigBang/BigBang.sol

216              (bool success, bytes memory result) = address(this).delegatecall(
217                  calls[i]
218              );
219              require(success || !revertOnFail, _getRevertMsg(result));
220              successes[i] = success;
221:             results[i] = _getRevertMsg(result);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L216-L221

File: contracts/markets/singularity/Singularity.sol

188              (bool success, bytes memory result) = address(this).delegatecall(
189                  calls[i]
190              );
191              require(success || !revertOnFail, _getRevertMsg(result));
192              successes[i] = success;
193:             results[i] = _getRevertMsg(result);

625          (success, returnData) = module.delegatecall(_data);
626          if (!success) {
627              revert(_getRevertMsg(returnData));
628          }
629:     }

638          (success, returnData) = module.staticcall(_data);
639          if (!success) {
640              revert(_getRevertMsg(returnData));
641          }
642:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L188-L193

File: contracts/usd0/BaseUSDO.sol

369          (success, returnData) = module.delegatecall(_data);
370          if (!success && !_forwardRevert) {
371              revert(_getRevertMsg(returnData));
372          }
373:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDO.sol#L369-L373

File: contracts/usd0/modules/USDOLeverageModule.sol

169          (bool success, bytes memory reason) = module.delegatecall(
170              abi.encodeWithSelector(
171                  this.leverageUpInternal.selector,
172                  amount,
173                  swapData,
174:                 externalData,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L169-L174

File: contracts/usd0/modules/USDOMarketModule.sol

168          (bool success, bytes memory reason) = module.delegatecall(
169              abi.encodeWithSelector(
170                  this.lendInternal.selector,
171                  to,
172                  lendParams,
173:                 approvals,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol#L168-L173

File: contracts/usd0/modules/USDOOptionsModule.sol

174          (bool success, bytes memory reason) = module.delegatecall(
175              abi.encodeWithSelector(
176                  this.exerciseInternal.selector,
177                  optionsData.from,
178                  optionsData.oTAPTokenID,
179:                 optionsData.paymentToken,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol#L174-L179

File: contracts/TapiocaWrapper.sol

120          (success, result) = payable(_toft).call{value: msg.value}(_bytecode);
121          if (_revertOnFailure && !success) {
122              revert TapiocaWrapper__TOFTExecutionFailed(result);
123          }
124:     }

141              (success, results[i]) = payable(_call[i].toft).call{
142                  value: msg.value
143              }(_call[i].bytecode);
144              if (_call[i].revertOnFailure && !success) {
145                  revert TapiocaWrapper__TOFTExecutionFailed(results[i]);
146:             }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L120-L124

File: contracts/tOFT/BaseTOFT.sol

380          (bool sent, ) = to.call{value: amount}("");
381          require(sent, "TOFT_failed");
382:     }

411          (success, returnData) = module.delegatecall(_data);
412          if (!success && !_forwardRevert) {
413              revert(_getRevertMsg(returnData));
414          }
415:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFT.sol#L380-L382

File: contracts/tOFT/modules/BaseTOFTLeverageModule.sol

184          (bool success, bytes memory reason) = module.delegatecall(
185              abi.encodeWithSelector(
186                  this.leverageDownInternal.selector,
187                  amount,
188                  swapData,
189:                 externalData,

280          (bool sent, ) = to.call{value: amount}("");
281          require(sent, "TOFT_failed");
282:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L184-L189

File: contracts/tOFT/modules/BaseTOFTMarketModule.sol

160          (bool success, bytes memory reason) = module.delegatecall(
161              abi.encodeWithSelector(
162                  this.borrowInternal.selector,
163                  _to,
164                  borrowParams,
165:                 withdrawParams,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L160-L165

File: contracts/tOFT/modules/BaseTOFTOptionsModule.sol

189          (bool success, bytes memory reason) = module.delegatecall(
190              abi.encodeWithSelector(
191                  this.exerciseInternal.selector,
192                  optionsData.from,
193                  optionsData.oTAPTokenID,
194:                 optionsData.paymentToken,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol#L189-L194

File: contracts/tOFT/modules/BaseTOFTStrategyModule.sol

152          (bool success, bytes memory reason) = module.delegatecall(
153              abi.encodeWithSelector(
154                  this.depositToYieldbox.selector,
155                  assetId,
156                  amount,
157:                 share,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol#L152-L157

File: contracts/tokens/BaseTapOFT.sol

236                      rewardClaimSendParams[i].callParams
237                  );
238                  ++i;
239              }
240          } catch Error(string memory _reason) {
241:             emit CallFailedStr(_srcChainId, _payload, _reason);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L236-L241

File: contracts/Magnetar/MagnetarV2.sol

1045         (bool success, bytes memory returnData) = target.call(actionCalldata);
1046         if (!success && !allowFailure) {
1047             _getRevertMsg(returnData);
1048         }
1049:    }

1071         (success, returnData) = module.delegatecall(_data);
1072         if (!success) {
1073             _getRevertMsg(returnData);
1074         }
1075:    }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L1045-L1049

File: contracts/Multicall/Multicall3.sol

52                   calli.callData
53               );
54               if (!result.success) {
55                   _getRevertMsg(result.returnData);
56               }
57:              unchecked {

51               (result.success, result.returnData) = calli.target.call(
52                   calli.callData
53               );
54               if (!result.success) {
55                   _getRevertMsg(result.returnData);
56:              }

80                   calli.callData
81               );
82               if (!result.success) {
83                   _getRevertMsg(result.returnData);
84               }
85:              unchecked {

79               (result.success, result.returnData) = calli.target.call{value: val}(
80                   calli.callData
81               );
82               if (!result.success) {
83                   _getRevertMsg(result.returnData);
84:              }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Multicall/Multicall3.sol#L52-L57

File: contracts/Swapper/BaseSwapper.sol

99           (bool success, bytes memory data) = token.call(
100              abi.encodeWithSelector(0x095ea7b3, to, value)
101          );
102          require(
103              success && (data.length == 0 || abi.decode(data, (bool))),
104:             "BaseSwapper::safeApprove: approve failed"

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol#L99-L104

File: contracts/convex/ConvexTricryptoStrategy.sol

356          (bool successEmtptyApproval, ) = token.call(
357              abi.encodeWithSelector(
358                  bytes4(keccak256("approve(address,uint256)")),
359                  to,
360                  0
361:             )

369          (bool success, bytes memory data) = token.call(
370              abi.encodeWithSelector(
371                  bytes4(keccak256("approve(address,uint256)")),
372                  to,
373                  value
374:             )

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L356-L361

File: contracts/curve/TricryptoLPStrategy.sol

105          (bool success, bytes memory response) = address(lpGauge).staticcall(
106              abi.encodeWithSignature("claimable_tokens(address)", address(this))
107          );
108          result = 0;
109          uint256 claimable = 0;
110:         if (success) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L105-L110

[L‑05] External call recipient may consume all transaction gas

There is no limit specified on the amount of gas used, so the recipient can use up all of the transaction's gas, causing it to revert. Use addr.call{gas: <amount>}("") or this library instead.

There are 12 instances of this issue:

see instances
File: contracts/Penrose.sol

/// @audit `executeMarketFn()`
444:             (success[i], result[i]) = mc[i].call(data[i]);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L444-L444

File: contracts/TapiocaWrapper.sol

/// @audit `executeTOFT()`
120:         (success, result) = payable(_toft).call{value: msg.value}(_bytecode);

/// @audit `executeCalls()`
141:             (success, results[i]) = payable(_call[i].toft).call{

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L120-L120

File: contracts/tOFT/BaseTOFT.sol

/// @audit `_safeTransferETH()`
380:         (bool sent, ) = to.call{value: amount}("");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFT.sol#L380-L380

File: contracts/tOFT/modules/BaseTOFTLeverageModule.sol

/// @audit `_safeTransferETH()`
280:         (bool sent, ) = to.call{value: amount}("");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L280-L280

File: contracts/Magnetar/MagnetarV2.sol

/// @audit `burst()`
206:                     _action.call.length > 0,

/// @audit `_permit()`
1045:        (bool success, bytes memory returnData) = target.call(actionCalldata);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L206-L206

File: contracts/Multicall/Multicall3.sol

/// @audit `multicall()`
51:              (result.success, result.returnData) = calli.target.call(

/// @audit `multicallValue()`
79:              (result.success, result.returnData) = calli.target.call{value: val}(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Multicall/Multicall3.sol#L51-L51

File: contracts/Swapper/BaseSwapper.sol

/// @audit `_safeApprove()`
99:          (bool success, bytes memory data) = token.call(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol#L99-L99

File: contracts/convex/ConvexTricryptoStrategy.sol

/// @audit `_safeApprove()`
356:         (bool successEmtptyApproval, ) = token.call(

/// @audit `_safeApprove()`
369:         (bool success, bytes memory data) = token.call(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L356-L356

[L‑06] Multiplication on the result of a division

Dividing an integer by another integer will often result in loss of precision. When the result is multiplied by another number, the loss of precision is magnified, often to material magnitudes. (X / Z) * Y should be re-written as (X * Y) / Z

There are 8 instances of this issue:

File: contracts/markets/Market.sol

290          uint256 denominator = ((10 ** ratesPrecision) -
291              (collateralizationRate *
292                  ((10 ** ratesPrecision) + liquidationMultiplier)) /
293:             (10 ** ratesPrecision)) * (10 ** (18 - ratesPrecision));

392                  (userCollateralShare[user] *
393                      (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *
394:                     collateralizationRate),

392                  (userCollateralShare[user] *
393:                     (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *

417                  collateralShare *
418                      (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *
419:                     collateralizationRate,

417                  collateralShare *
418:                     (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L290-L293

File: contracts/markets/singularity/SGLLiquidation.sol

83               (collateralShare *
84                   (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *
85:                  lqCollateralizationRate),

83               (collateralShare *
84:                  (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L83-L85

File: contracts/oracle/implementations/ARBTriCryptoOracle.sol

137:         uint256 _discount = Math.max((_g ** 2 / 1 ether) * _a, 1e34); // handle qbrt nonconvergence

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol#L137-L137

[L‑07] Division by zero not prevented

The divisions below take an input parameter which does not have any zero-value checks, which may lead to the functions reverting when zero is passed.

There are 13 instances of this issue:

see instances
File: contracts/markets/Market.sol

387          uint256 _exchangeRate
388      ) internal view returns (uint256 collateralAmountInAsset) {
389          collateralAmountInAsset =
390              yieldBox.toAmount(
391                  collateralId,
392                  (userCollateralShare[user] *
393                      (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *
394                      collateralizationRate),
395                  false
396              ) /
397:             _exchangeRate;

435              false
436          );
437  
438:         max = (collateralAmount * EXCHANGE_RATE_PRECISION) / _exchangeRate;

486              return 0;
487          }
488          uint256 _numerator = numerator * 10 ** (precision + 1);
489:         uint256 _quotient = ((_numerator / denominator) + 5) / 10;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L387-L397

File: contracts/markets/bigBang/BigBang.sol

778              uint256 collateralShare
779          )
780      {
781          uint256 collateralPartInAsset = (yieldBox.toAmount(
782              collateralId,
783              userCollateralShare[user],
784              false
785:         ) * EXCHANGE_RATE_PRECISION) / _exchangeRate;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L778-L785

File: contracts/markets/singularity/SGLLiquidation.sol

78   
79           Rebase memory _totalBorrow = totalBorrow;
80   
81           uint256 collateralAmountInAsset = yieldBox.toAmount(
82               collateralId,
83               (collateralShare *
84                   (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *
85                   lqCollateralizationRate),
86               false
87:          ) / _exchangeRate;

213              uint256 collateralShare
214          )
215      {
216          uint256 collateralPartInAsset = (yieldBox.toAmount(
217              collateralId,
218              userCollateralShare[user],
219              false
220:         ) * EXCHANGE_RATE_PRECISION) / _exchangeRate;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L78-L87

File: contracts/option-airdrop/AirdropBroker.sol

527          uint256 _paymentTokenDecimals
528      ) internal pure returns (uint256 paymentAmount) {
529          // Calculate payment amount
530:         uint256 rawPaymentAmount = _otcAmountInUSD / _paymentTokenValuation;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L527-L530

File: contracts/options/TapiocaOptionBroker.sol

548          uint256 _paymentTokenDecimals
549      ) internal pure returns (uint256 paymentAmount) {
550          // Calculate payment amount
551:         uint256 rawPaymentAmount = _otcAmountInUSD / _paymentTokenValuation;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L548-L551

File: contracts/twAML.sol

138          if (_cumulative == 0) {
139              return _dMax;
140          }
141:         uint256 target = (_magnitude * _dMax) / _cumulative;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/twAML.sol#L138-L141

File: contracts/YieldBoxRebase.sol

29           totalShares_ += 1e8;
30   
31           // Calculte the shares using te current amount to share ratio
32:          share = (amount * totalShares_) / totalAmount;

32           share = (amount * totalShares_) / totalAmount;
33   
34           // Default is to round down (Solidity), round up if required
35:          if (roundUp && (share * totalAmount) / totalShares_ < amount) {

52           totalShares_ += 1e8;
53   
54           // Calculte the amount using te current amount to share ratio
55:          amount = (share * totalAmount) / totalShares_;

55           amount = (share * totalAmount) / totalShares_;
56   
57           // Default is to round down (Solidity), round up if required
58:          if (roundUp && (amount * totalShares_) / totalAmount < share) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxRebase.sol#L29-L32

[L‑08] External calls in an un-bounded for-loop may result in a DOS

Consider limiting the number of iterations in for-loops that make external calls

There are 61 instances of this issue:

see instances
File: contracts/markets/singularity/SGLLiquidation.sol

128                  uint256 collateralShare = yieldBox.toShare(
129                      collateralId,
130                      (amountWithBonus * _exchangeRate) / EXCHANGE_RATE_PRECISION,
131                      false
132:                 );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L128-L132

File: contracts/usd0/modules/USDOLeverageModule.sol

289                      IERC20Permit(approvals[i].target).permit(
290                          approvals[i].owner,
291                          approvals[i].spender,
292                          approvals[i].value,
293                          approvals[i].deadline,
294                          approvals[i].v,
295                          approvals[i].r,
296                          approvals[i].s
297:                     )

274                      IPermitAll(approvals[i].target).permitAll(
275                          approvals[i].owner,
276                          approvals[i].spender,
277                          approvals[i].deadline,
278                          approvals[i].v,
279                          approvals[i].r,
280                          approvals[i].s
281:                     )

258                      IPermitBorrow(approvals[i].target).permitBorrow(
259                          approvals[i].owner,
260                          approvals[i].spender,
261                          approvals[i].value,
262                          approvals[i].deadline,
263                          approvals[i].v,
264                          approvals[i].r,
265                          approvals[i].s
266:                     )

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L289-L297

File: contracts/usd0/modules/USDOMarketModule.sol

278                      IERC20Permit(approvals[i].target).permit(
279                          approvals[i].owner,
280                          approvals[i].spender,
281                          approvals[i].value,
282                          approvals[i].deadline,
283                          approvals[i].v,
284                          approvals[i].r,
285                          approvals[i].s
286:                     )

263                      IPermitAll(approvals[i].target).permitAll(
264                          approvals[i].owner,
265                          approvals[i].spender,
266                          approvals[i].deadline,
267                          approvals[i].v,
268                          approvals[i].r,
269                          approvals[i].s
270:                     )

247                      IPermitBorrow(approvals[i].target).permitBorrow(
248                          approvals[i].owner,
249                          approvals[i].spender,
250                          approvals[i].value,
251                          approvals[i].deadline,
252                          approvals[i].v,
253                          approvals[i].r,
254                          approvals[i].s
255:                     )

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol#L278-L286

File: contracts/usd0/modules/USDOOptionsModule.sol

279                      IERC20Permit(approvals[i].target).permit(
280                          approvals[i].owner,
281                          approvals[i].spender,
282                          approvals[i].value,
283                          approvals[i].deadline,
284                          approvals[i].v,
285                          approvals[i].r,
286                          approvals[i].s
287:                     )

264                      IPermitAll(approvals[i].target).permitAll(
265                          approvals[i].owner,
266                          approvals[i].spender,
267                          approvals[i].deadline,
268                          approvals[i].v,
269                          approvals[i].r,
270                          approvals[i].s
271:                     )

248                      IPermitBorrow(approvals[i].target).permitBorrow(
249                          approvals[i].owner,
250                          approvals[i].spender,
251                          approvals[i].value,
252                          approvals[i].deadline,
253                          approvals[i].v,
254                          approvals[i].r,
255                          approvals[i].s
256:                     )

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol#L279-L287

File: contracts/TapiocaWrapper.sol

99:              harvestableTapiocaOFTs[i].harvestFees();

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L99-L99

File: contracts/tOFT/modules/BaseTOFTLeverageModule.sol

319                      IERC20Permit(approvals[i].target).permit(
320                          approvals[i].owner,
321                          approvals[i].spender,
322                          approvals[i].value,
323                          approvals[i].deadline,
324                          approvals[i].v,
325                          approvals[i].r,
326                          approvals[i].s
327:                     )

304                      IPermitAll(approvals[i].target).permitAll(
305                          approvals[i].owner,
306                          approvals[i].spender,
307                          approvals[i].deadline,
308                          approvals[i].v,
309                          approvals[i].r,
310                          approvals[i].s
311:                     )

288                      IPermitBorrow(approvals[i].target).permitBorrow(
289                          approvals[i].owner,
290                          approvals[i].spender,
291                          approvals[i].value,
292                          approvals[i].deadline,
293                          approvals[i].v,
294                          approvals[i].r,
295                          approvals[i].s
296:                     )

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L319-L327

File: contracts/tOFT/modules/BaseTOFTMarketModule.sol

295                      IERC20Permit(approvals[i].target).permit(
296                          approvals[i].owner,
297                          approvals[i].spender,
298                          approvals[i].value,
299                          approvals[i].deadline,
300                          approvals[i].v,
301                          approvals[i].r,
302                          approvals[i].s
303:                     )

280                      IPermitAll(approvals[i].target).permitAll(
281                          approvals[i].owner,
282                          approvals[i].spender,
283                          approvals[i].deadline,
284                          approvals[i].v,
285                          approvals[i].r,
286                          approvals[i].s
287:                     )

264                      IPermitBorrow(approvals[i].target).permitBorrow(
265                          approvals[i].owner,
266                          approvals[i].spender,
267                          approvals[i].value,
268                          approvals[i].deadline,
269                          approvals[i].v,
270                          approvals[i].r,
271                          approvals[i].s
272:                     )

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L295-L303

File: contracts/tOFT/modules/BaseTOFTOptionsModule.sol

294                      IERC20Permit(approvals[i].target).permit(
295                          approvals[i].owner,
296                          approvals[i].spender,
297                          approvals[i].value,
298                          approvals[i].deadline,
299                          approvals[i].v,
300                          approvals[i].r,
301                          approvals[i].s
302:                     )

279                      IPermitAll(approvals[i].target).permitAll(
280                          approvals[i].owner,
281                          approvals[i].spender,
282                          approvals[i].deadline,
283                          approvals[i].v,
284                          approvals[i].r,
285                          approvals[i].s
286:                     )

263                      IPermitBorrow(approvals[i].target).permitBorrow(
264                          approvals[i].owner,
265                          approvals[i].spender,
266                          approvals[i].value,
267                          approvals[i].deadline,
268                          approvals[i].v,
269                          approvals[i].r,
270                          approvals[i].s
271:                     )

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol#L294-L302

File: contracts/option-airdrop/AirdropBroker.sol

377                  paymentToken.transfer(
378                      paymentTokenBeneficiary,
379                      paymentToken.balanceOf(address(this))
380:                 );

379:                     paymentToken.balanceOf(address(this))

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L377-L380

File: contracts/options/TapiocaOptionBroker.sol

491                  paymentToken.transfer(
492                      paymentTokenBeneficiary,
493                      paymentToken.balanceOf(address(this))
494:                 );

493:                     paymentToken.balanceOf(address(this))

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L491-L494

File: contracts/tokens/BaseTapOFT.sol

229                  ISendFrom(address(rewardTokens[i])).sendFrom{
230                      value: rewardClaimSendParams[i].ethValue
231                  }(
232                      address(this),
233                      _srcChainId,
234                      LzLib.addressToBytes32(to),
235                      IERC20(rewardTokens[i]).balanceOf(address(this)),
236                      rewardClaimSendParams[i].callParams
237:                 );

235:                     IERC20(rewardTokens[i]).balanceOf(address(this)),

335                  IERC20Permit(approvals[i].target).permit(
336                      approvals[i].owner,
337                      approvals[i].spender,
338                      approvals[i].value,
339                      approvals[i].deadline,
340                      approvals[i].v,
341                      approvals[i].r,
342                      approvals[i].s
343:                 )

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L229-L237

File: contracts/Magnetar/MagnetarV2.sol

699                  IUSDOBase(_action.target).removeAsset(
700                      data.from,
701                      data.to,
702                      data.lzDstChainId,
703                      data.zroPaymentAddress,
704                      data.adapterParams,
705                      data.externalData,
706                      data.removeAndRepayData,
707                      data.approvals
708:                 );

683                  IUSDOBase(_action.target).initMultiHopBuy(
684                      data.from,
685                      data.collateralAmount,
686                      data.borrowAmount,
687                      data.swapData,
688                      data.lzData,
689                      data.externalData,
690                      data.airdropAdapterParams,
691                      data.approvals
692:                 );

667                  IUSDOBase(_action.target).initMultiHopBuy(
668                      data.from,
669                      data.collateralAmount,
670                      data.borrowAmount,
671                      data.swapData,
672                      data.lzData,
673                      data.externalData,
674                      data.airdropAdapterParams,
675                      data.approvals
676:                 );

655                  ITapiocaOptionsBrokerCrossChain(_action.target).exerciseOption(
656                      data.optionsData,
657                      data.lzData,
658                      data.tapSendData,
659                      data.approvals
660:                 );

642                  IMarket(data.market).sellCollateral(
643                      data.from,
644                      data.share,
645                      data.minAmountOut,
646                      address(data.swapper),
647                      data.dexData
648:                 );

628                  IMarket(data.market).buyCollateral(
629                      data.from,
630                      data.borrowAmount,
631                      data.supplyAmount,
632                      data.minAmountOut,
633                      address(data.swapper),
634                      data.dexData
635:                 );

517                  ITapiocaOFT(_action.target).retrieveFromStrategy{
518                      value: _action.value
519                  }(
520                      msg.sender,
521                      amount,
522                      share,
523                      assetId,
524                      lzDstChainId,
525                      zroPaymentAddress,
526                      airdropAdapterParam
527:                 );

482                  ITapiocaOFT(_action.target).sendToStrategy{
483                      value: _action.value
484                  }(
485                      msg.sender,
486                      data.to,
487                      data.amount,
488                      data.share,
489                      data.assetId,
490                      data.lzDstChainId,
491                      data.options
492:                 );

463                  IUSDOBase(_action.target).sendAndLendOrRepay{
464                      value: _action.value
465                  }(
466                      msg.sender,
467                      to,
468                      dstChainId,
469                      zroPaymentAddress,
470                      lendParams,
471                      approvals,
472                      withdrawParams,
473                      adapterParams
474:                 );

426                  ITapiocaOFT(_action.target).sendToYBAndBorrow{
427                      value: _action.value
428                  }(
429                      msg.sender,
430                      to,
431                      lzDstChainId,
432                      airdropAdapterParams,
433                      borrowParams,
434                      withdrawParams,
435                      options,
436                      approvals
437:                 );

391                  uint256 amount = IMarket(_action.target).repay(
392                      msg.sender,
393                      data.to,
394                      data.skim,
395                      data.part
396:                 );

374                  uint256 fraction = IMarket(_action.target).addAsset(
375                      msg.sender,
376                      data.to,
377                      data.skim,
378                      data.share
379:                 );

316                  (uint256 part, uint256 share) = IMarket(_action.target).borrow(
317                      msg.sender,
318                      data.to,
319                      data.amount
320:                 );

302                  IMarket(_action.target).addCollateral(
303                      msg.sender,
304                      data.to,
305                      data.skim,
306                      data.amount,
307                      data.share
308:                 );

282                  (uint256 amountOut, uint256 shareOut) = IYieldBoxBase(
283                      _action.target
284                  ).depositAsset(
285                          data.assetId,
286                          msg.sender,
287                          data.to,
288                          data.amount,
289                          data.share
290:                     );

268                  ISendFrom(_action.target).sendFrom{value: _action.value}(
269                      msg.sender,
270                      dstChainId,
271                      to,
272                      amount,
273                      lzCallParams
274:                 );

243                      ITapiocaOFT(_action.target).wrap(
244                          msg.sender,
245                          data.to,
246                          data.amount
247:                     );

239                      ITapiocaOFT(_action.target).wrapNative{
240                          value: _action.value
241:                     }(data.to);

978              (uint128 totalAssetElastic, uint128 totalAssetBase) = sgl //
979:                 .totalAsset(); //

982:             result[i].userAssetFraction = sgl.balanceOf(who); //

987:             ) = sgl.getInterestDetails();

1008:            (uint64 debtRate, uint64 lastAccrued) = bigBang.accrueInfo();

1011:            result[i].minDebtRate = bigBang.minDebtRate();

1012:            result[i].maxDebtRate = bigBang.maxDebtRate();

1013             result[i].debtRateAgainstEthMarket = bigBang
1014:                .debtRateAgainstEthMarket();

1015:            result[i].currentDebtRate = bigBang.getDebtRate();

1017:            IPenrose penrose = IPenrose(bigBang.penrose());

1018:            result[i].mainBBMarket = penrose.bigBangEthMarket();

1019:            result[i].mainBBDebtRate = penrose.bigBangEthDebtRate();

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L699-L708

File: contracts/convex/ConvexTricryptoStrategy.sol

198                  ISwapper.SwapData memory swapData = swapper.buildSwapData(
199                      tokens[i],
200                      address(wrappedNative),
201                      rewards[i],
202                      0,
203                      false,
204                      false
205:                 );

206:                 uint256 calcAmount = swapper.getOutputAmount(swapData, "");

208:                 swapper.swap(swapData, minAmount, address(this), "");

256              balancesBefore[i] = IERC20(tempData.tokens[i]).balanceOf(
257                  address(this)
258:             );

274              balancesAfter[i] = IERC20(tempData.tokens[i]).balanceOf(
275                  address(this)
276:             );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L198-L205

[L‑09] State variables not capped at reasonable values

Consider adding minimum/maximum value checks to ensure that the state variables below can never be used to excessively harm users, including via griefing

There are 3 instances of this issue:

File: contracts/markets/bigBang/BigBang.sol

159:             maxDebtRate = _debtRateMax;

160:             minDebtRate = _debtRateMin;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L159-L159

File: contracts/tokens/LTap.sol

38:          maxLockedUntil = _maxLockedUntil;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L38-L38

[L‑10] Missing checks for address(0x0) when assigning values to address state variables

There are 46 instances of this issue:

see instances
File: contracts/Penrose.sol

92:          yieldBox = _yieldBox;

93:          tapToken = tapToken_;

94:          owner = _owner;

113:         wethToken = wethToken_;

264:         bigBangEthMarket = _market;

456:         feeTo = feeTo_;

570:                     markets[marketIndex] = clonesOf[mcLocation][j];

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L92-L92

File: contracts/markets/bigBang/BigBang.sol

127:         penrose = tapiocaBar_;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L127-L127

File: contracts/markets/singularity/Singularity.sol

96:          penrose = tapiocaBar_;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L96-L96

File: contracts/usd0/BaseUSDOStorage.sol

80:          yieldBox = _yieldBox;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol#L80-L80

File: contracts/tOFT/BaseTOFTStorage.sol

61:          erc20 = _erc20;

64:          yieldBox = _yieldBox;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol#L61-L61

File: contracts/Vesting.sol

72:          owner = _owner;

156:         token = _token;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L72-L72

File: contracts/option-airdrop/AirdropBroker.sol

105:         paymentTokenBeneficiary = _paymentTokenBeneficiary;

109:         owner = _owner;

312:         tapOracle = _tapOracle;

349:         paymentTokens[_paymentToken].oracle = _oracle;

360:         paymentTokenBeneficiary = _paymentTokenBeneficiary;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L105-L105

File: contracts/option-airdrop/aoTAP.sol

42:          owner = _owner;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L42-L42

File: contracts/options/TapiocaOptionBroker.sol

89:          paymentTokenBeneficiary = _paymentTokenBeneficiary;

94:          owner = _owner;

450:         tapOracle = _tapOracle;

463:         paymentTokens[_paymentToken].oracle = _oracle;

474:         paymentTokenBeneficiary = _paymentTokenBeneficiary;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L89-L89

File: contracts/options/TapiocaOptionLiquidityProvision.sol

75:          owner = _owner;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L75-L75

File: contracts/tokens/LTap.sol

36:          tapToken = _tapToken;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L36-L36

File: contracts/Swapper/CurveSwapper.sol

40:          curvePool = _curvePool;

41:          yieldBox = _yieldBox;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol#L40-L40

File: contracts/Swapper/UniswapV2Swapper.sol

41:          yieldBox = _yieldBox;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol#L41-L41

File: contracts/Swapper/UniswapV3Swapper.sol

54:          yieldBox = _yieldBox;

55:          swapRouter = _swapRouter;

56:          factory = _factory;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L54-L54

File: contracts/oracle/implementations/ARBTriCryptoOracle.sol

55:          TRI_CRYPTO = pool;

56:          BTC_FEED = btcFeed;

57:          ETH_FEED = ethFeed;

58:          USDT_FEED = usdtFeed;

59:          WBTC_FEED = wbtcFeed;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol#L55-L55

File: contracts/oracle/implementations/GLPOracle.sol

11:          glpManager = glpManager_;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/GLPOracle.sol#L11-L11

File: contracts/oracle/implementations/SGOracle.sol

38:          SG_POOL = pool;

39:          UNDERLYING = _underlying;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/SGOracle.sol#L38-L38

File: contracts/glp/GlpStrategy.sol

82:          feeRecipient = owner;

114:         feeRecipient = recipient;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L82-L82

File: contracts/stargate/StargateStrategy.sol

79:          stgEthPool = _stgEthPool;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L79-L79

File: contracts/YieldBox.sol

92:          wrappedNative = wrappedNative_;

93:          uriBuilder = uriBuilder_;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L92-L92

[L‑11] Allowed fees/rates should be capped by smart contracts

Fees/rates should be required to be below 100%, preferably at a much lower limit, to ensure users don't have to monitor the blockchain for changes prior to using the protocol

There are 2 instances of this issue:

File: contracts/Penrose.sol

256      function setBigBangEthMarketDebtRate(uint256 _rate) external onlyOwner {
257          bigBangEthDebtRate = _rate;
258          emit BigBangEthMarketDebtRate(_rate);
259:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L256-L259

File: contracts/Swapper/UniswapV3Swapper.sol

61       function setPoolFee(uint24 _newFee) external onlyOwner {
62           emit PoolFee(poolFee, _newFee);
63           poolFee = _newFee;
64:      }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L61-L64

[L‑12] Solidity version 0.8.20 may not work on other chains due to PUSH0

The compiler for Solidity 0.8.20 switches the default target EVM version to Shanghai, which includes the new PUSH0 op code. This op code may not yet be implemented on all L2s, so deployment on these chains will fail. To work around this issue, use an earlier EVM version. While the project itself may or may not compile with 0.8.20, other projects with which it integrates, or which extend this project may, and those projects will have problems deploying these contracts/libraries.

There are 67 instances of this issue:

see instances
File: contracts/Penrose.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L2-L2

File: contracts/markets/Market.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L2-L2

File: contracts/markets/MarketERC20.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L2-L2

File: contracts/markets/bigBang/BigBang.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L2-L2

File: contracts/markets/singularity/SGLBorrow.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLBorrow.sol#L2-L2

File: contracts/markets/singularity/SGLCollateral.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCollateral.sol#L2-L2

File: contracts/markets/singularity/SGLCommon.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol#L2-L2

File: contracts/markets/singularity/SGLLendingCommon.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol#L2-L2

File: contracts/markets/singularity/SGLLeverage.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLeverage.sol#L2-L2

File: contracts/markets/singularity/SGLLiquidation.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L2-L2

File: contracts/markets/singularity/SGLStorage.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L2-L2

File: contracts/markets/singularity/Singularity.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L2-L2

File: contracts/usd0/BaseUSDO.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDO.sol#L2-L2

File: contracts/usd0/BaseUSDOStorage.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol#L2-L2

File: contracts/usd0/USDO.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/USDO.sol#L2-L2

File: contracts/usd0/modules/USDOLeverageModule.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L2-L2

File: contracts/usd0/modules/USDOMarketModule.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol#L2-L2

File: contracts/usd0/modules/USDOOptionsModule.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol#L2-L2

File: contracts/Balancer.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L2-L2

File: contracts/TapiocaWrapper.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L2-L2

File: contracts/tOFT/BaseTOFT.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFT.sol#L2-L2

File: contracts/tOFT/BaseTOFTStorage.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol#L2-L2

File: contracts/tOFT/TapiocaOFT.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/TapiocaOFT.sol#L2-L2

File: contracts/tOFT/mTapiocaOFT.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol#L2-L2

File: contracts/tOFT/modules/BaseTOFTLeverageModule.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L2-L2

File: contracts/tOFT/modules/BaseTOFTMarketModule.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L2-L2

File: contracts/tOFT/modules/BaseTOFTOptionsModule.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol#L2-L2

File: contracts/tOFT/modules/BaseTOFTStrategyModule.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol#L2-L2

File: contracts/Vesting.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L2-L2

File: contracts/option-airdrop/AirdropBroker.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L2-L2

File: contracts/option-airdrop/aoTAP.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L2-L2

File: contracts/options/TapiocaOptionBroker.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L2-L2

File: contracts/options/TapiocaOptionLiquidityProvision.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L2-L2

File: contracts/options/oTAP.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/oTAP.sol#L2-L2

File: contracts/tokens/BaseTapOFT.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L2-L2

File: contracts/tokens/LTap.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L2-L2

File: contracts/tokens/TapOFT.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L2-L2

File: contracts/twAML.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/twAML.sol#L2-L2

File: contracts/Magnetar/MagnetarV2.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L2-L2

File: contracts/Magnetar/MagnetarV2Storage.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2Storage.sol#L2-L2

File: contracts/Magnetar/modules/MagnetarMarketModule.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L2-L2

File: contracts/Multicall/Multicall3.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Multicall/Multicall3.sol#L2-L2

File: contracts/Swapper/BaseSwapper.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol#L2-L2

File: contracts/Swapper/CurveSwapper.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol#L2-L2

File: contracts/Swapper/UniswapV2Swapper.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol#L2-L2

File: contracts/Swapper/UniswapV3Swapper.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L2-L2

File: contracts/TapiocaDeployer/TapiocaDeployer.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/TapiocaDeployer/TapiocaDeployer.sol#L2-L2

File: contracts/oracle/Seer.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/Seer.sol#L2-L2

File: contracts/oracle/implementations/ARBTriCryptoOracle.sol

2:   pragma solidity ^0.8.9;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol#L2-L2

File: contracts/oracle/implementations/GLPOracle.sol

2:   pragma solidity >=0.8.0;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/GLPOracle.sol#L2-L2

File: contracts/oracle/implementations/SGOracle.sol

2:   pragma solidity ^0.8.9;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/SGOracle.sol#L2-L2

File: contracts/aave/AaveStrategy.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L2-L2

File: contracts/balancer/BalancerStrategy.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L2-L2

File: contracts/compound/CompoundStrategy.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L2-L2

File: contracts/convex/ConvexTricryptoStrategy.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L2-L2

File: contracts/curve/TricryptoLPStrategy.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L2-L2

File: contracts/curve/TricryptoNativeStrategy.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L2-L2

File: contracts/glp/GlpStrategy.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L2-L2

File: contracts/lido/LidoEthStrategy.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L2-L2

File: contracts/stargate/StargateStrategy.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L2-L2

File: contracts/yearn/YearnStrategy.sol

2:   pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L2-L2

File: contracts/BoringMath.sol

2:   pragma solidity ^0.8.9;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/BoringMath.sol#L2-L2

File: contracts/NativeTokenFactory.sol

2:   pragma solidity ^0.8.9;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L2-L2

File: contracts/YieldBox.sol

24:  pragma solidity ^0.8.9;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L24-L24

File: contracts/YieldBoxPermit.sol

3:   pragma solidity ^0.8.0;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxPermit.sol#L3-L3

File: contracts/YieldBoxRebase.sol

3:   pragma solidity ^0.8.9;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxRebase.sol#L3-L3

File: contracts/YieldBoxURIBuilder.sol

2:   pragma solidity ^0.8.9;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxURIBuilder.sol#L2-L2

[L‑13] Consider implementing two-step procedure for updating protocol addresses

A copy-paste error or a typo may end up bricking protocol functionality, or sending tokens to an address with no known private key. Consider implementing a two-step procedure for updating protocol addresses, where the recipient is set as pending, and must 'accept' the assignment by making an affirmative call. A straight forward way of doing this would be to have the target contracts implement EIP-165, and to have the 'set' functions ensure that the recipient is of the right interface type.

There are 7 instances of this issue:

File: contracts/Penrose.sol

263      function setBigBangEthMarket(address _market) external onlyOwner {
264          bigBangEthMarket = _market;
265          emit BigBangEthMarketSet(_market);
266:     }

455      function setFeeTo(address feeTo_) external onlyOwner {
456          feeTo = feeTo_;
457          emit FeeToUpdate(feeTo_);
458:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L263-L266

File: contracts/option-airdrop/AirdropBroker.sol

308      function setTapOracle(
309          IOracle _tapOracle,
310          bytes calldata _tapOracleData
311      ) external onlyOwner {
312          tapOracle = _tapOracle;
313          tapOracleData = _tapOracleData;
314  
315          emit SetTapOracle(_tapOracle, _tapOracleData);
316:     }

357      function setPaymentTokenBeneficiary(
358          address _paymentTokenBeneficiary
359      ) external onlyOwner {
360          paymentTokenBeneficiary = _paymentTokenBeneficiary;
361:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L308-L316

File: contracts/options/TapiocaOptionBroker.sol

446      function setTapOracle(
447          IOracle _tapOracle,
448          bytes calldata _tapOracleData
449      ) external onlyOwner {
450          tapOracle = _tapOracle;
451          tapOracleData = _tapOracleData;
452  
453          emit SetTapOracle(_tapOracle, _tapOracleData);
454:     }

471      function setPaymentTokenBeneficiary(
472          address _paymentTokenBeneficiary
473      ) external onlyOwner {
474          paymentTokenBeneficiary = _paymentTokenBeneficiary;
475:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L446-L454

File: contracts/glp/GlpStrategy.sol

113      function setFeeRecipient(address recipient) external onlyOwner {
114          feeRecipient = recipient;
115:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L113-L115

[L‑14] Unsafe downcast

When a type is downcast to a smaller type, the higher order bits are truncated, effectively applying a modulo to the original value. Without any other checks, this wrapping will lead to unexpected behavior and bugs

There are 64 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

/// @audit uint64
521:          _accrueInfo.debtRate = uint64(annumDebtRate / 31536000); //per second

/// @audit uint64
523:          _accrueInfo.lastAccrued = uint64(block.timestamp);

/// @audit uint256 extraAmount -> uint128
535:          _totalBorrow.elastic += uint128(extraAmount);

/// @audit uint256 borrowAmount -> uint128
822:          totalBorrow.elastic -= uint128(borrowAmount);

/// @audit uint256 borrowPart -> uint128
823:          totalBorrow.base -= uint128(borrowPart);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L521

File: tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol

/// @audit uint64
79:           _accrueInfo.lastAccrued = uint64(block.timestamp);

/// @audit uint256 extraAmount -> uint128
104:          _totalBorrow.elastic += uint128(extraAmount);

/// @audit uint256 feeFraction -> uint128
108:          _accrueInfo.feesEarnedFraction += uint128(feeFraction);

/// @audit uint256 feeFraction -> uint128
109:          _totalAsset.base = _totalAsset.base + uint128(feeFraction);

/// @audit uint64
117               _accrueInfo.interestPerSecond = uint64(
118                   (uint256(_accrueInfo.interestPerSecond) * interestElasticity) /
119                       scale
120:              );

/// @audit uint256 newInterestPerSecond -> uint64
135:              _accrueInfo.interestPerSecond = uint64(newInterestPerSecond);

/// @audit uint256 fraction -> uint128
210:          if (_totalAsset.base + uint128(fraction) < 1000) {

/// @audit uint256 share -> uint128
238:          _totalAsset.elastic -= uint128(share);

/// @audit uint256 fraction -> uint128
239:          _totalAsset.base -= uint128(fraction);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol#L79

File: tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol

/// @audit uint256 share -> uint128
76:           _totalAsset.elastic -= uint128(share);

/// @audit uint256 share -> uint128
96:           totalAsset.elastic = totalShare + uint128(share);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol#L76

File: tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol

/// @audit uint256 allBorrowAmount -> uint128
154:          _totalBorrow.elastic -= uint128(allBorrowAmount);

/// @audit uint256 allBorrowPart -> uint128
155:          _totalBorrow.base -= uint128(allBorrowPart);

/// @audit uint128
195:          totalAsset.elastic += uint128(returnedShare - callerShare);

/// @audit uint256 borrowAmount -> uint128
266:          totalBorrow.elastic -= uint128(borrowAmount);

/// @audit uint256 borrowPart -> uint128
267:          totalBorrow.base -= uint128(borrowPart);

/// @audit uint128
284:          totalAsset.elastic += uint128(returnedShare - feeShare - callerShare);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L154

File: tapioca-bar-audit/contracts/markets/singularity/Singularity.sol

/// @audit uint64
117:          accrueInfo.interestPerSecond = uint64(startingInterestPerSecond); // 1% APR, with 1e18 being 100%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L117

File: tapioca-bar-audit/contracts/Penrose.sol

/// @audit uint96
104           tapAssetId = uint96(
105               _yieldBox.registerAsset(
106                   TokenType.ERC20,
107                   address(tapToken_),
108                   emptyStrategies[address(tapToken_)],
109                   0
110               )
111:          );

/// @audit uint96
122           wethAssetId = uint96(
123               _yieldBox.registerAsset(
124                   TokenType.ERC20,
125                   address(wethToken_),
126                   emptyStrategies[address(wethToken_)],
127                   0
128               )
129:          );

/// @audit uint96
302           usdoAssetId = uint96(
303               yieldBox.registerAsset(
304                   TokenType.ERC20,
305                   _usdoToken,
306                   emptyStrategies[_usdoToken],
307                   0
308               )
309:          );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L104-L111

File: tap-token-audit/contracts/governance/twTAP.sol

/// @audit uint256 expiry -> uint56
333:              expiry: uint56(expiry),

/// @audit uint256 _amount -> uint88
334:              tapAmount: uint88(_amount),

/// @audit uint256 multiplier -> uint24
335:              multiplier: uint24(multiplier),

/// @audit uint256 w0 -> uint40
336:              lastInactive: uint40(w0),

/// @audit uint256 w1 -> uint40
337:              lastActive: uint40(w1)

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L333

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

/// @audit uint64
287:          lastEpochUpdate = uint64(block.timestamp);

/// @audit uint256 _epochTAPValuation -> uint128
292:          epochTAPValuation = uint128(_epochTAPValuation);

/// @audit uint128
398:          uint128 expiry = uint128(lastEpochUpdate + EPOCH_DURATION); // Set expiry to the end of the epoch

/// @audit uint256 PHASE_1_DISCOUNT -> uint128
402:              uint128(PHASE_1_DISCOUNT),

/// @audit uint128
433:          uint128 expiry = uint128(lastEpochUpdate + EPOCH_DURATION); // Set expiry to the end of the epoch

/// @audit uint128
435:          uint128 discount = uint128(PHASE_2_DISCOUNT_PER_USER[_role]) * 1e4;

/// @audit uint256 _tokenID -> uint160
448:          address tokenIDToAddress = address(uint160(_tokenID));

/// @audit uint128
458:          uint128 expiry = uint128(lastEpochUpdate + EPOCH_DURATION); // Set expiry to the end of the epoch

/// @audit uint256 PHASE_3_DISCOUNT -> uint128
460:          uint128 discount = uint128(PHASE_3_DISCOUNT);

/// @audit uint128
473:          uint128 expiry = uint128(lastEpochUpdate + EPOCH_DURATION); // Set expiry to the end of the epoch

/// @audit uint256 PHASE_4_DISCOUNT -> uint128
477:              uint128(PHASE_4_DISCOUNT),

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L287

File: tap-token-audit/contracts/options/TapiocaOptionBroker.sol

/// @audit uint256 target -> uint128
282:              uint128(target),

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L282

File: tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol

/// @audit uint128
195:          lockPosition.lockTime = uint128(block.timestamp);

/// @audit uint256 sglAssetID -> uint128
196:          lockPosition.sglAssetID = uint128(sglAssetID);

/// @audit uint256 sglAssetID -> uint128
200:          emit Mint(_to, uint128(sglAssetID), lockPosition);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L195

File: tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol

/// @audit int128 -> int256
/// @audit int256
72:               int128(int256(tokenIndexes[0])),

/// @audit int128 -> int256
/// @audit int256
73:               int128(int256(tokenIndexes[1])),

/// @audit int128 -> int256
/// @audit int256
125:              int128(int256(tokenIndexes[0])),

/// @audit int128 -> int256
/// @audit int256
126:              int128(int256(tokenIndexes[1])),

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol#L72

File: tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol

/// @audit uint256 amountIn -> uint128
101:              uint128(amountIn),

/// @audit uint256 amountOut -> uint128
129:              uint128(amountOut),

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L101

File: tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol

/// @audit uint256 lpRouterPid -> uint16
202:              uint16(lpRouterPid),

/// @audit uint256 lpRouterPid -> uint16
254:                  uint16(lpRouterPid),

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L202

File: YieldBox/contracts/BoringMath.sol

/// @audit uint256 a -> uint128
7:            c = uint128(a);

/// @audit uint256 a -> uint64
12:           c = uint64(a);

/// @audit uint256 a -> uint32
17:           c = uint32(a);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/BoringMath.sol#L7

File: YieldBox/contracts/YieldBoxURIBuilder.sol

/// @audit uint160
37:                                       uint256(uint160(asset.contractAddress)).toHexString(20),

/// @audit uint160
90:                   abi.encodePacked("ERC1155:", uint256(uint160(asset.contractAddress)).toHexString(20), "/", asset.tokenId.toString())

/// @audit uint160
106:                  ? abi.encodePacked(',"tokenAddress":"', uint256(uint160(asset.contractAddress)).toHexString(20), '"')

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxURIBuilder.sol#L37

[L‑15] Loss of precision

Division by large numbers may result in the result being zero, due to solidity not supporting fractions. Consider requiring a minimum amount for the numerator to ensure that it is always larger than the denominator

There are 121 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

187           uint256 _maxDebtPoint = (_ethMarketTotalDebt *
188:              debtRateAgainstEthMarket) / 1e18;

192           uint256 debtPercentage = ((_currentDebt - debtStartPoint) *
193:              DEBT_PRECISION) / (_maxDebtPoint - debtStartPoint);

194           uint256 debt = ((maxDebtRate - minDebtRate) * debtPercentage) /
195:              DEBT_PRECISION +

521:          _accrueInfo.debtRate = uint64(annumDebtRate / 31536000); //per second

531               (uint256(_totalBorrow.elastic) *
532                   _accrueInfo.debtRate *
533                   elapsedTime) /
534:              1e18;

645:          feeShare = (extraShare * protocolFee) / FEE_PRECISION; // x% of profit goes to fee.

646:          callerShare = (extraShare * callerReward) / FEE_PRECISION; //  y%  of profit goes to caller.

747:          uint256 feeAmount = (amount * borrowOpeningFee) / FEE_PRECISION; // A flat % fee is charged for any borrow

781           uint256 collateralPartInAsset = (yieldBox.toAmount(
782               collateralId,
783               userCollateralShare[user],
784               false
785:          ) * EXCHANGE_RATE_PRECISION) / _exchangeRate;

809               (borrowAmount * liquidationMultiplier) /
810:              FEE_PRECISION;

813:              (amountWithBonus * _exchangeRate) / EXCHANGE_RATE_PRECISION,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L187-L188

File: tapioca-bar-audit/contracts/markets/Market.sol

265:              borrowPartScaled = borrowPart / (10 ** (borrowPartDecimals - 18));

274                   collateralPartInAsset /
275:                  (10 ** (collateralPartDecimals - 18));

283           uint256 liquidationStartsAt = (collateralPartInAssetScaled *
284:              collateralizationRate) / (10 ** ratesPrecision);

288               ((collateralizationRate * collateralPartInAssetScaled) /
289:                  (10 ** ratesPrecision));

291               (collateralizationRate *
292                   ((10 ** ratesPrecision) + liquidationMultiplier)) /
293:              (10 ** ratesPrecision)) * (10 ** (18 - ratesPrecision));

295:          uint256 x = (numerator * 1e18) / denominator;

323:          borrowPart = (borrowPart * _totalBorrow.elastic) / _totalBorrow.base;

390               yieldBox.toAmount(
391                   collateralId,
392                   (userCollateralShare[user] *
393                       (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *
394                       collateralizationRate),
395                   false
396               ) /
397:              _exchangeRate;

393:                      (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *

418:                      (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *

423               (borrowPart * _totalBorrow.elastic * _exchangeRate) /
424:                  _totalBorrow.base;

438:          max = (collateralAmount * EXCHANGE_RATE_PRECISION) / _exchangeRate;

439:          min = (max * collateralizationRate) / FEE_PRECISION;

453           uint256 rewardPercentage = ((borrowed - startTVLInAsset) *
454:              FEE_PRECISION) / (maxTVLInAsset - startTVLInAsset);

457           int256 reward = (diff * int256(rewardPercentage)) /
458:              int256(FEE_PRECISION) +

477:          return (shareRatio * userCollateralShare[user]) / (10 ** assetDecimals);

489:          uint256 _quotient = ((_numerator / denominator) + 5) / 10;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L265

File: tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol

63                : (uint256(_totalBorrow.elastic) * UTILIZATION_PRECISION) /
64:                   fullAssetAmount;

100               (uint256(_totalBorrow.elastic) *
101                   _accrueInfo.interestPerSecond *
102                   elapsedTime) /
103:              1e18;

106:          uint256 feeAmount = (extraAmount * protocolFee) / FEE_PRECISION; // % of interest paid goes to fee

107:          feeFraction = (feeAmount * _totalAsset.base) / fullAssetAmount;

113               uint256 underFactor = ((minimumTargetUtilization - utilization) *
114:                  FACTOR_PRECISION) / minimumTargetUtilization;

118                   (uint256(_accrueInfo.interestPerSecond) * interestElasticity) /
119:                      scale

125               uint256 overFactor = ((utilization - maximumTargetUtilization) *
126:                  FACTOR_PRECISION) / fullUtilizationMinusMax;

129               uint256 newInterestPerSecond = (uint256(
130                   _accrueInfo.interestPerSecond
131:              ) * scale) / interestElasticity;

209:              : (share * _totalAsset.base) / allShare;

235:          share = (fraction * allShare) / _totalAsset.base;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol#L63-L64

File: tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol

63:           uint256 feeAmount = (amount * borrowOpeningFee) / FEE_PRECISION; // A flat % fee is charged for any borrow

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol#L63

File: tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol

81            uint256 collateralAmountInAsset = yieldBox.toAmount(
82                collateralId,
83                (collateralShare *
84                    (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *
85                    lqCollateralizationRate),
86                false
87:           ) / _exchangeRate;

84:                   (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *

89:           borrowPart = (borrowPart * _totalBorrow.elastic) / _totalBorrow.base;

126                       (borrowAmount * liquidationMultiplier) /
127:                      FEE_PRECISION;

130:                      (amountWithBonus * _exchangeRate) / EXCHANGE_RATE_PRECISION,

182:          uint256 callerShare = (extraShare * callerFee) / FEE_PRECISION; // 1% goes to caller

216           uint256 collateralPartInAsset = (yieldBox.toAmount(
217               collateralId,
218               userCollateralShare[user],
219               false
220:          ) * EXCHANGE_RATE_PRECISION) / _exchangeRate;

236                   (availableBorrowPart * liquidationBonusAmount) /
237:                  FEE_PRECISION;

253               (borrowAmount * liquidationMultiplier) /
254:              FEE_PRECISION;

257:              (amountWithBonus * _exchangeRate) / EXCHANGE_RATE_PRECISION,

278:          feeShare = (extraShare * protocolFee) / FEE_PRECISION; // x% of profit goes to fee.

279:          callerShare = (extraShare * callerReward) / FEE_PRECISION; //  y%  of profit goes to caller.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L81-L87

File: tapioca-bar-audit/contracts/markets/singularity/Singularity.sol

157:          share = (amount * allShare) / totalAsset.base;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L157

File: tapioca-bar-audit/contracts/usd0/USDO.sol

69:           return (amount * flashMintFee) / FLASH_MINT_FEE_PRECISION;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/USDO.sol#L69

File: tapiocaz-audit/contracts/Balancer.sol

339:          return _amount - ((_amount * _slippage) / SLIPPAGE_PRECISION);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L339

File: tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol

57:               _decimal / 2,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol#L57

File: tap-token-audit/contracts/governance/twTAP.sol

151:          return (block.timestamp - creation) / EPOCH_DURATION;

236:              result[i] = ((votes * net) / DIST_PRECISION) - claimed[_tokenId][i];

280                   (pool.averageMagnitude + magnitude) /
281:                  pool.totalParticipants; // compute new average magnitude

323:          uint256 w1 = (expiry - creation) / EPOCH_DURATION;

446               (_amount * DIST_PRECISION) /
447:              uint256(totals.netActiveVotes);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L151

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

530:          uint256 rawPaymentAmount = _otcAmountInUSD / _paymentTokenValuation;

535:          paymentAmount = paymentAmount / (10 ** (18 - _paymentTokenDecimals));

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L530

File: tap-token-audit/contracts/options/TapiocaOptionBroker.sol

245                   (pool.averageMagnitude + magnitude) /
246:                  pool.totalParticipants; // compute new average magnitude

551:          uint256 rawPaymentAmount = _otcAmountInUSD / _paymentTokenValuation;

555:          paymentAmount = paymentAmount / (10 ** (18 - _paymentTokenDecimals));

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L245-L246

File: tap-token-audit/contracts/tokens/TapOFT.sol

242:          return ((timestamp - emissionsStartTime) / WEEK) + 1; // Starts at week 1

254:          result = (dso_supply * decay_rate) / DECAY_RATE_DECIMAL;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L242

File: tap-token-audit/contracts/twAML.sol

120:          return mul >= 1e4 ? mul / 1e4 : _totalWeight;

141:          uint256 target = (_magnitude * _dMax) / _cumulative;

150:              uint256 x = y / 2 + 1;

153:                  x = (y / x + x) / 2;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/twAML.sol#L120

File: tap-token-audit/contracts/Vesting.sol

172:          return (total * (block.timestamp - start)) / duration;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L172

File: tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol

105                   (borrowAmount *
106                       market.liquidationMultiplier() *
107                       market.exchangeRate()) /
108:                      (liquidationMultiplierPrecision * exchangeRatePrecision),

161:                  (fraction * totalAssetElastic) / totalAssetBase,

186:          fraction = allShare == 0 ? share : (share * totalAssetBase) / allShare;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L105-L108

File: tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol

127:              ? (_wbtcPrice * _btcPrice) / 1e18

132:          _maxPrice = (3 * _vp * FixedPointMathLib.cbrt(_basePrices)) / 1 ether;

135:          uint256 _g = (TRI_CRYPTO.gamma() * 1 ether) / GAMMA0;

136:          uint256 _a = (TRI_CRYPTO.A() * 1 ether) / A0;

137:          uint256 _discount = Math.max((_g ** 2 / 1 ether) * _a, 1e34); // handle qbrt nonconvergence

139:          _discount = (FixedPointMathLib.sqrt(_discount) * DISCOUNT0) / 1 ether;

141:          _maxPrice -= (_maxPrice * _discount) / 1 ether;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol#L127

File: tapioca-periph-audit/contracts/oracle/implementations/SGOracle.sol

50            uint256 lpPrice = (SG_POOL.totalLiquidity() *
51:               uint256(UNDERLYING.latestAnswer())) / SG_POOL.totalSupply();

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/SGOracle.sol#L50-L51

File: tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol

113:              result = result - (result * 50) / 10_000; //0.5%

193:              uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L113

File: tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol

122:          toWithdraw = toWithdraw - (toWithdraw * 50) / 10_000; //0.5%

177:          bptOut = bptOut - (bptOut * 50) / 10_000; //0.5%

202               uint256 toWithdraw = (((amount - queued) * (10 ** decimals)) /
203:                  pricePerShare);

250:          bptIn = bptIn + (bptIn * 250) / 10_000; //2.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L122

File: tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol

116:          uint256 invested = (shares * pricePerShare) / (10 ** 18);

146               uint256 toWithdraw = (((amount - queued) * (10 ** 18)) /
147:                  pricePerShare);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L116

File: tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol

143:              result = result - (result * 50) / 10_000; //0.5%

154:          uint256 minAmount = (calcWithdraw * 50) / 10_000; //0.5%

207:                  uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

313:              uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

336:              uint256 minAmount = calcWithdraw - (calcWithdraw * 50) / 10_000; //0.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L143

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol

179:                  uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

186:                  minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L179

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol

116:              result = result - (result * 50) / 10_000; //0.5%

170:                  uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

188:          uint256 minAmount = calcWithdraw - (calcWithdraw * 50) / 10_000; //0.5%

232:              uint256 minAmount = calcWithdraw - (calcWithdraw * 50) / 10_000; //0.5%

249:          uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L116

File: tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol

171:              uint256 fee = (wethAmount * FEE_BPS) / 10_000;

207           uint256 minTokenReserve = ((vestingNow + vestable) * avgTokenStake) /
208:              totalVestable;

244                   (totalVestable * tokenAvailable) /
245:                  avgTokenStake -

310:          uint256 buffer = (freeEsGmx + stakedEsGmx) / 20;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L171

File: tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol

108:          uint256 minAmount = (toWithdraw * 50) / 10_000; //0.5%

151:              uint256 minAmount = toWithdraw - (toWithdraw * 250) / 10_000; //2.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L108

File: tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol

133:              result = result - (result * 50) / 10_000; //0.5%

182:                  uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L133

File: tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol

114:          uint256 invested = (shares * pricePerShare) / (10 ** vault.decimals());

142               uint256 toWithdraw = (((amount - queued) *
143:                  (10 ** vault.decimals())) / pricePerShare);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L114

File: YieldBox/contracts/BoringMath.sol

26:           result = (value * mul) / div;

27:           if (roundUp && (result * div) / mul < value) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/BoringMath.sol#L26

File: YieldBox/contracts/YieldBoxRebase.sol

32:           share = (amount * totalShares_) / totalAmount;

35:           if (roundUp && (share * totalAmount) / totalShares_ < amount) {

55:           amount = (share * totalAmount) / totalShares_;

58:           if (roundUp && (amount * totalShares_) / totalAmount < share) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxRebase.sol#L32

[L‑16] Array lengths not checked

If the length of the arrays are not required to be of the same length, user operations may not be fully executed due to a mismatch in the number of items iterated over, versus the number of items provided in the second array

There are 9 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

309       function liquidate(
310           address[] calldata users,
311           uint256[] calldata maxBorrowParts,
312           ISwapper swapper,
313           bytes calldata collateralToAssetSwapData
314:      ) external notPaused {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L309-L314

File: tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol

29        function liquidate(
30            address[] calldata users,
31            uint256[] calldata maxBorrowParts,
32            ISwapper swapper,
33            bytes calldata collateralToAssetSwapData,
34            bytes calldata usdoToBorrowedSwapData
35:       ) external notPaused {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L29-L35

File: tapioca-bar-audit/contracts/markets/singularity/Singularity.sol

440       function liquidate(
441           address[] calldata users,
442           uint256[] calldata maxBorrowParts,
443           ISwapper swapper,
444           bytes calldata collateralToAssetSwapData,
445:          bytes calldata usdoToBorrowedSwapData

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L440-L445

File: tapioca-bar-audit/contracts/Penrose.sol

424       function executeMarketFn(
425           address[] calldata mc,
426           bytes[] memory data,
427           bool forceSuccess
428       )
429           external
430           onlyOwner
431           notPaused
432:          returns (bool[] memory success, bytes[] memory result)

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L424-L432

File: tap-token-audit/contracts/tokens/BaseTapOFT.sol

163       function claimRewards(
164           address to,
165           uint256 tokenID,
166           address[] memory rewardTokens,
167           uint16 lzDstChainId,
168           address zroPaymentAddress,
169           bytes calldata adapterParams,
170:          IRewardClaimSendFromParams[] calldata rewardClaimSendParams

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L163-L170

File: YieldBox/contracts/NativeTokenFactory.sol

127:      function batchMint(uint256 tokenId, address[] calldata tos, uint256[] calldata amounts) public onlyOwner(tokenId) {

138:      function batchBurn(uint256 tokenId, address[] calldata froms, uint256[] calldata amounts) public {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L127

File: YieldBox/contracts/YieldBox.sol

307:      function batchTransfer(address from, address to, uint256[] calldata assetIds_, uint256[] calldata shares_) public {

336:      function transferMultiple(address from, address[] calldata tos, uint256 assetId, uint256[] calldata shares) public allowed(from, assetId) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L307

[L‑17] Empty receive()/payable fallback() function does not authorize requests

If the intention is for the Ether to be used, the function should call another function, otherwise it should revert (e.g. require(msg.sender == address(weth))). 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. If the concern is having to spend a small amount of gas to check the sender against an immutable address, the code should at least have a function to rescue unused Ether.

There are 10 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/singularity/Singularity.sol

644:      receive() external payable {}

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L644

File: tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol

68:       receive() external payable {}

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol#L68

File: tapiocaz-audit/contracts/Balancer.sol

342:      receive() external payable {}

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L342

File: tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol

43:       receive() external payable {}

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol#L43

File: tap-token-audit/contracts/tokens/BaseTapOFT.sol

330:      receive() external payable virtual {}

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L330

File: tapioca-periph-audit/contracts/Magnetar/MagnetarV2Storage.sol

340:      receive() external payable virtual {}

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2Storage.sol#L340

File: tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol

301:      receive() external payable {}

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L301

File: tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol

164:      receive() external payable {}

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L164

File: tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol

169:      receive() external payable {}

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L169

File: tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol

271:      receive() external payable {}

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L271

[L‑18] Draft imports may break in new minor versions

While OpenZeppelin draft contracts are safe to use and have been audited, their 'draft' status means that the EIPs they're based on are not finalized, and thus there may be breaking changes in even minor releases. If a bug is found in this version of OpenZeppelin, and the version that you're forced to upgrade to has breaking changes in the new version, you'll encounter unnecessary delays in porting and testing replacement contracts. Ensure that you have extensive test coverage of this area so that differences can be automatically detected, and have a plan in place for how you would fully test a new version of these contracts if they do indeed change unexpectedly. Consider creating a forked version of the file rather than importing it from the package, and manually patch your fork as changes are made.

There are 7 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/MarketERC20.sol

5:    import {IERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L5

File: tapioca-bar-audit/contracts/usd0/BaseUSDO.sol

9:    import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDO.sol#L9

File: tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol

9:    import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol#L9

File: tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol

9:    import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol#L9

File: tap-token-audit/contracts/tokens/BaseTapOFT.sol

5:    import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L5

File: tap-token-audit/contracts/tokens/LTap.sol

5:    import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L5

File: tap-token-audit/contracts/tokens/TapOFT.sol

4:    import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L4

[L‑19] Functions calling contracts/addresses with transfer hooks are missing reentrancy guards

Even if the function follows the best practice of check-effects-interaction, not using a reentrancy guard when there may be transfer hooks will open the users of this protocol up to read-only reentrancies with no way to protect against it, except by block-listing the whole protocol.

There are 8 instances of this issue:

File: contracts/tOFT/mTapiocaOFT.sol

/// @audit `extractUnderlying()`
148:             IERC20(erc20).safeTransfer(msg.sender, _amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol#L148-L148

File: contracts/governance/twTAP.sol

/// @audit `distributeReward()`
448:         rewardToken.safeTransferFrom(msg.sender, address(this), _amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L448-L448

File: contracts/option-airdrop/AirdropBroker.sol

/// @audit `collectPaymentTokens()`
377:                 paymentToken.transfer(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L377-L377

File: contracts/options/TapiocaOptionBroker.sol

/// @audit `collectPaymentTokens()`
491:                 paymentToken.transfer(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L491-L491

File: contracts/Swapper/CurveSwapper.sol

/// @audit `swap()`
140:             IERC20(tokenOut).safeTransfer(to, amountOut);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol#L140-L140

File: contracts/YieldBox.sol

/// @audit `depositAsset()`
151:                 IERC1155(asset.contractAddress).safeTransferFrom(from, address(asset.strategy), asset.tokenId, amount, "");

/// @audit `depositAsset()`
144:             IERC20(asset.contractAddress).safeTransferFrom(from, address(asset.strategy), amount);

/// @audit `depositNFTAsset()`
181:         IERC721(asset.contractAddress).safeTransferFrom(from, address(asset.strategy), asset.tokenId);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L151-L151

[L‑20] Use Ownable2Step rather than Ownable

Ownable2Step and Ownable2StepUpgradeable prevent the contract ownership from mistakenly being transferred to an address that cannot handle it (e.g. due to a typo in the address), by requiring that the recipient of the owner permissions actively accept via a contract call of its own.

There are 4 instances of this issue:

File: tapiocaz-audit/contracts/TapiocaWrapper.sol

26    contract TapiocaWrapper is Ownable {
27        struct ExecutionCall {
28            address toft;
29            bytes bytecode;
30:           bool revertOnFailure;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L26-L30

File: tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol

30:   contract MagnetarV2 is Ownable, MagnetarV2Storage {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L30

File: tapioca-periph-audit/contracts/Multicall/Multicall3.sol

22    contract Multicall3 is Ownable {
23        struct Call {
24            address target;
25            bool allowFailure;
26:           bytes callData;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Multicall/Multicall3.sol#L22-L26

File: tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol

11:   abstract contract BaseSwapper is Ownable, ReentrancyGuard, ISwapper {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol#L11

[L‑21] addRewardToken() does note remove old entries before adding new ones

Each time addRewardToken() is called, new entries are added to the array, but doing so does not remove any old entries. By calling the function multiple times, an attacker can can increase their voting power indefinitely, without having to acquire new tokens.

There are 2 instances of this issue:

File: contracts/governance/twTAP.sol

455      function addRewardToken(IERC20 token) external onlyOwner returns (uint256) {
456          uint256 i = rewardTokens.length;
457          rewardTokens.push(token);
458          rewardTokenIndex[token] = i;
459          return i;
460:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L455-L460

File: contracts/options/TapiocaOptionLiquidityProvision.sol

280      ) external onlyOwner updateTotalSGLPoolWeights {
281          require(assetID > 0, "tOLP: invalid asset ID");
282          require(
283              activeSingularities[singularity].sglAssetID == 0,
284              "tOLP: already registered"
285          );
286  
287          activeSingularities[singularity].sglAssetID = assetID;
288          activeSingularities[singularity].poolWeight = weight > 0 ? weight : 1;
289          sglAssetIDToAddress[assetID] = singularity;
290          singularities.push(assetID);
291  
292          emit RegisterSingularity(address(singularity), assetID);
293:     }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L280-L293

[L‑22] Signature use at deadlines should be allowed

According to EIP-2612, signatures used on exactly the deadline timestamp are supposed to be allowed. While the signature may or may not be used for the exact EIP-2612 use case (transfer approvals), for consistency's sake, all deadlines should follow this semantic. If the timestamp is an expiration rather than a deadline, consider whether it makes more sense to include the expiration timestamp as a valid timestamp, as is done for deadlines.

There are 3 instances of this issue:

File: contracts/governance/twTAP.sol

159:         if (participant.expiry < block.timestamp) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L159-L159

File: contracts/option-airdrop/AirdropBroker.sol

158:         require(aoTapOption.expiry > block.timestamp, "adb: Option expired");

233:         require(aoTapOption.expiry > block.timestamp, "adb: Option expired");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L158-L158

[L‑23] NFT doesn't handle hard forks

When there are hard forks, users often have to go through many hoops to ensure that they control ownership on every fork. Consider adding require(1 == chain.chainId), or the chain ID of whichever chain you prefer, to the functions below, or at least include the chain ID in the URI, so that there is no confusion about which chain is the owner of the NFT.

There are 2 instances of this issue:

File: contracts/option-airdrop/aoTAP.sol

68       function tokenURI(
69           uint256 _tokenId
70       ) public view override returns (string memory) {
71           return tokenURIs[_tokenId];
72:      }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L68-L72

File: contracts/options/oTAP.sol

54       function tokenURI(
55           uint256 _tokenId
56       ) public view override returns (string memory) {
57           return tokenURIs[_tokenId];
58:      }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/oTAP.sol#L54-L58

[L‑24] decimals() is not a part of the ERC-20 standard

The decimals() function is not a part of the ERC-20 standard, and was added later as an optional extension. As such, some valid ERC20 tokens do not support this interface, so it is unsafe to blindly cast all tokens to this interface, and then call this function.

There are 4 instances of this issue:

File: contracts/option-airdrop/AirdropBroker.sol

189:             _paymentToken.decimals()

506:             _paymentToken.decimals()

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L189-L189

File: contracts/options/TapiocaOptionBroker.sol

202:             _paymentToken.decimals()

527:             _paymentToken.decimals()

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L202-L202

[L‑25] tokenURI() does not follow EIP-721

The EIP states that tokenURI() "Throws if _tokenId is not a valid NFT", which the code below does not do. If the NFT has not yet been minted, tokenURI() should revert

There are 2 instances of this issue:

File: contracts/option-airdrop/aoTAP.sol

68       function tokenURI(
69           uint256 _tokenId
70       ) public view override returns (string memory) {
71           return tokenURIs[_tokenId];
72:      }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L68-L72

File: contracts/options/oTAP.sol

54       function tokenURI(
55           uint256 _tokenId
56       ) public view override returns (string memory) {
57           return tokenURIs[_tokenId];
58:      }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/oTAP.sol#L54-L58

[L‑26] Open TODOs

Code architecture, incentives, and error handling/reporting questions/issues should be resolved before deployment

There are 10 instances of this issue:

File: tap-token-audit/contracts/governance/twTAP.sol

233:              //    (TODO: Word better?)

289:                  // TODO: Strongly suspect this is never less. Prove it.

347:          // TODO: Mint event?

398:          // TODO: Make whole function unchecked

411:              // TODO: Prove that math is safe

444:          // TODO: Word this better

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L233

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol

200:          // uint256 compoundAmount = compoundAmount();//TODO: not view

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L200

File: tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol

238:              // (TODO: Check that the multiplication does not overflow!)

241:              // (TODO: Check edge case where the average calculation drops to

331:          // TODO: Check the cast?

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L238

[L‑27] Calls to _get() will revert when totalSupply() returns zero

totalSupply() being zero will result in a division by zero, causing the transaction to fail. The function should instead special-case this scenario, and avoid reverting.

There is one instance of this issue:

File: contracts/oracle/implementations/SGOracle.sol

/// @audit _get()
50           uint256 lpPrice = (SG_POOL.totalLiquidity() *
51:              uint256(UNDERLYING.latestAnswer())) / SG_POOL.totalSupply();

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/SGOracle.sol#L50-L51

[L‑28] latestAnswer() is deprecated

Use latestRoundData() instead so that you can tell whether the answer is stale or not. The latestAnswer() function returns zero if it is unable to fetch data, which may be the case if ChainLink stops supporting this API. The API and its deprecation message no longer even appear on the ChainLink website, so it is dangerous to continue using it.

There are 5 instances of this issue:

File: tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol

121:          uint256 _btcPrice = uint256(BTC_FEED.latestAnswer()) * 1e10;

122:          uint256 _wbtcPrice = uint256(WBTC_FEED.latestAnswer()) * 1e10;

123:          uint256 _ethPrice = uint256(ETH_FEED.latestAnswer()) * 1e10;

124:          uint256 _usdtPrice = uint256(USDT_FEED.latestAnswer()) * 1e10;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol#L121

File: tapioca-periph-audit/contracts/oracle/implementations/SGOracle.sol

51:               uint256(UNDERLYING.latestAnswer())) / SG_POOL.totalSupply();

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/SGOracle.sol#L51

[L‑29] safeApprove() is deprecated

Deprecated in favor of safeIncreaseAllowance() and safeDecreaseAllowance(). If only setting the initial allowance to the value that means infinite, safeIncreaseAllowance() can be used instead. The function may currently work, but if a bug is found in this version of OpenZeppelin, and the version that you're forced to upgrade to no longer has this function, you'll encounter unnecessary delays in porting and testing replacement contracts.

There is one instance of this issue:

File: tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol

172:          TransferHelper.safeApprove(tokenIn, address(swapRouter), amountIn);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L172

[L‑30] Use of a single-step ownership transfer

The existing transferOwnership function immediately transfers ownership to the new addres. Consider implementing a two-step variant, where the 'acceptor' of the ownership must call a separate function in order for the transfer to take effect. This can help to prevent mistakes where the wrong address is used, and ownership is irrecoverably lost.

There is one instance of this issue:

File: contracts/NativeTokenFactory.sol

56       function transferOwnership(uint256 tokenId, address newOwner, bool direct, bool renounce) public onlyOwner(tokenId) {
57           if (direct) {
58               // Checks
59               require(newOwner != address(0) || renounce, "NTF: zero address");
60   
61               // Effects
62               emit OwnershipTransferred(tokenId, owner[tokenId], newOwner);
63               owner[tokenId] = newOwner;
64               pendingOwner[tokenId] = address(0);
65           } else {
66               // Effects
67               pendingOwner[tokenId] = newOwner;
68           }
69:      }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L56-L69

Non-critical Issues

[N‑01] Events are missing sender information

When an action is triggered based on a user's action, not being able to filter based on who triggered the action makes event processing a lot more cumbersome. Including the msg.sender the events of these types of action will make events much more useful to end users, especially when msg.sender is not tx.origin.

There are 21 instances of this issue:

see instances
File: contracts/Penrose.sol

274:         emit PausedUpdated(paused, val);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L274-L274

File: contracts/markets/Market.sol

248:         emit PausedUpdated(paused, val);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L248-L248

File: contracts/markets/MarketERC20.sol

185:         emit Transfer(from, to, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L185-L185

File: contracts/markets/bigBang/BigBang.sol

587:         emit LogRemoveCollateral(user, address(swapper), collateralShare);

588:         emit LogRepay(address(swapper), user, borrowAmount, borrowPart);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L587-L587

File: contracts/markets/singularity/SGLLiquidation.sol

134                  emit LogRemoveCollateral(
135                      user,
136                      address(liquidationQueue),
137                      collateralShare
138:                 );

139                  emit LogRepay(
140                      address(liquidationQueue),
141                      user,
142                      borrowAmount,
143                      borrowPart
144:                 );

196          emit LogAddAsset(
197              address(liquidationQueue),
198              address(this),
199              returnedShare - callerShare,
200              0
201:         );

286          emit LogAddAsset(
287              swapper,
288              address(this),
289              extraShare - feeShare - callerShare,
290              0
291:         );

321:         emit LogRemoveCollateral(user, address(swapper), collateralShare);

322:         emit LogRepay(address(swapper), user, borrowAmount, borrowPart);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L134-L138

File: contracts/usd0/BaseUSDO.sol

117:         emit PausedUpdated(paused, val);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDO.sol#L117-L117

File: contracts/usd0/USDO.sol

112:         emit Minted(_to, _amount);

121:         emit Burned(_from, _amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/USDO.sol#L112-L112

File: contracts/governance/twTAP.sol

301              emit AMLDivergence(
302                  pool.cumulative,
303                  pool.averageMagnitude,
304                  pool.totalParticipants
305:             );

346:         emit Participate(_participant, _amount, multiplier);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L301-L305

File: contracts/options/TapiocaOptionBroker.sol

264              emit AMLDivergence(
265                  epoch,
266                  pool.cumulative,
267                  pool.averageMagnitude,
268                  pool.totalParticipants
269:             ); // Register new voting power event

285          emit Participate(
286              epoch,
287              lock.sglAssetID,
288              pool.totalDeposited,
289              lock,
290              target
291:         );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L264-L269

File: contracts/options/TapiocaOptionLiquidityProvision.sol

200:         emit Mint(_to, uint128(sglAssetID), lockPosition);

249:         emit Burn(_to, lockPosition.sglAssetID, lockPosition);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L200-L200

File: contracts/NativeTokenFactory.sol

80:          emit OwnershipTransferred(tokenId, owner[tokenId], _pendingOwner);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L80-L80

[N‑02] Variables need not be initialized to zero

The default value for variables is zero, so initializing them to zero is superfluous.

There are 129 instances of this issue:

see instances
File: contracts/Penrose.sol

437:         for (uint256 i = 0; i < len; ) {

492:             for (uint256 i = 0; i < length; ) {

512:         uint256 amount = 0;

546:         uint256 marketsLength = 0;

550:             for (uint256 i = 0; i < _masterContractLength; ) {

569:                 for (uint256 j = 0; j < clonesOfLength; ) {

564:             for (uint256 i = 0; i < _masterContractLength; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L437-L437

File: contracts/markets/bigBang/BigBang.sol

215:         for (uint256 i = 0; i < calls.length; i++) {

527:         uint256 extraAmount = 0;

603:         uint256 minAssetMount = 0;

665:         uint256 liquidatedCount = 0;

666:         for (uint256 i = 0; i < users.length; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L215-L215

File: contracts/markets/singularity/SGLLiquidation.sol

44:                  uint256 needed = 0;

45:                  for (uint256 i = 0; i < maxBorrowParts.length; i++) {

107:         for (uint256 i = 0; i < users.length; i++) {

337:         uint256 minAssetAmount = 0;

383:         uint256 liquidatedCount = 0;

384:         for (uint256 i = 0; i < users.length; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L44-L44

File: contracts/markets/singularity/Singularity.sol

187:         for (uint256 i = 0; i < calls.length; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L187-L187

File: contracts/usd0/modules/USDOLeverageModule.sol

255:         for (uint256 i = 0; i < approvals.length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L255-L255

File: contracts/usd0/modules/USDOMarketModule.sol

244:         for (uint256 i = 0; i < approvals.length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol#L244-L244

File: contracts/usd0/modules/USDOOptionsModule.sol

245:         for (uint256 i = 0; i < approvals.length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol#L245-L245

File: contracts/Penrose.sol

437:         for (uint256 i = 0; i < len; ) {

492:             for (uint256 i = 0; i < length; ) {

512:         uint256 amount = 0;

546:         uint256 marketsLength = 0;

550:             for (uint256 i = 0; i < _masterContractLength; ) {

569:                 for (uint256 j = 0; j < clonesOfLength; ) {

564:             for (uint256 i = 0; i < _masterContractLength; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L437-L437

File: contracts/markets/bigBang/BigBang.sol

215:         for (uint256 i = 0; i < calls.length; i++) {

527:         uint256 extraAmount = 0;

603:         uint256 minAssetMount = 0;

665:         uint256 liquidatedCount = 0;

666:         for (uint256 i = 0; i < users.length; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L215-L215

File: contracts/markets/singularity/SGLLiquidation.sol

44:                  uint256 needed = 0;

45:                  for (uint256 i = 0; i < maxBorrowParts.length; i++) {

107:         for (uint256 i = 0; i < users.length; i++) {

337:         uint256 minAssetAmount = 0;

383:         uint256 liquidatedCount = 0;

384:         for (uint256 i = 0; i < users.length; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L44-L44

File: contracts/markets/singularity/Singularity.sol

187:         for (uint256 i = 0; i < calls.length; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L187-L187

File: contracts/usd0/modules/USDOLeverageModule.sol

255:         for (uint256 i = 0; i < approvals.length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L255-L255

File: contracts/usd0/modules/USDOMarketModule.sol

244:         for (uint256 i = 0; i < approvals.length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol#L244-L244

File: contracts/usd0/modules/USDOOptionsModule.sol

245:         for (uint256 i = 0; i < approvals.length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol#L245-L245

File: contracts/TapiocaWrapper.sol

98:          for (uint256 i = 0; i < harvestableTapiocaOFTs.length; i++) {

140:         for (uint256 i = 0; i < _call.length; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L98-L98

File: contracts/tOFT/modules/BaseTOFTLeverageModule.sol

285:         for (uint256 i = 0; i < approvals.length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L285-L285

File: contracts/tOFT/modules/BaseTOFTMarketModule.sol

261:         for (uint256 i = 0; i < approvals.length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L261-L261

File: contracts/tOFT/modules/BaseTOFTOptionsModule.sol

260:         for (uint256 i = 0; i < approvals.length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol#L260-L260

File: contracts/TapiocaWrapper.sol

98:          for (uint256 i = 0; i < harvestableTapiocaOFTs.length; i++) {

140:         for (uint256 i = 0; i < _call.length; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L98-L98

File: contracts/tOFT/modules/BaseTOFTLeverageModule.sol

285:         for (uint256 i = 0; i < approvals.length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L285-L285

File: contracts/tOFT/modules/BaseTOFTMarketModule.sol

261:         for (uint256 i = 0; i < approvals.length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L261-L261

File: contracts/tOFT/modules/BaseTOFTOptionsModule.sol

260:         for (uint256 i = 0; i < approvals.length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol#L260-L260

File: contracts/Vesting.sol

29:      uint256 public seeded = 0;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L29-L29

File: contracts/governance/twTAP.sol

196:         for (uint256 i = 0; i < len; ) {

413:             for (uint256 i = 0; i < len; ) {

487:             for (uint256 i = 0; i < len; ++i) {

507:             for (uint256 i = 0; i < len; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L196-L196

File: contracts/option-airdrop/AirdropBroker.sol

336:             for (uint256 i = 0; i < _users.length; i++) {

332:             for (uint256 i = 0; i < _users.length; i++) {

375:             for (uint256 i = 0; i < len; ++i) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L336-L336

File: contracts/options/TapiocaOptionBroker.sol

489:             for (uint256 i = 0; i < len; ++i) {

565:             for (uint256 i = 0; i < len; ++i) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L489-L489

File: contracts/options/TapiocaOptionLiquidityProvision.sol

136:             for (uint256 i = 0; i < len; ++i) {

308:             for (uint256 i = 0; i < sglLength; i++) {

339:         for (uint256 i = 0; i < len; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L136-L136

File: contracts/tokens/BaseTapOFT.sol

228:             for (uint i = 0; i < len; ) {

333:         for (uint256 i = 0; i < approvals.length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L228-L228

File: contracts/governance/twTAP.sol

196:         for (uint256 i = 0; i < len; ) {

413:             for (uint256 i = 0; i < len; ) {

487:             for (uint256 i = 0; i < len; ++i) {

507:             for (uint256 i = 0; i < len; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L196-L196

File: contracts/option-airdrop/AirdropBroker.sol

336:             for (uint256 i = 0; i < _users.length; i++) {

332:             for (uint256 i = 0; i < _users.length; i++) {

375:             for (uint256 i = 0; i < len; ++i) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L336-L336

File: contracts/options/TapiocaOptionBroker.sol

489:             for (uint256 i = 0; i < len; ++i) {

565:             for (uint256 i = 0; i < len; ++i) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L489-L489

File: contracts/options/TapiocaOptionLiquidityProvision.sol

136:             for (uint256 i = 0; i < len; ++i) {

308:             for (uint256 i = 0; i < sglLength; i++) {

339:         for (uint256 i = 0; i < len; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L136-L136

File: contracts/tokens/BaseTapOFT.sol

228:             for (uint i = 0; i < len; ) {

333:         for (uint256 i = 0; i < approvals.length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L228-L228

File: contracts/Magnetar/MagnetarV2.sol

202:         for (uint256 i = 0; i < length; i++) {

973:         for (uint256 i = 0; i < len; i++) {

1004:        for (uint256 i = 0; i < len; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L202-L202

File: contracts/Magnetar/modules/MagnetarMarketModule.sol

401:         uint256 fraction = 0;

414:         uint256 tOLPTokenId = 0;

508:         uint256 tOLPId = 0;

571:         uint256 _removeAmount = 0;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L401-L401

File: contracts/Multicall/Multicall3.sol

47:          for (uint256 i = 0; i < length; ) {

70:          for (uint256 i = 0; i < length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Multicall/Multicall3.sol#L47-L47

File: contracts/Magnetar/MagnetarV2.sol

202:         for (uint256 i = 0; i < length; i++) {

973:         for (uint256 i = 0; i < len; i++) {

1004:        for (uint256 i = 0; i < len; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L202-L202

File: contracts/Magnetar/modules/MagnetarMarketModule.sol

401:         uint256 fraction = 0;

414:         uint256 tOLPTokenId = 0;

508:         uint256 tOLPId = 0;

571:         uint256 _removeAmount = 0;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L401-L401

File: contracts/Multicall/Multicall3.sol

47:          for (uint256 i = 0; i < length; ) {

70:          for (uint256 i = 0; i < length; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Multicall/Multicall3.sol#L47-L47

File: contracts/balancer/BalancerStrategy.sol

156:         for (uint256 i = 0; i < poolTokens.length; i++) {

225:         for (uint256 i = 0; i < poolTokens.length; i++) {

277:         for (uint256 i = 0; i < poolTokens.length; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L156-L156

File: contracts/convex/ConvexTricryptoStrategy.sol

195:         for (uint256 i = 0; i < tokens.length; i++) {

255:         for (uint256 i = 0; i < tempData.tokens.length; i++) {

273:         for (uint256 i = 0; i < tempData.tokens.length; i++) {

280:         for (uint256 i = 0; i < tempData.tokens.length; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L195-L195

File: contracts/curve/TricryptoLPStrategy.sol

109:         uint256 claimable = 0;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L109-L109

File: contracts/balancer/BalancerStrategy.sol

156:         for (uint256 i = 0; i < poolTokens.length; i++) {

225:         for (uint256 i = 0; i < poolTokens.length; i++) {

277:         for (uint256 i = 0; i < poolTokens.length; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L156-L156

File: contracts/convex/ConvexTricryptoStrategy.sol

195:         for (uint256 i = 0; i < tokens.length; i++) {

255:         for (uint256 i = 0; i < tempData.tokens.length; i++) {

273:         for (uint256 i = 0; i < tempData.tokens.length; i++) {

280:         for (uint256 i = 0; i < tempData.tokens.length; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L195-L195

File: contracts/curve/TricryptoLPStrategy.sol

109:         uint256 claimable = 0;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L109-L109

File: contracts/NativeTokenFactory.sol

129:         for (uint256 i = 0; i < len; i++) {

141:         for (uint256 i = 0; i < len; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L129-L129

File: contracts/YieldBox.sol

309:         for (uint256 i = 0; i < len; i++) {

320:         for (uint256 i = 0; i < len; i++) {

339:         for (uint256 i = 0; i < len; i++) {

345:         for (uint256 i = 0; i < len; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L309-L309

File: contracts/NativeTokenFactory.sol

129:         for (uint256 i = 0; i < len; i++) {

141:         for (uint256 i = 0; i < len; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L129-L129

File: contracts/YieldBox.sol

309:         for (uint256 i = 0; i < len; i++) {

320:         for (uint256 i = 0; i < len; i++) {

339:         for (uint256 i = 0; i < len; i++) {

345:         for (uint256 i = 0; i < len; i++) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L309-L309

[N‑03] Consider using named mappings

Consider moving to solidity version 0.8.18 or later, and using named mappings to make it easier to understand the purpose of each mapping

There are 57 instances of this issue:

see instances
File: contracts/Penrose.sol

61:      mapping(address => bool) public isSingularityMasterContractRegistered;

63:      mapping(address => bool) public isBigBangMasterContractRegistered;

65:      mapping(address => bool) public isMarketRegistered;

79:      mapping(address => IStrategy) public emptyStrategies;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L61-L61

File: contracts/markets/Market.sol

57:      mapping(address => uint256) public userBorrowPart;

59:      mapping(address => uint256) public userCollateralShare;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L57-L57

File: contracts/markets/MarketERC20.sol

48:      mapping(address => uint256) public override balanceOf;

50:      mapping(address => mapping(address => uint256)) public override allowance;

52:      mapping(address => mapping(address => uint256)) public allowanceBorrow;

54:      mapping(address => uint256) private _nonces;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L48-L48

File: contracts/markets/bigBang/BigBang.sol

46:      mapping(address => mapping(address => bool)) public operators;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L46-L46

File: contracts/markets/singularity/SGLStorage.sol

49:      mapping(address => mapping(bytes32 => uint256)) internal _yieldBoxShares;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L49-L49

File: contracts/usd0/BaseUSDOStorage.sol

25:      mapping(uint256 => mapping(address => bool)) public allowedMinter;

28:      mapping(uint256 => mapping(address => bool)) public allowedBurner;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol#L25-L25

File: contracts/Balancer.sol

49:      mapping(address => mapping(uint16 => OFTData)) public connectedOFTs;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L49-L49

File: contracts/TapiocaWrapper.sol

41:      mapping(address => ITapiocaOFT) public tapiocaOFTsByErc20;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L41-L41

File: contracts/tOFT/mTapiocaOFT.sol

17:      mapping(uint256 => bool) public connectedChains;

21:      mapping(address => bool) public balancers;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol#L17-L17

File: contracts/Vesting.sol

38:      mapping(address => UserData) public users;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L38-L38

File: contracts/governance/twTAP.sol

59:      mapping(uint256 => uint256) totalDistPerVote;

79:      mapping(uint256 => Participation) public participants; // tokenId => part.

100:     mapping(uint256 => mapping(uint256 => uint256)) public claimed;

109:     mapping(uint256 => WeekTotals) public weekTotals;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L59-L59

File: contracts/option-airdrop/AirdropBroker.sol

57:      mapping(uint256 => mapping(uint256 => uint256)) public aoTAPCalls; // oTAPTokenID => epoch => amountExercised

61:      mapping(address => mapping(uint256 => bool)) public userParticipation; // user address => phase => participated

68:      mapping(address => uint256) public phase1Users;

92:      mapping(address => uint256) public phase4Users;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L57-L57

File: contracts/option-airdrop/aoTAP.sol

36:      mapping(uint256 => AirdropTapOption) public options; // tokenId => Option

37:      mapping(uint256 => string) public tokenURIs; // tokenId => tokenURI

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L36-L36

File: contracts/options/TapiocaOptionBroker.sol

64:      mapping(uint256 => Participation) public participants; // tOLPTokenID => Participation

65:      mapping(uint256 => mapping(uint256 => uint256)) public oTAPCalls; // oTAPTokenID => epoch => amountExercised

67:      mapping(uint256 => mapping(uint256 => uint256)) public singularityGauges; // epoch => sglAssetId => availableTAP

73:      mapping(uint256 => TWAMLPool) public twAML; // sglAssetId => twAMLPool

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L64-L64

File: contracts/options/TapiocaOptionLiquidityProvision.sol

56:      mapping(uint256 => LockPosition) public lockPositions; // TokenID => LockPosition

62:      mapping(uint256 => IERC20) public sglAssetIDToAddress; // Singularity market YieldBox asset ID => Singularity market address

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L56-L56

File: contracts/options/oTAP.sol

34:      mapping(uint256 => TapOption) public options; // tokenId => Option

35:      mapping(uint256 => string) public tokenURIs; // tokenId => tokenURI

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/oTAP.sol#L34-L34

File: contracts/tokens/TapOFT.sol

57:      mapping(uint256 => uint256) public emissionForWeek;

61:      mapping(uint256 => uint256) public mintedInWeek;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L57-L57

File: contracts/Magnetar/MagnetarV2Storage.sol

29:      mapping(address => mapping(address => bool)) public isApprovedForAll;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2Storage.sol#L29-L29

File: contracts/NativeTokenFactory.sol

24:      mapping(uint256 => NativeToken) public nativeTokens;

25:      mapping(uint256 => address) public owner;

26:      mapping(uint256 => address) public pendingOwner;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L24-L24

File: contracts/YieldBoxPermit.sol

24:      mapping(address => Counters.Counter) private _nonces;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxPermit.sol#L24-L24

[N‑04] Contract uses both require()/revert() as well as custom errors

Consider using just one method in a single file

There are 4 instances of this issue:

File: contracts/markets/MarketERC20.sol

24   contract MarketERC20 is IERC20, IERC20Permit, EIP712 {
25       // ************ //
26       // *** VARS *** //
27       // ************ //
28:      // solhint-disable-next-line var-name-mixedcase

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L24-L28

File: contracts/Vesting.sol

10:  contract Vesting is BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L10-L10

File: contracts/Swapper/BaseSwapper.sol

11:  abstract contract BaseSwapper is Ownable, ReentrancyGuard, ISwapper {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol#L11-L11

File: contracts/Swapper/CurveSwapper.sol

23:  contract CurveSwapper is BaseSwapper {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol#L23-L23

[N‑05] Consider adding a block/deny-list

Doing so will significantly increase centralization, but will help to prevent hackers from using stolen tokens

There are 55 instances of this issue:

see instances
File: contracts/Penrose.sol

32   contract Penrose is BoringOwnable, BoringFactory {
33       // ************ //
34       // *** VARS *** //
35       // ************ //
36:      /// @notice returns the Conservator address

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L32-L36

File: contracts/markets/MarketERC20.sol

24   contract MarketERC20 is IERC20, IERC20Permit, EIP712 {
25       // ************ //
26       // *** VARS *** //
27       // ************ //
28:      // solhint-disable-next-line var-name-mixedcase

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L24-L28

File: contracts/markets/bigBang/BigBang.sol

39:  contract BigBang is BoringOwnable, Market {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L39-L39

File: contracts/markets/singularity/SGLBorrow.sol

8:   contract SGLBorrow is SGLLendingCommon {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLBorrow.sol#L8-L8

File: contracts/markets/singularity/SGLCollateral.sol

8:   contract SGLCollateral is SGLLendingCommon {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCollateral.sol#L8-L8

File: contracts/markets/singularity/SGLCommon.sol

9:   contract SGLCommon is SGLStorage {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol#L9-L9

File: contracts/markets/singularity/SGLLendingCommon.sol

8:   contract SGLLendingCommon is SGLCommon {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol#L8-L8

File: contracts/markets/singularity/SGLLeverage.sol

10:  contract SGLLeverage is SGLLendingCommon {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLeverage.sol#L10-L10

File: contracts/markets/singularity/SGLLiquidation.sol

10:  contract SGLLiquidation is SGLCommon {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L10-L10

File: contracts/markets/singularity/SGLStorage.sol

34:  contract SGLStorage is BoringOwnable, Market {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L34-L34

File: contracts/markets/singularity/Singularity.sol

37:  contract Singularity is SGLCommon {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L37-L37

File: contracts/usd0/BaseUSDO.sol

46:  contract BaseUSDO is BaseUSDOStorage, ERC20Permit {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDO.sol#L46-L46

File: contracts/usd0/BaseUSDOStorage.sol

17   contract BaseUSDOStorage is OFTV2 {
18:      /// @notice the YieldBox address.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol#L17-L18

File: contracts/usd0/USDO.sol

24:  contract USDO is BaseUSDO, IERC3156FlashLender {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/USDO.sol#L24-L24

File: contracts/usd0/modules/USDOLeverageModule.sol

19:  contract USDOLeverageModule is BaseUSDOStorage {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L19-L19

File: contracts/usd0/modules/USDOMarketModule.sol

21:  contract USDOMarketModule is BaseUSDOStorage {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol#L21-L21

File: contracts/usd0/modules/USDOOptionsModule.sol

16:  contract USDOOptionsModule is BaseUSDOStorage {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol#L16-L16

File: contracts/Balancer.sol

34   contract Balancer is Owned {
35       // ************ //
36       // *** VARS *** //
37       // ************ //
38       /// @notice current OFT => chain => destination OFT
39       /// @dev chain ids (https://stargateprotocol.gitbook.io/stargate/developers/chain-ids):
40       ///         - Ethereum: 101
41       ///         - BNB: 102
42       ///         - Avalanche: 106
43       ///         - Polygon: 109
44       ///         - Arbitrum: 110
45       ///         - Optimism: 111
46       ///         - Fantom: 112
47       ///         - Metis: 151
48:      ///     pool ids https://stargateprotocol.gitbook.io/stargate/developers/pool-ids

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L34-L48

File: contracts/TapiocaWrapper.sol

26:  contract TapiocaWrapper is Ownable {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L26-L26

File: contracts/tOFT/BaseTOFT.sol

15:  contract BaseTOFT is BaseTOFTStorage, ERC20Permit {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFT.sol#L15-L15

File: contracts/tOFT/BaseTOFTStorage.sol

21   contract BaseTOFTStorage is OFTV2 {
22       // ************ //
23       // *** VARS *** //
24       // ************ //
25:      /// @notice The YieldBox address.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol#L21-L25

File: contracts/tOFT/TapiocaOFT.sol

21:  contract TapiocaOFT is BaseTOFT {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/TapiocaOFT.sol#L21-L21

File: contracts/tOFT/mTapiocaOFT.sol

9:   contract mTapiocaOFT is BaseTOFT {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol#L9-L9

File: contracts/tOFT/modules/BaseTOFTLeverageModule.sol

21:  contract BaseTOFTLeverageModule is BaseTOFTStorage {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L21-L21

File: contracts/tOFT/modules/BaseTOFTMarketModule.sol

20:  contract BaseTOFTMarketModule is BaseTOFTStorage {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L20-L20

File: contracts/tOFT/modules/BaseTOFTOptionsModule.sol

16:  contract BaseTOFTOptionsModule is BaseTOFTStorage {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol#L16-L16

File: contracts/tOFT/modules/BaseTOFTStrategyModule.sol

16:  contract BaseTOFTStrategyModule is BaseTOFTStorage {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol#L16-L16

File: contracts/Vesting.sol

10:  contract Vesting is BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L10-L10

File: contracts/governance/twTAP.sol

71:  contract TwTAP is TWAML, ONFT721, ERC721Permit {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L71-L71

File: contracts/option-airdrop/AirdropBroker.sol

43:  contract AirdropBroker is Pausable, BoringOwnable, FullMath {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L43-L43

File: contracts/option-airdrop/aoTAP.sol

32:  contract AOTAP is ERC721, ERC721Permit, BaseBoringBatchable, BoringOwnable {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L32-L32

File: contracts/options/TapiocaOptionBroker.sol

53:  contract TapiocaOptionBroker is Pausable, BoringOwnable, TWAML {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L53-L53

File: contracts/options/TapiocaOptionLiquidityProvision.sol

48   contract TapiocaOptionLiquidityProvision is
49       ERC721,
50       ERC721Permit,
51       BaseBoringBatchable,
52       Pausable,
53       BoringOwnable
54:  {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L48-L54

File: contracts/options/oTAP.sol

30:  contract OTAP is ERC721, ERC721Permit, BaseBoringBatchable {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/oTAP.sol#L30-L30

File: contracts/tokens/LTap.sol

23:  contract LTap is BoringOwnable, ERC20Permit {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L23-L23

File: contracts/tokens/TapOFT.sol

26   contract TapOFT is BaseTapOFT, ERC20Permit {
27       // ==========
28       // *DATA*
29       // ==========
30   
31       //  Allocation:
32       // =========
33       // * DSO: 53,313,405
34       // * DAO: 8m
35       // * Contributors: 15m
36       // * Early supporters: 3,686,595
37       // * Supporters: 12.5m
38       // * LBP: 5m
39       // * Airdrop: 2.5m
40:      // == 100M ==

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L26-L40

File: contracts/Magnetar/MagnetarV2.sol

30:  contract MagnetarV2 is Ownable, MagnetarV2Storage {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L30-L30

File: contracts/Magnetar/modules/MagnetarMarketModule.sol

20:  contract MagnetarMarketModule is MagnetarV2Storage {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L20-L20

File: contracts/Swapper/CurveSwapper.sol

23:  contract CurveSwapper is BaseSwapper {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol#L23-L23

File: contracts/Swapper/UniswapV2Swapper.sol

21:  contract UniswapV2Swapper is BaseSwapper {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol#L21-L21

File: contracts/Swapper/UniswapV3Swapper.sol

28:  contract UniswapV3Swapper is BaseSwapper {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L28-L28

File: contracts/oracle/Seer.sol

7:   contract Seer is ITOracle, OracleMulti {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/Seer.sol#L7-L7

File: contracts/aave/AaveStrategy.sol

29:  contract AaveStrategy is BaseERC20Strategy, BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L29-L29

File: contracts/balancer/BalancerStrategy.sol

28:  contract BalancerStrategy is BaseERC20Strategy, BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L28-L28

File: contracts/compound/CompoundStrategy.sol

28:  contract CompoundStrategy is BaseERC20Strategy, BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L28-L28

File: contracts/convex/ConvexTricryptoStrategy.sol

31   contract ConvexTricryptoStrategy is
32       BaseERC20Strategy,
33       BoringOwnable,
34       ReentrancyGuard
35:  {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L31-L35

File: contracts/curve/TricryptoLPStrategy.sol

30   contract TricryptoLPStrategy is
31       BaseERC20Strategy,
32       BoringOwnable,
33       ReentrancyGuard
34:  {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L30-L34

File: contracts/curve/TricryptoNativeStrategy.sol

30   contract TricryptoNativeStrategy is
31       BaseERC20Strategy,
32       BoringOwnable,
33       ReentrancyGuard
34:  {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L30-L34

File: contracts/glp/GlpStrategy.sol

23:  contract GlpStrategy is BaseERC20Strategy, BoringOwnable {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L23-L23

File: contracts/lido/LidoEthStrategy.sol

30:  contract LidoEthStrategy is BaseERC20Strategy, BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L30-L30

File: contracts/stargate/StargateStrategy.sol

35:  contract StargateStrategy is BaseERC20Strategy, BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L35-L35

File: contracts/yearn/YearnStrategy.sol

30:  contract YearnStrategy is BaseERC20Strategy, BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L30-L30

File: contracts/NativeTokenFactory.sol

21:  contract NativeTokenFactory is AssetRegister {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L21-L21

File: contracts/YieldBox.sol

50   contract YieldBox is YieldBoxPermit, BoringBatchable, NativeTokenFactory, ERC721TokenReceiver, ERC1155TokenReceiver {
51       // ******************* //
52       // *** CONSTRUCTOR *** //
53:      // ******************* //

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L50-L53

File: contracts/YieldBoxURIBuilder.sol

11:  contract YieldBoxURIBuilder {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxURIBuilder.sol#L11-L11

[N‑06] Non-external/public variable and function names should begin with an underscore

According to the Solidity Style Guide, Non-external/public variable and function names should begin with an underscore

There are 89 instances of this issue:

see instances
File: contracts/markets/Market.sol

82:      uint256 internal EXCHANGE_RATE_PRECISION; //not costant, but can only be set in the 'init' method

83:      uint256 internal constant FEE_PRECISION = 1e5;

84:      uint256 internal constant FEE_PRECISION_DECIMALS = 5;

129:     bool internal initialized;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L82-L82

File: contracts/markets/bigBang/BigBang.sol

57:      uint256 private constant DEBT_PRECISION = 1e18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L57-L57

File: contracts/markets/singularity/SGLStorage.sol

50       bytes32 internal ASSET_SIG =
51:          0x0bd4060688a1800ae986e4840aebc924bb40b5bf44de4583df2257220b54b77c; // keccak256("asset")

52       bytes32 internal COLLATERAL_SIG =
53:          0x7d1dc38e60930664f8cbf495da6556ca091d2f92d6550877750c049864b18230; // keccak256("collateral")

143:     uint256 internal constant FULL_UTILIZATION = 1e18;

144:     uint256 internal constant UTILIZATION_PRECISION = 1e18;

146:     uint256 internal constant FACTOR_PRECISION = 1e18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L50-L51

File: contracts/usd0/BaseUSDOStorage.sol

37:      uint256 internal constant FLASH_MINT_FEE_PRECISION = 1e6;

38       bytes32 internal constant FLASH_MINT_CALLBACK_SUCCESS =
39:          keccak256("ERC3156FlashBorrower.onFlashLoan");

41:      uint16 internal constant PT_MARKET_MULTIHOP_BUY = 772;

42:      uint16 internal constant PT_MARKET_REMOVE_ASSET = 773;

43:      uint16 internal constant PT_YB_SEND_SGL_LEND_OR_REPAY = 774;

44:      uint16 internal constant PT_LEVERAGE_MARKET_UP = 775;

45:      uint16 internal constant PT_TAP_EXERCISE = 777;

46:      uint16 internal constant PT_SEND_FROM = 778;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol#L37-L37

File: contracts/Balancer.sol

63:      uint256 private constant SLIPPAGE_PRECISION = 1e5;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L63-L63

File: contracts/TapiocaWrapper.sol

39:      ITapiocaOFT[] private harvestableTapiocaOFTs;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L39-L39

File: contracts/tOFT/BaseTOFTStorage.sol

34:      uint16 internal constant PT_YB_SEND_STRAT = 770;

35:      uint16 internal constant PT_YB_RETRIEVE_STRAT = 771;

36:      uint16 internal constant PT_MARKET_REMOVE_COLLATERAL = 772;

37:      uint16 internal constant PT_MARKET_MULTIHOP_SELL = 773;

38:      uint16 internal constant PT_YB_SEND_SGL_BORROW = 775;

39:      uint16 internal constant PT_LEVERAGE_MARKET_DOWN = 776;

40:      uint16 internal constant PT_TAP_EXERCISE = 777;

41:      uint16 internal constant PT_SEND_FROM = 778;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol#L34-L34

File: contracts/governance/twTAP.sol

81:      uint256 constant MIN_WEIGHT_FACTOR = 10; // In BPS, 0.1%

82:      uint256 constant dMAX = 100 * 1e4; // 10% - 100% voting power multiplier

83:      uint256 constant dMIN = 10 * 1e4;

95:      uint256 constant DIST_PRECISION = 2 ** 128;

112:     string private baseURI;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L81-L81

File: contracts/options/TapiocaOptionBroker.sol

75:      uint256 constant MIN_WEIGHT_FACTOR = 10; // In BPS, 0.1%

76:      uint256 constant dMAX = 50 * 1e4; // 5% - 50% discount

77:      uint256 constant dMIN = 5 * 1e4;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L75-L75

File: contracts/tokens/BaseTapOFT.sol

37:      uint16 internal constant PT_LOCK_TWTAP = 870;

38:      uint16 internal constant PT_UNLOCK_TWTAP = 871;

39:      uint16 internal constant PT_CLAIM_REWARDS = 872;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L37-L37

File: contracts/tokens/LTap.sol

24:      IERC20 tapToken;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L24-L24

File: contracts/tokens/TapOFT.sol

45:      uint256 constant decay_rate = 8800000000000000; // 0.88%

46:      uint256 constant DECAY_RATE_DECIMAL = 1e18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L45-L45

File: contracts/twAML.sol

6        function muldiv(
7            uint256 a,
8            uint256 b,
9            uint256 denominator
10:      ) internal pure returns (uint256 result) {

115      function computeMinWeight(
116          uint256 _totalWeight,
117          uint256 _minWeightFactor
118:     ) internal pure returns (uint256) {

123      function computeMagnitude(
124          uint256 _timeWeight,
125          uint256 _cumulative
126:     ) internal pure returns (uint256) {

132      function computeTarget(
133          uint256 _dMin,
134          uint256 _dMax,
135          uint256 _magnitude,
136          uint256 _cumulative
137:     ) internal pure returns (uint256) {

147:     function sqrt(uint256 y) internal pure returns (uint256 z) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/twAML.sol#L6-L10

File: contracts/Magnetar/MagnetarV2Storage.sol

298:     uint16 internal constant PERMIT_ALL = 1;

299:     uint16 internal constant PERMIT = 2;

301:     uint16 internal constant YB_DEPOSIT_ASSET = 100;

302:     uint16 internal constant YB_WITHDRAW_TO = 102;

304:     uint16 internal constant MARKET_ADD_COLLATERAL = 200;

305:     uint16 internal constant MARKET_BORROW = 201;

306:     uint16 internal constant MARKET_LEND = 203;

307:     uint16 internal constant MARKET_REPAY = 204;

308:     uint16 internal constant MARKET_YBDEPOSIT_AND_LEND = 205;

309:     uint16 internal constant MARKET_YBDEPOSIT_COLLATERAL_AND_BORROW = 206;

310:     uint16 internal constant MARKET_REMOVE_ASSET = 207;

311:     uint16 internal constant MARKET_DEPOSIT_REPAY_REMOVE_COLLATERAL = 208;

312:     uint16 internal constant MARKET_BUY_COLLATERAL = 209;

313:     uint16 internal constant MARKET_SELL_COLLATERAL = 210;

314:     uint16 internal constant MARKET_MULTIHOP_BUY = 211;

315:     uint16 internal constant MARKET_MULTIHOP_SELL = 212;

317:     uint16 internal constant TOFT_WRAP = 300;

318:     uint16 internal constant TOFT_SEND_FROM = 301;

319:     uint16 internal constant TOFT_SEND_APPROVAL = 302;

320:     uint16 internal constant TOFT_SEND_AND_BORROW = 303;

321:     uint16 internal constant TOFT_SEND_AND_LEND = 304;

322:     uint16 internal constant TOFT_DEPOSIT_TO_STRATEGY = 305;

323:     uint16 internal constant TOFT_RETRIEVE_FROM_STRATEGY = 306;

324:     uint16 internal constant TOFT_REMOVE_AND_REPAY = 307;

326:     uint16 internal constant TAP_EXERCISE_OPTION = 400;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2Storage.sol#L298-L298

File: contracts/Swapper/UniswapV3Swapper.sol

34:      IYieldBox private immutable yieldBox;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L34-L34

File: contracts/oracle/implementations/GLPOracle.sol

8:       IGmxGlpManager private immutable glpManager;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/GLPOracle.sol#L8-L8

File: contracts/glp/GlpStrategy.sol

30:      IERC20 private immutable gmx;

31:      IERC20 private immutable esGmx;

32:      IERC20 private immutable weth;

34:      IGmxRewardTracker private immutable feeGmxTracker;

35:      IGlpManager private immutable glpManager;

36:      IGmxRewardRouterV2 private immutable glpRewardRouter;

37:      IGmxRewardRouterV2 private immutable gmxRewardRouter;

38:      IGmxVester private immutable glpVester;

39:      IGmxVester private immutable gmxVester;

40:      IGmxRewardTracker private immutable stakedGlpTracker;

41:      IGmxRewardTracker private immutable stakedGmxTracker;

43       IUniswapV3Pool private constant gmxWethPool =
44:          IUniswapV3Pool(0x80A9ae39310abf666A87C743d6ebBD0E8C42158E);

45:      uint160 internal constant UNI_MIN_SQRT_RATIO = 4295128739;

46       uint160 internal constant UNI_MAX_SQRT_RATIO =
47:          1461446703485210103287273052203988822378723970342;

49:      uint256 internal constant FEE_BPS = 100;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L30-L30

[N‑07] Large numeric literals should use underscores for readability

There are 15 instances of this issue:

File: contracts/markets/Market.sol

77:      uint256 public liquidationMultiplier = 12000; //12%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L77-L77

File: contracts/markets/bigBang/BigBang.sol

148:         callerFee = 90000; // 90%

149:         protocolFee = 10000; // 10%

150:         collateralizationRate = 75000; // 75%

168:         liquidationMultiplier = 12000; //12%

521:         _accrueInfo.debtRate = uint64(annumDebtRate / 31536000); //per second

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L148-L148

File: contracts/markets/singularity/SGLStorage.sol

55:      uint256 public lqCollateralizationRate = 25000; // 25%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L55-L55

File: contracts/markets/singularity/Singularity.sol

112:         minimumInterestPerSecond = 951293760; // approx 3% APR

113:         maximumInterestPerSecond = 2536783360; // approx 8% APR

123:         protocolFee = 10000; // 10%

127:         liquidationMultiplier = 12000; //12%

129:         collateralizationRate = 75000;

130:         lqCollateralizationRate = 25000;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L112-L112

File: contracts/tokens/TapOFT.sol

45:      uint256 constant decay_rate = 8800000000000000; // 0.88%

49:      uint256 public constant WEEK = 604800;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L45-L45

[N‑08] Unused contract variables

Note that there may be cases where a variable appears to be used, but this is only because there are multiple definitions of the varible in different files. In such cases, the variable definition should be moved into a separate file. The instances below are the unused variables.

There are 4 instances of this issue:

File: contracts/markets/MarketERC20.sol

45:      bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L45-L45

File: contracts/governance/twTAP.sol

112:     string private baseURI;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L112-L112

File: contracts/Magnetar/MagnetarV2Storage.sol

315:     uint16 internal constant MARKET_MULTIHOP_SELL = 212;

319:     uint16 internal constant TOFT_SEND_APPROVAL = 302;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2Storage.sol#L315-L315

[N‑09] Use abi.encodeCall() instead of abi.encodeSignature()/abi.encodeSelector()

abi.encodeCall() has compiler type safety, whereas the other two functions do not

There are 58 instances of this issue:

see instances
File: contracts/markets/singularity/Singularity.sol

244:             abi.encodeWithSelector(

262:             abi.encodeWithSelector(

284:             abi.encodeWithSelector(SGLBorrow.borrow.selector, from, to, amount)

304:             abi.encodeWithSelector(

331:             abi.encodeWithSelector(

361:             abi.encodeWithSelector(

391:             abi.encodeWithSelector(

418:             abi.encodeWithSelector(

449:             abi.encodeWithSelector(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L244-L244

File: contracts/usd0/BaseUSDO.sol

168:             abi.encodeWithSelector(

196:             abi.encodeWithSelector(

227:             abi.encodeWithSelector(

263:             abi.encodeWithSelector(

293:             abi.encodeWithSelector(

325:             abi.encodeWithSelector(

482:                 abi.encodeWithSelector(

466:                 abi.encodeWithSelector(

454:                 abi.encodeWithSelector(

442:                 abi.encodeWithSelector(

426:                 abi.encodeWithSelector(

410:                 abi.encodeWithSelector(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDO.sol#L168-L168

File: contracts/usd0/modules/USDOLeverageModule.sol

170:             abi.encodeWithSelector(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L170-L170

File: contracts/usd0/modules/USDOMarketModule.sol

169:             abi.encodeWithSelector(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol#L169-L169

File: contracts/usd0/modules/USDOOptionsModule.sol

175:             abi.encodeWithSelector(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol#L175-L175

File: contracts/tOFT/BaseTOFT.sol

109:             abi.encodeWithSelector(

137:             abi.encodeWithSelector(

167:             abi.encodeWithSelector(

202:             abi.encodeWithSelector(

235:             abi.encodeWithSelector(

267:             abi.encodeWithSelector(

302:             abi.encodeWithSelector(

332:             abi.encodeWithSelector(

554:                 abi.encodeWithSelector(

539:                 abi.encodeWithSelector(

527:                 abi.encodeWithSelector(

515:                 abi.encodeWithSelector(

499:                 abi.encodeWithSelector(

483:                 abi.encodeWithSelector(

470:                 abi.encodeWithSelector(

453:                 abi.encodeWithSelector(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFT.sol#L109-L109

File: contracts/tOFT/modules/BaseTOFTLeverageModule.sol

185:             abi.encodeWithSelector(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L185-L185

File: contracts/tOFT/modules/BaseTOFTMarketModule.sol

161:             abi.encodeWithSelector(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L161-L161

File: contracts/tOFT/modules/BaseTOFTOptionsModule.sol

190:             abi.encodeWithSelector(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol#L190-L190

File: contracts/tOFT/modules/BaseTOFTStrategyModule.sol

153:             abi.encodeWithSelector(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol#L153-L153

File: contracts/Magnetar/MagnetarV2.sol

609:                     abi.encodeWithSelector(

592:                     abi.encodeWithSelector(

571:                     abi.encodeWithSelector(

536:                     abi.encodeWithSelector(

353:                     abi.encodeWithSelector(

746:             abi.encodeWithSelector(

787:             abi.encodeWithSelector(

825:             abi.encodeWithSelector(

867:             abi.encodeWithSelector(

897:             abi.encodeWithSelector(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L609-L609

File: contracts/Swapper/BaseSwapper.sol

100:             abi.encodeWithSelector(0x095ea7b3, to, value)

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol#L100-L100

File: contracts/convex/ConvexTricryptoStrategy.sol

357:             abi.encodeWithSelector(

370:             abi.encodeWithSelector(

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L357-L357

File: contracts/curve/TricryptoLPStrategy.sol

106:             abi.encodeWithSignature("claimable_tokens(address)", address(this))

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L106-L106

[N‑10] Constants in comparisons should appear on the left side

Doing so will prevent typo bugs

There are 92 instances of this issue:

see instances
File: contracts/Penrose.sol

175:             isSingularityMasterContractRegistered[mc] == true,

183:             isBigBangMasterContractRegistered[mc] == true,

322:             isSingularityMasterContractRegistered[mcAddress] == false,

344:             isBigBangMasterContractRegistered[mcAddress] == false,

509:         if (feeShares == 0) return;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L175-L175

File: contracts/markets/Market.sol

314:         if (borrowPart == 0) return (0, 0, 0);

408:         if (borrowPart == 0) return true;

410:         if (collateralShare == 0) return false;

447:         if (borrowed == 0) return 0;

448:         if (startTVLInAsset == 0) return 0;

485:         if (numerator == 0 || denominator == 0) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L314-L314

File: contracts/markets/MarketERC20.sol

140:         if (amount != 0 || msg.sender == to) {

165:         if (amount != 0) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L140-L140

File: contracts/markets/bigBang/BigBang.sol

182:         if (totalBorrow.elastic == 0) return minDebtRate;

516:         if (elapsedTime == 0) {

550:         if (share == 0) {

751:             totalBorrowCap == 0 || totalBorrow.elastic <= totalBorrowCap,

820:         require(borrowAmount != 0, "SGL: solvent");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L182-L182

File: contracts/markets/singularity/SGLBorrow.sol

26:          if (amount == 0) return (0, 0);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLBorrow.sol#L26-L26

File: contracts/markets/singularity/SGLCommon.sol

61:          utilization = fullAssetAmount == 0

68:          if (elapsedTime == 0) {

81:          if (_totalBorrow.base == 0) {

207:         fraction = allShare == 0

229:         if (totalAsset.base == 0) {

240:         require(_totalAsset.base >= 1000, "SGL: min limit");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol#L61-L61

File: contracts/markets/singularity/SGLLendingCommon.sol

23:          if (share == 0) {

67:              totalBorrowCap == 0 || totalBorrow.base <= totalBorrowCap,

75:          require(_totalAsset.base >= 1000, "SGL: min limit");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol#L23-L23

File: contracts/markets/singularity/SGLLiquidation.sol

76:          if (borrowPart == 0) return 0;

115:                 if (borrowAmount == 0) {

152:         require(allBorrowAmount != 0, "SGL: solvent");

264:         require(borrowAmount != 0, "SGL: solvent");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L76-L76

File: contracts/Balancer.sol

118:         if (_slippage >= 1e5) revert SlippageNotValid();

206:             if (msg.value == 0) revert FeeAmountNotSet();

226:         if (!isNative && _ercData.length == 0) revert PoolInfoRequired();

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L118-L118

File: contracts/TapiocaWrapper.sol

86:          if (tapiocaOFTs.length == 0) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L86-L86

File: contracts/tOFT/BaseTOFT.sol

85:          if (_decimalCache == 0) return 18; //temporary fix for LZ _sharedDecimals check

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFT.sol#L85-L85

File: contracts/Vesting.sol

111:         if (start == 0 || seeded == 0) revert NotStarted();

113:         if (_claimable == 0) revert NothingToClaim();

133:         if (_amount == 0) revert AmountNotValid();

153:         if (_seededAmount == 0) revert NoTokens();

168:         if (start == 0) return 0;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L111-L111

File: contracts/governance/twTAP.sol

179:         if (votes == 0) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L179-L179

File: contracts/option-airdrop/AirdropBroker.sol

176:         tapAmount = _tapAmount == 0 ? eligibleTapAmount : _tapAmount;

177:         require(tapAmount >= 1e18, "adb: Too low");

204:         require(cachedEpoch <= 4, "adb: Airdrop ended");

207:         if (cachedEpoch == 1) {

209:         } else if (cachedEpoch == 2) {

211:         } else if (cachedEpoch == 3) {

213:         } else if (cachedEpoch == 4) {

257:         uint256 chosenAmount = _tapAmount == 0 ? eligibleTapAmount : _tapAmount;

258:         require(chosenAmount >= 1e18, "adb: Too low");

331:         if (_phase == 1) {

335:         } else if (_phase == 4) {

426:             userParticipation[msg.sender][subPhase] == false,

450:             userParticipation[tokenIDToAddress][3] == false,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L176-L176

File: contracts/options/TapiocaOptionBroker.sol

189:         tapAmount = _tapAmount == 0 ? eligibleTapAmount : _tapAmount;

190:         require(tapAmount >= 1e18, "tOB: Too low");

390:         uint256 chosenAmount = _tapAmount == 0 ? eligibleTapAmount : _tapAmount;

391:         require(chosenAmount >= 1e18, "tOB: Too low");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L189-L189

File: contracts/options/TapiocaOptionLiquidityProvision.sol

283:             activeSingularities[singularity].sglAssetID == 0,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L283-L283

File: contracts/tokens/TapOFT.sol

176:         if (timestamp == 0) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L176-L176

File: contracts/twAML.sol

32:          if (prod1 == 0) {

120:         return mul >= 1e4 ? mul / 1e4 : _totalWeight;

138:         if (_cumulative == 0) {

155:         } else if (y != 0) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/twAML.sol#L32-L32

File: contracts/Magnetar/MagnetarV2.sol

186:         fraction = allShare == 0 ? share : (share * totalAssetBase) / allShare;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L186-L186

File: contracts/Magnetar/modules/MagnetarMarketModule.sol

402:         if (lendAmount == 0 && depositData.deposit) {

454:             if (participateData.tOLPTokenId != 0) {

455:                 if (tOLPTokenId != 0) {

468:             require(tOLPTokenId != 0, "Magnetar: tOLPTokenId 0");

554:             if (removeAndRepayData.unlockData.tokenId != 0) {

555:                 if (tOLPId != 0) {

690:         if (dstChainId == 0) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L402-L402

File: contracts/Swapper/BaseSwapper.sol

103:             success && (data.length == 0 || abi.decode(data, (bool))),

132:                 amountIn = amounts.amountIn == 0

137:                 amountOut = amounts.amountOut == 0

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol#L103-L103

File: contracts/Swapper/UniswapV2Swapper.sol

147:         if (data.length == 0) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol#L147-L147

File: contracts/Swapper/UniswapV3Swapper.sol

175:         if (data.length == 0) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L175-L175

File: contracts/TapiocaDeployer/TapiocaDeployer.sol

33:              bytecode.length != 0,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/TapiocaDeployer/TapiocaDeployer.sol#L33-L33

File: contracts/convex/ConvexTricryptoStrategy.sol

190:         if (data.length == 0) return;

312:         if (calcAmount >= 1e18) {

377:             success && (data.length == 0 || abi.decode(data, (bool))),

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L190-L190

File: contracts/glp/GlpStrategy.sol

186:         if (available == 0) {

194:         if (vestable == 0) {

265:         if (vestable == 0) {

294:         if (vestable == 0) {

318:         if (gmxAmount == 0) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L186-L186

File: contracts/YieldBox.sol

131:         if (share == 0) {

280:         if (share == 0) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L131-L131

[N‑11] Consider disabling renounceOwnership()

If the plan for your project does not include eventually giving up all ownership control, consider overwriting OpenZeppelin's Ownable's renounceOwnership() function in order to disable it.

There are 24 instances of this issue:

see instances
File: contracts/Penrose.sol

32:  contract Penrose is BoringOwnable, BoringFactory {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L32-L32

File: contracts/markets/Market.sol

14:  abstract contract Market is MarketERC20, BoringOwnable {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L14-L14

File: contracts/markets/bigBang/BigBang.sol

39:  contract BigBang is BoringOwnable, Market {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L39-L39

File: contracts/markets/singularity/SGLStorage.sol

34:  contract SGLStorage is BoringOwnable, Market {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L34-L34

File: contracts/TapiocaWrapper.sol

26:  contract TapiocaWrapper is Ownable {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L26-L26

File: contracts/Vesting.sol

10:  contract Vesting is BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L10-L10

File: contracts/option-airdrop/AirdropBroker.sol

43:  contract AirdropBroker is Pausable, BoringOwnable, FullMath {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L43-L43

File: contracts/option-airdrop/aoTAP.sol

32:  contract AOTAP is ERC721, ERC721Permit, BaseBoringBatchable, BoringOwnable {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L32-L32

File: contracts/options/TapiocaOptionBroker.sol

53:  contract TapiocaOptionBroker is Pausable, BoringOwnable, TWAML {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L53-L53

File: contracts/options/TapiocaOptionLiquidityProvision.sol

53:      BoringOwnable

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L53-L53

File: contracts/tokens/LTap.sol

23:  contract LTap is BoringOwnable, ERC20Permit {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L23-L23

File: contracts/Magnetar/MagnetarV2.sol

30:  contract MagnetarV2 is Ownable, MagnetarV2Storage {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L30-L30

File: contracts/Multicall/Multicall3.sol

22:  contract Multicall3 is Ownable {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Multicall/Multicall3.sol#L22-L22

File: contracts/Swapper/BaseSwapper.sol

11:  abstract contract BaseSwapper is Ownable, ReentrancyGuard, ISwapper {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol#L11-L11

File: contracts/aave/AaveStrategy.sol

29:  contract AaveStrategy is BaseERC20Strategy, BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L29-L29

File: contracts/balancer/BalancerStrategy.sol

28:  contract BalancerStrategy is BaseERC20Strategy, BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L28-L28

File: contracts/compound/CompoundStrategy.sol

28:  contract CompoundStrategy is BaseERC20Strategy, BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L28-L28

File: contracts/convex/ConvexTricryptoStrategy.sol

33:      BoringOwnable,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L33-L33

File: contracts/curve/TricryptoLPStrategy.sol

32:      BoringOwnable,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L32-L32

File: contracts/curve/TricryptoNativeStrategy.sol

32:      BoringOwnable,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L32-L32

File: contracts/glp/GlpStrategy.sol

23:  contract GlpStrategy is BaseERC20Strategy, BoringOwnable {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L23-L23

File: contracts/lido/LidoEthStrategy.sol

30:  contract LidoEthStrategy is BaseERC20Strategy, BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L30-L30

File: contracts/stargate/StargateStrategy.sol

35:  contract StargateStrategy is BaseERC20Strategy, BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L35-L35

File: contracts/yearn/YearnStrategy.sol

30:  contract YearnStrategy is BaseERC20Strategy, BoringOwnable, ReentrancyGuard {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L30-L30

[N‑12] Consider adding emergency-stop functionality

Adding a way to quickly halt protocol functionality in an emergency, rather than having to pause individual contracts one-by-one, will make in-progress hack mitigation faster and much less stressful.

There are 18 instances of this issue:

see instances
File: contracts/Penrose.sol

32   contract Penrose is BoringOwnable, BoringFactory {
33       // ************ //
34       // *** VARS *** //
35       // ************ //
36       /// @notice returns the Conservator address
37       address public conservator;
38       /// @notice returns the pause state of the contract
39       bool public paused;
40       /// @notice returns the YieldBox contract
41       YieldBox public immutable yieldBox;
42       /// @notice returns the TAP contract
43       IERC20 public immutable tapToken;
44       /// @notice returns TAP asset id registered in the YieldBox contract
45       uint256 public immutable tapAssetId;
46       /// @notice returns USDO contract
47       IERC20 public usdoToken;
48       /// @notice returns USDO asset id registered in the YieldBox contract
49       uint256 public usdoAssetId;
50       /// @notice returns the WETH contract
51       IERC20 public immutable wethToken;
52       /// @notice returns WETH asset id registered in the YieldBox contract
53       uint256 public immutable wethAssetId;
54   
55       /// @notice Singularity master contracts
56       IPenrose.MasterContract[] public singularityMasterContracts;
57       /// @notice BigBang master contracts
58       IPenrose.MasterContract[] public bigbangMasterContracts;
59   
60       // Used to check if a Singularity master contract is registered
61       mapping(address => bool) public isSingularityMasterContractRegistered;
62       // Used to check if a BigBang master contract is registered
63       mapping(address => bool) public isBigBangMasterContractRegistered;
64       // Used to check if a SGL/BB is a real market
65       mapping(address => bool) public isMarketRegistered;
66   
67       /// @notice protocol fees
68       address public feeTo;
69   
70       /// @notice whitelisted swappers
71       mapping(ISwapper => bool) public swappers;
72   
73       /// @notice BigBang ETH market address
74       address public bigBangEthMarket;
75       /// @notice BigBang ETH market debt rate
76       uint256 public bigBangEthDebtRate;
77   
78       /// @notice registered empty strategies
79       mapping(address => IStrategy) public emptyStrategies;
80   
81       /// @notice creates a Penrose contract
82       /// @param _yieldBox YieldBox contract address
83       /// @param tapToken_ TapOFT contract address
84       /// @param wethToken_ WETH contract address
85       /// @param _owner owner address
86       constructor(
87           YieldBox _yieldBox,
88           IERC20 tapToken_,
89           IERC20 wethToken_,
90           address _owner
91       ) {
92           yieldBox = _yieldBox;
93           tapToken = tapToken_;
94           owner = _owner;
95   
96           emptyStrategies[address(tapToken_)] = IStrategy(
97               address(
98                   new ERC20WithoutStrategy(
99                       IYieldBox(address(_yieldBox)),
100                      tapToken_
101                  )
102              )
103          );
104          tapAssetId = uint96(
105              _yieldBox.registerAsset(
106                  TokenType.ERC20,
107                  address(tapToken_),
108                  emptyStrategies[address(tapToken_)],
109                  0
110              )
111          );
112  
113          wethToken = wethToken_;
114          emptyStrategies[address(wethToken_)] = IStrategy(
115              address(
116                  new ERC20WithoutStrategy(
117                      IYieldBox(address(_yieldBox)),
118                      wethToken_
119                  )
120              )
121          );
122          wethAssetId = uint96(
123              _yieldBox.registerAsset(
124                  TokenType.ERC20,
125                  address(wethToken_),
126                  emptyStrategies[address(wethToken_)],
127                  0
128              )
129          );
130  
131          bigBangEthDebtRate = 5e15;
132      }
133  
134      // **************//
135      // *** EVENTS *** //
136      // ************** //
137      /// @notice event emitted when fees are extracted
138      event ProtocolWithdrawal(IMarket[] markets, uint256 timestamp);
139      /// @notice event emitted when Singularity master contract is registered
140      event RegisterSingularityMasterContract(
141          address location,
142          IPenrose.ContractType risk
143      );
144      /// @notice event emitted when BigBang master contract is registered
145      event RegisterBigBangMasterContract(
146          address location,
147          IPenrose.ContractType risk
148      );
149      /// @notice event emitted when Singularity is registered
150      event RegisterSingularity(address location, address masterContract);
151      /// @notice event emitted when BigBang is registered
152      event RegisterBigBang(address location, address masterContract);
153      /// @notice event emitted when feeTo address is updated
154      event FeeToUpdate(address newFeeTo);
155      /// @notice event emitted when ISwapper address is updated
156      event SwapperUpdate(address swapper, bool isRegistered);
157      /// @notice event emitted when USDO address is updated
158      event UsdoTokenUpdated(address indexed usdoToken, uint256 assetId);
159      /// @notice event emitted when conservator is updated
160      event ConservatorUpdated(address indexed old, address indexed _new);
161      /// @notice event emitted when pause state is updated
162      event PausedUpdated(bool oldState, bool newState);
163      /// @notice event emitted when BigBang ETH market address is updated
164      event BigBangEthMarketSet(address indexed _newAddress);
165      /// @notice event emitted when BigBang ETH market debt rate is updated
166      event BigBangEthMarketDebtRate(uint256 _rate);
167      /// @notice event emitted when fees are deposited to YieldBox
168      event LogYieldBoxFeesDeposit(uint256 feeShares, uint256 ethAmount);
169  
170      // ******************//
171      // *** MODIFIERS *** //
172      // ***************** //
173      modifier registeredSingularityMasterContract(address mc) {
174          require(
175              isSingularityMasterContractRegistered[mc] == true,
176              "Penrose: MC not registered"
177          );
178          _;
179      }
180  
181      modifier registeredBigBangMasterContract(address mc) {
182          require(
183              isBigBangMasterContractRegistered[mc] == true,
184              "Penrose: MC not registered"
185          );
186          _;
187      }
188  
189      modifier notPaused() {
190          require(!paused, "Penrose: paused");
191          _;
192      }
193  
194      // ********************** //
195      // *** VIEW FUNCTIONS *** //
196      // ********************** //
197      /// @notice Get all the Singularity contract addresses
198      /// @return markets list of available markets
199      function singularityMarkets()
200          public
201          view
202          returns (address[] memory markets)
203      {
204          markets = _getMasterContractLength(singularityMasterContracts);
205      }
206  
207      /// @notice Get all the BigBang contract addresses
208      /// @return markets list of available markets
209      function bigBangMarkets() public view returns (address[] memory markets) {
210          markets = _getMasterContractLength(bigbangMasterContracts);
211      }
212  
213      /// @notice Get the length of `singularityMasterContracts`
214      function singularityMasterContractLength() public view returns (uint256) {
215          return singularityMasterContracts.length;
216      }
217  
218      /// @notice Get the length of `bigbangMasterContracts`
219      function bigBangMasterContractLength() public view returns (uint256) {
220          return bigbangMasterContracts.length;
221      }
222  
223      // ************************ //
224      // *** PUBLIC FUNCTIONS *** //
225      // ************************ //
226      /// @notice Loop through the master contracts and call `_depositFeesToYieldBox()` to each one of their clones.
227      /// @dev `swappers_` can have one element that'll be used for all clones. Or one swapper per MasterContract.
228      /// @dev Fees are withdrawn in TAP and sent to the FeeDistributor contract
229      /// @param markets_ Singularity &/ BigBang markets array
230      /// @param swappers_ one or more swappers to convert the asset to TAP.
231      /// @param swapData_ swap data for each swapper
232      function withdrawAllMarketFees(
233          IMarket[] calldata markets_,
234          ISwapper[] calldata swappers_,
235          IPenrose.SwapData[] calldata swapData_
236      ) public notPaused {
237          require(
238              markets_.length == swappers_.length &&
239                  swappers_.length == swapData_.length,
240              "Penrose: length mismatch"
241          );
242          require(address(swappers_[0]) != address(0), "Penrose: zero address");
243          require(address(markets_[0]) != address(0), "Penrose: zero address");
244  
245          _withdrawAllProtocolFees(swappers_, swapData_, markets_);
246  
247          emit ProtocolWithdrawal(markets_, block.timestamp);
248      }
249  
250      // *********************** //
251      // *** OWNER FUNCTIONS *** //
252      // *********************** //
253      /// @notice sets the main BigBang market debt rate
254      /// @dev can only be called by the owner
255      /// @param _rate the new rate
256      function setBigBangEthMarketDebtRate(uint256 _rate) external onlyOwner {
257          bigBangEthDebtRate = _rate;
258          emit BigBangEthMarketDebtRate(_rate);
259      }
260  
261      /// @notice sets the main BigBang market
262      /// @dev needed for the variable debt computation
263      function setBigBangEthMarket(address _market) external onlyOwner {
264          bigBangEthMarket = _market;
265          emit BigBangEthMarketSet(_market);
266      }
267  
268      /// @notice updates the pause state of the contract
269      /// @dev can only be called by the conservator
270      /// @param val the new value
271      function updatePause(bool val) external {
272          require(msg.sender == conservator, "Penrose: unauthorized");
273          require(val != paused, "Penrose: same state");
274          emit PausedUpdated(paused, val);
275          paused = val;
276      }
277  
278      /// @notice Set the Conservator address
279      /// @dev Conservator can pause the contract
280      /// @param _conservator The new address
281      function setConservator(address _conservator) external onlyOwner {
282          require(_conservator != address(0), "Penrose: address not valid");
283          emit ConservatorUpdated(conservator, _conservator);
284          conservator = _conservator;
285      }
286  
287      /// @notice Set the USDO token
288      /// @dev sets usdoToken and usdoAssetId
289      ///      can only by called by the owner
290      /// @param _usdoToken the USDO token address
291      function setUsdoToken(address _usdoToken) external onlyOwner {
292          usdoToken = IERC20(_usdoToken);
293  
294          emptyStrategies[_usdoToken] = IStrategy(
295              address(
296                  new ERC20WithoutStrategy(
297                      IYieldBox(address(yieldBox)),
298                      IERC20(_usdoToken)
299                  )
300              )
301          );
302          usdoAssetId = uint96(
303              yieldBox.registerAsset(
304                  TokenType.ERC20,
305                  _usdoToken,
306                  emptyStrategies[_usdoToken],
307                  0
308              )
309          );
310          emit UsdoTokenUpdated(_usdoToken, usdoAssetId);
311      }
312  
313      /// @notice Register a Singularity master contract
314      /// @dev can only be called by the owner
315      /// @param mcAddress The address of the contract
316      /// @param contractType_ The risk type of the contract
317      function registerSingularityMasterContract(
318          address mcAddress,
319          IPenrose.ContractType contractType_
320      ) external onlyOwner {
321          require(
322              isSingularityMasterContractRegistered[mcAddress] == false,
323              "Penrose: MC registered"
324          );
325  
326          IPenrose.MasterContract memory mc;
327          mc.location = mcAddress;
328          mc.risk = contractType_;
329          singularityMasterContracts.push(mc);
330          isSingularityMasterContractRegistered[mcAddress] = true;
331  
332          emit RegisterSingularityMasterContract(mcAddress, contractType_);
333      }
334  
335      /// @notice Register a BigBang master contract
336      /// @dev can only be called by the owner
337      /// @param mcAddress The address of the contract
338      /// @param contractType_ The risk type of the contract
339      function registerBigBangMasterContract(
340          address mcAddress,
341          IPenrose.ContractType contractType_
342      ) external onlyOwner {
343          require(
344              isBigBangMasterContractRegistered[mcAddress] == false,
345              "Penrose: MC registered"
346          );
347  
348          IPenrose.MasterContract memory mc;
349          mc.location = mcAddress;
350          mc.risk = contractType_;
351          bigbangMasterContracts.push(mc);
352          isBigBangMasterContractRegistered[mcAddress] = true;
353  
354          emit RegisterBigBangMasterContract(mcAddress, contractType_);
355      }
356  
357      /// @notice Registers a Singularity market
358      /// @dev can only be called by the owner
359      /// @param mc The address of the master contract which must be already registered
360      /// @param data The init data of the Singularity
361      /// @param useCreate2 Whether to use create2 or not
362      function registerSingularity(
363          address mc,
364          bytes calldata data,
365          bool useCreate2
366      )
367          external
368          payable
369          onlyOwner
370          registeredSingularityMasterContract(mc)
371          returns (address _contract)
372      {
373          _contract = deploy(mc, data, useCreate2);
374          isMarketRegistered[_contract] = true;
375          emit RegisterSingularity(_contract, mc);
376      }
377  
378      /// @notice Registers an existing Singularity market (without deployment)
379      /// @dev can only be called by the owner
380      /// @param mc The address of the master contract which must be already registered
381      function addSingularity(
382          address mc,
383          address _contract
384      ) external onlyOwner registeredSingularityMasterContract(mc) {
385          isMarketRegistered[_contract] = true;
386          clonesOf[mc].push(_contract);
387          emit RegisterSingularity(_contract, mc);
388      }
389  
390      /// @notice Registers a BigBang market
391      /// @dev can only be called by the owner
392      /// @param mc The address of the master contract which must be already registered
393      /// @param data The init data of the BigBang contract
394      /// @param useCreate2 Whether to use create2 or not
395      function registerBigBang(
396          address mc,
397          bytes calldata data,
398          bool useCreate2
399      )
400          external
401          payable
402          onlyOwner
403          registeredBigBangMasterContract(mc)
404          returns (address _contract)
405      {
406          _contract = deploy(mc, data, useCreate2);
407          isMarketRegistered[_contract] = true;
408          emit RegisterBigBang(_contract, mc);
409      }
410  
411      /// @notice Registers an existing BigBang market (without deployment)
412      /// @dev can only be called by the owner
413      /// @param mc The address of the master contract which must be already registered
414      function addBigBang(
415          address mc,
416          address _contract
417      ) external onlyOwner registeredBigBangMasterContract(mc) {
418          isMarketRegistered[_contract] = true;
419          clonesOf[mc].push(_contract);
420          emit RegisterBigBang(_contract, mc);
421      }
422  
423      /// @notice Execute an only owner function inside of a Singularity or a BigBang market
424      function executeMarketFn(
425          address[] calldata mc,
426          bytes[] memory data,
427          bool forceSuccess
428      )
429          external
430          onlyOwner
431          notPaused
432          returns (bool[] memory success, bytes[] memory result)
433      {
434          uint256 len = mc.length;
435          success = new bool[](len);
436          result = new bytes[](len);
437          for (uint256 i = 0; i < len; ) {
438              require(
439                  isSingularityMasterContractRegistered[
440                      masterContractOf[mc[i]]
441                  ] || isBigBangMasterContractRegistered[masterContractOf[mc[i]]],
442                  "Penrose: MC not registered"
443              );
444              (success[i], result[i]) = mc[i].call(data[i]);
445              if (forceSuccess) {
446                  require(success[i], _getRevertMsg(result[i]));
447              }
448              ++i;
449          }
450      }
451  
452      /// @notice Set protocol fees address
453      /// @dev can only be called by the owner
454      /// @param feeTo_ the new feeTo address
455      function setFeeTo(address feeTo_) external onlyOwner {
456          feeTo = feeTo_;
457          emit FeeToUpdate(feeTo_);
458      }
459  
460      /// @notice Used to register and enable or disable swapper contracts used in closed liquidations.
461      /// @dev can only be called by the owner
462      /// @param swapper The address of the swapper contract that conforms to `ISwapper`.
463      /// @param enable True to enable the swapper. To disable use False.
464      function setSwapper(ISwapper swapper, bool enable) external onlyOwner {
465          swappers[swapper] = enable;
466          emit SwapperUpdate(address(swapper), enable);
467      }
468  
469      // ************************* //
470      // *** PRIVATE FUNCTIONS *** //
471      // ************************* //
472      function _getRevertMsg(
473          bytes memory _returnData
474      ) private pure returns (string memory) {
475          // If the _res length is less than 68, then the transaction failed silently (without a revert message)
476          if (_returnData.length < 68) return "SGL: no return data";
477          // solhint-disable-next-line no-inline-assembly
478          assembly {
479              // Slice the sighash.
480              _returnData := add(_returnData, 0x04)
481          }
482          return abi.decode(_returnData, (string)); // All that remains is the revert string
483      }
484  
485      function _withdrawAllProtocolFees(
486          ISwapper[] calldata swappers_,
487          IPenrose.SwapData[] calldata swapData_,
488          IMarket[] memory markets_
489      ) private {
490          uint256 length = markets_.length;
491          unchecked {
492              for (uint256 i = 0; i < length; ) {
493                  _depositFeesToYieldBox(markets_[i], swappers_[i], swapData_[i]);
494                  ++i;
495              }
496          }
497      }
498  
499      /// @notice Withdraw the balance of `feeTo`, swap asset into TAP and deposit it to yieldBox of `feeTo`
500      function _depositFeesToYieldBox(
501          IMarket market,
502          ISwapper swapper,
503          IPenrose.SwapData calldata dexData
504      ) private {
505          require(swappers[swapper], "Penrose: Invalid swapper");
506          require(isMarketRegistered[address(market)], "Penrose: Invalid market");
507  
508          uint256 feeShares = market.refreshPenroseFees(feeTo);
509          if (feeShares == 0) return;
510  
511          uint256 assetId = market.assetId();
512          uint256 amount = 0;
513          if (assetId != wethAssetId) {
514              yieldBox.transfer(
515                  address(this),
516                  address(swapper),
517                  assetId,
518                  feeShares
519              );
520  
521              ISwapper.SwapData memory swapData = swapper.buildSwapData(
522                  assetId,
523                  wethAssetId,
524                  0,
525                  feeShares,
526                  true,
527                  true
528              );
529              (amount, ) = swapper.swap(
530                  swapData,
531                  dexData.minAssetAmount,
532                  feeTo,
533                  ""
534              );
535          } else {
536              yieldBox.transfer(address(this), feeTo, assetId, feeShares);
537          }
538  
539          emit LogYieldBoxFeesDeposit(feeShares, amount);
540      }
541  
542      function _getMasterContractLength(
543          IPenrose.MasterContract[] memory array
544      ) public view returns (address[] memory markets) {
545          uint256 _masterContractLength = array.length;
546          uint256 marketsLength = 0;
547  
548          unchecked {
549              // We first compute the length of the markets array
550              for (uint256 i = 0; i < _masterContractLength; ) {
551                  marketsLength += clonesOfCount(array[i].location);
552  
553                  ++i;
554              }
555          }
556  
557          markets = new address[](marketsLength);
558  
559          uint256 marketIndex;
560          uint256 clonesOfLength;
561  
562          unchecked {
563              // We populate the array
564              for (uint256 i = 0; i < _masterContractLength; ) {
565                  address mcLocation = array[i].location;
566                  clonesOfLength = clonesOfCount(mcLocation);
567  
568                  // Loop through clones of the current MC.
569                  for (uint256 j = 0; j < clonesOfLength; ) {
570                      markets[marketIndex] = clonesOf[mcLocation][j];
571                      ++marketIndex;
572                      ++j;
573                  }
574                  ++i;
575              }
576          }
577      }
578: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L32-L578

File: contracts/markets/Market.sol

14   abstract contract Market is MarketERC20, BoringOwnable {
15       using RebaseLibrary for Rebase;
16   
17       // ************ //
18       // *** VARS *** //
19       // ************ //
20       /// @notice returns YieldBox address
21       YieldBox public yieldBox;
22       /// @notice returns Penrose address
23       IPenrose public penrose;
24   
25       /// @notice collateral token address
26       IERC20 public collateral;
27       /// @notice collateral token YieldBox id
28       uint256 public collateralId;
29       /// @notice asset token address
30       IERC20 public asset;
31       /// @notice asset token YieldBox id
32       uint256 public assetId;
33   
34       /// @notice contract's pause state
35       bool public paused;
36       /// @notice conservator's addresss
37       /// @dev conservator can pause/unpause the contract
38       address public conservator;
39   
40       /// @notice oracle address
41       IOracle public oracle;
42       /// @notice oracleData
43       bytes public oracleData;
44       /// @notice Exchange and interest rate tracking.
45       /// This is 'cached' here because calls to Oracles can be very expensive.
46       /// Asset -> collateral = assetAmount * exchangeRate.
47       uint256 public exchangeRate;
48   
49       /// @notice total amount borrowed
50       /// @dev elastic = Total token amount to be repayed by borrowers, base = Total parts of the debt held by borrowers
51       Rebase public totalBorrow;
52       /// @notice total collateral supplied
53       uint256 public totalCollateralShare;
54       /// @notice max borrow cap
55       uint256 public totalBorrowCap;
56       /// @notice borrow amount per user
57       mapping(address => uint256) public userBorrowPart;
58       /// @notice collateral share per user
59       mapping(address => uint256) public userCollateralShare;
60   
61       /// @notice liquidation caller rewards
62       uint256 public callerFee; // 90%
63       /// @notice liquidation protocol rewards
64       uint256 public protocolFee; // 10%
65       /// @notice min % a liquidator can receive in rewards
66       uint256 public minLiquidatorReward = 1e3; //1%
67       /// @notice max % a liquidator can receive in rewards
68       uint256 public maxLiquidatorReward = 1e4; //10%
69       /// @notice max liquidatable bonus amount
70       /// @dev max % added to the amount that can be liquidated
71       uint256 public liquidationBonusAmount = 1e4; //10%
72       /// @notice collateralization rate
73       uint256 public collateralizationRate; // 75%
74       /// @notice borrowing opening fee
75       uint256 public borrowOpeningFee = 50; //0.05%
76       /// @notice liquidation multiplier used to compute liquidator rewards
77       uint256 public liquidationMultiplier = 12000; //12%
78   
79       // ***************** //
80       // *** CONSTANTS *** //
81       // ***************** //
82       uint256 internal EXCHANGE_RATE_PRECISION; //not costant, but can only be set in the 'init' method
83       uint256 internal constant FEE_PRECISION = 1e5;
84       uint256 internal constant FEE_PRECISION_DECIMALS = 5;
85   
86       // ************** //
87       // *** EVENTS *** //
88       // ************** //
89       /// @notice event emitted when conservator is updated
90       event ConservatorUpdated(address indexed old, address indexed _new);
91       /// @notice event emitted when pause state is changed
92       event PausedUpdated(bool oldState, bool newState);
93       /// @notice event emitted when cached exchange rate is updated
94       event LogExchangeRate(uint256 rate);
95       /// @notice event emitted when borrow cap is updated
96       event LogBorrowCapUpdated(uint256 _oldVal, uint256 _newVal);
97       /// @notice event emitted when oracle data is updated
98       event OracleDataUpdated();
99       /// @notice event emitted when oracle is updated
100      event OracleUpdated();
101      /// @notice event emitted when a position is liquidated
102      event Liquidated(
103          address liquidator,
104          address[] users,
105          uint256 liquidatorReward,
106          uint256 protocolReward,
107          uint256 repayedAmount,
108          uint256 collateralShareRemoved
109      );
110      /// @notice event emitted when borrow opening fee is updated
111      event LogBorrowingFee(uint256 _oldVal, uint256 _newVal);
112      /// @notice event emitted when the liquidation multiplier rate is updated
113      event LiquidationMultiplierUpdated(uint256 oldVal, uint256 newVal);
114  
115      modifier notPaused() {
116          require(!paused, "Market: paused");
117          _;
118      }
119      /// @dev Checks if the user is solvent in the closed liquidation case at the end of the function body.
120      modifier solvent(address from) {
121          updateExchangeRate();
122          _accrue();
123  
124          _;
125  
126          require(_isSolvent(from, exchangeRate), "Market: insolvent");
127      }
128  
129      bool internal initialized;
130      modifier onlyOnce() {
131          require(!initialized, "Market: initialized");
132          _;
133          initialized = true;
134      }
135  
136      // *********************** //
137      // *** OWNER FUNCTIONS *** //
138      // *********************** //
139      /// @notice sets the borrowing opening fee
140      /// @dev can only be called by the owner
141      /// @param _val the new value
142      function setBorrowOpeningFee(uint256 _val) external onlyOwner {
143          require(_val <= FEE_PRECISION, "Market: not valid");
144          emit LogBorrowingFee(borrowOpeningFee, _val);
145          borrowOpeningFee = _val;
146      }
147  
148      /// @notice sets max borrowable amount
149      /// @dev can only be called by the owner
150      /// @param _cap the new value
151      function setBorrowCap(uint256 _cap) external notPaused onlyOwner {
152          emit LogBorrowCapUpdated(totalBorrowCap, _cap);
153          totalBorrowCap = _cap;
154      }
155  
156      /// @notice sets common market configuration
157      /// @dev values are updated only if > 0 or not address(0)
158      function setMarketConfig(
159          uint256 _borrowOpeningFee,
160          IOracle _oracle,
161          bytes calldata _oracleData,
162          address _conservator,
163          uint256 _callerFee,
164          uint256 _protocolFee,
165          uint256 _liquidationBonusAmount,
166          uint256 _minLiquidatorReward,
167          uint256 _maxLiquidatorReward,
168          uint256 _totalBorrowCap,
169          uint256 _collateralizationRate
170      ) external onlyOwner {
171          if (_borrowOpeningFee > 0) {
172              require(_borrowOpeningFee <= FEE_PRECISION, "Market: not valid");
173              emit LogBorrowingFee(borrowOpeningFee, _borrowOpeningFee);
174              borrowOpeningFee = _borrowOpeningFee;
175          }
176  
177          if (address(_oracle) != address(0)) {
178              oracle = _oracle;
179              emit OracleUpdated();
180          }
181  
182          if (_oracleData.length > 0) {
183              oracleData = _oracleData;
184              emit OracleDataUpdated();
185          }
186  
187          if (_conservator != address(0)) {
188              emit ConservatorUpdated(conservator, _conservator);
189              conservator = _conservator;
190          }
191  
192          if (_callerFee > 0) {
193              require(_callerFee <= FEE_PRECISION, "Market: not valid");
194              callerFee = _callerFee;
195          }
196  
197          if (_protocolFee > 0) {
198              require(_protocolFee <= FEE_PRECISION, "Market: not valid");
199              protocolFee = _protocolFee;
200          }
201  
202          if (_liquidationBonusAmount > 0) {
203              require(
204                  _liquidationBonusAmount < FEE_PRECISION,
205                  "Market: not valid"
206              );
207              liquidationBonusAmount = _liquidationBonusAmount;
208          }
209  
210          if (_minLiquidatorReward > 0) {
211              require(_minLiquidatorReward < FEE_PRECISION, "Market: not valid");
212              require(
213                  _minLiquidatorReward < maxLiquidatorReward,
214                  "Market: not valid"
215              );
216              minLiquidatorReward = _minLiquidatorReward;
217          }
218  
219          if (_maxLiquidatorReward > 0) {
220              require(_maxLiquidatorReward < FEE_PRECISION, "Market: not valid");
221              require(
222                  _maxLiquidatorReward > minLiquidatorReward,
223                  "Market: not valid"
224              );
225              maxLiquidatorReward = _maxLiquidatorReward;
226          }
227  
228          if (_totalBorrowCap > 0) {
229              emit LogBorrowCapUpdated(totalBorrowCap, _totalBorrowCap);
230              totalBorrowCap = _totalBorrowCap;
231          }
232  
233          if (_collateralizationRate > 0) {
234              require(
235                  _collateralizationRate <= FEE_PRECISION,
236                  "Market: not valid"
237              );
238              collateralizationRate = _collateralizationRate;
239          }
240      }
241  
242      /// @notice updates the pause state of the contract
243      /// @dev can only be called by the conservator
244      /// @param val the new value
245      function updatePause(bool val) external {
246          require(msg.sender == conservator, "Market: unauthorized");
247          require(val != paused, "Market: same state");
248          emit PausedUpdated(paused, val);
249          paused = val;
250      }
251  
252      // ********************** //
253      // *** VIEW FUNCTIONS *** //
254      // ********************** //
255      /// @notice returns the maximum liquidatable amount for user
256      function computeClosingFactor(
257          uint256 borrowPart,
258          uint256 collateralPartInAsset,
259          uint256 borrowPartDecimals,
260          uint256 collateralPartDecimals,
261          uint256 ratesPrecision
262      ) public view returns (uint256) {
263          uint256 borrowPartScaled = borrowPart;
264          if (borrowPartDecimals > 18) {
265              borrowPartScaled = borrowPart / (10 ** (borrowPartDecimals - 18));
266          }
267          if (borrowPartDecimals < 18) {
268              borrowPartScaled = borrowPart * (10 ** (18 - borrowPartDecimals));
269          }
270  
271          uint256 collateralPartInAssetScaled = collateralPartInAsset;
272          if (collateralPartDecimals > 18) {
273              collateralPartInAssetScaled =
274                  collateralPartInAsset /
275                  (10 ** (collateralPartDecimals - 18));
276          }
277          if (collateralPartDecimals < 18) {
278              collateralPartInAssetScaled =
279                  collateralPartInAsset *
280                  (10 ** (18 - collateralPartDecimals));
281          }
282  
283          uint256 liquidationStartsAt = (collateralPartInAssetScaled *
284              collateralizationRate) / (10 ** ratesPrecision);
285          if (borrowPartScaled < liquidationStartsAt) return 0;
286  
287          uint256 numerator = borrowPartScaled -
288              ((collateralizationRate * collateralPartInAssetScaled) /
289                  (10 ** ratesPrecision));
290          uint256 denominator = ((10 ** ratesPrecision) -
291              (collateralizationRate *
292                  ((10 ** ratesPrecision) + liquidationMultiplier)) /
293              (10 ** ratesPrecision)) * (10 ** (18 - ratesPrecision));
294  
295          uint256 x = (numerator * 1e18) / denominator;
296          return x;
297      }
298  
299      /// @notice return the amount of collateral for a `user` to be solvent, min TVL and max TVL. Returns 0 if user already solvent.
300      /// @dev we use a `CLOSED_COLLATERIZATION_RATE` that is a safety buffer when making the user solvent again,
301      ///      to prevent from being liquidated. This function is valid only if user is not solvent by `_isSolvent()`.
302      /// @param user The user to check solvency.
303      /// @param _exchangeRate the exchange rate asset/collateral.
304      /// @return amountToSolvency the amount of collateral to be solvent.
305      function computeTVLInfo(
306          address user,
307          uint256 _exchangeRate
308      )
309          public
310          view
311          returns (uint256 amountToSolvency, uint256 minTVL, uint256 maxTVL)
312      {
313          uint256 borrowPart = userBorrowPart[user];
314          if (borrowPart == 0) return (0, 0, 0);
315  
316          Rebase memory _totalBorrow = totalBorrow;
317  
318          uint256 collateralAmountInAsset = _computeMaxBorrowableAmount(
319              user,
320              _exchangeRate
321          );
322  
323          borrowPart = (borrowPart * _totalBorrow.elastic) / _totalBorrow.base;
324  
325          amountToSolvency = borrowPart >= collateralAmountInAsset
326              ? borrowPart - collateralAmountInAsset
327              : 0;
328  
329          (minTVL, maxTVL) = _computeMaxAndMinLTVInAsset(
330              userCollateralShare[user],
331              _exchangeRate
332          );
333      }
334  
335      /// @notice Gets the exchange rate. I.e how much collateral to buy 1e18 asset.
336      /// @dev This function is supposed to be invoked if needed because Oracle queries can be expensive.
337      ///      Oracle should consider USDO at 1$
338      /// @return updated True if `exchangeRate` was updated.
339      /// @return rate The new exchange rate.
340      function updateExchangeRate() public returns (bool updated, uint256 rate) {
341          (updated, rate) = oracle.get("");
342  
343          if (updated) {
344              require(rate > 0, "Market: invalid rate");
345              exchangeRate = rate;
346              emit LogExchangeRate(rate);
347          } else {
348              // Return the old rate if fetching wasn't successful
349              rate = exchangeRate;
350          }
351      }
352  
353      /// @notice computes the possible liquidator reward
354      /// @notice user the user for which a liquidation operation should be performed
355      /// @param _exchangeRate the exchange rate asset/collateral to use for internal computations
356      function computeLiquidatorReward(
357          address user,
358          uint256 _exchangeRate
359      ) public view returns (uint256) {
360          (uint256 minTVL, uint256 maxTVL) = _computeMaxAndMinLTVInAsset(
361              userCollateralShare[user],
362              _exchangeRate
363          );
364          return _getCallerReward(userBorrowPart[user], minTVL, maxTVL);
365      }
366  
367      // ************************** //
368      // *** INTERNAL FUNCTIONS *** //
369      // ************************** //
370      function _accrue() internal virtual;
371  
372      function _getRevertMsg(
373          bytes memory _returnData
374      ) internal pure returns (string memory) {
375          // If the _res length is less than 68, then the transaction failed silently (without a revert message)
376          if (_returnData.length < 68) return "Market: no return data";
377          // solhint-disable-next-line no-inline-assembly
378          assembly {
379              // Slice the sighash.
380              _returnData := add(_returnData, 0x04)
381          }
382          return abi.decode(_returnData, (string)); // All that remains is the revert string
383      }
384  
385      function _computeMaxBorrowableAmount(
386          address user,
387          uint256 _exchangeRate
388      ) internal view returns (uint256 collateralAmountInAsset) {
389          collateralAmountInAsset =
390              yieldBox.toAmount(
391                  collateralId,
392                  (userCollateralShare[user] *
393                      (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *
394                      collateralizationRate),
395                  false
396              ) /
397              _exchangeRate;
398      }
399  
400      /// @notice Concrete implementation of `isSolvent`. Includes a parameter to allow caching `exchangeRate`.
401      /// @param _exchangeRate The exchange rate. Used to cache the `exchangeRate` between calls.
402      function _isSolvent(
403          address user,
404          uint256 _exchangeRate
405      ) internal view returns (bool) {
406          // accrue must have already been called!
407          uint256 borrowPart = userBorrowPart[user];
408          if (borrowPart == 0) return true;
409          uint256 collateralShare = userCollateralShare[user];
410          if (collateralShare == 0) return false;
411  
412          Rebase memory _totalBorrow = totalBorrow;
413  
414          return
415              yieldBox.toAmount(
416                  collateralId,
417                  collateralShare *
418                      (EXCHANGE_RATE_PRECISION / FEE_PRECISION) *
419                      collateralizationRate,
420                  false
421              ) >=
422              // Moved exchangeRate here instead of dividing the other side to preserve more precision
423              (borrowPart * _totalBorrow.elastic * _exchangeRate) /
424                  _totalBorrow.base;
425      }
426  
427      /// @notice Returns the min and max LTV for user in asset price
428      function _computeMaxAndMinLTVInAsset(
429          uint256 collateralShare,
430          uint256 _exchangeRate
431      ) internal view returns (uint256 min, uint256 max) {
432          uint256 collateralAmount = yieldBox.toAmount(
433              collateralId,
434              collateralShare,
435              false
436          );
437  
438          max = (collateralAmount * EXCHANGE_RATE_PRECISION) / _exchangeRate;
439          min = (max * collateralizationRate) / FEE_PRECISION;
440      }
441  
442      function _getCallerReward(
443          uint256 borrowed,
444          uint256 startTVLInAsset,
445          uint256 maxTVLInAsset
446      ) internal view returns (uint256) {
447          if (borrowed == 0) return 0;
448          if (startTVLInAsset == 0) return 0;
449  
450          if (borrowed < startTVLInAsset) return 0;
451          if (borrowed >= maxTVLInAsset) return minLiquidatorReward;
452  
453          uint256 rewardPercentage = ((borrowed - startTVLInAsset) *
454              FEE_PRECISION) / (maxTVLInAsset - startTVLInAsset);
455  
456          int256 diff = int256(minLiquidatorReward) - int256(maxLiquidatorReward);
457          int256 reward = (diff * int256(rewardPercentage)) /
458              int256(FEE_PRECISION) +
459              int256(maxLiquidatorReward);
460  
461          return uint256(reward);
462      }
463  
464      function _computeAllowanceAmountInAsset(
465          address user,
466          uint256 _exchangeRate,
467          uint256 borrowAmount,
468          uint256 assetDecimals
469      ) internal view returns (uint256) {
470          uint256 maxBorrowabe = _computeMaxBorrowableAmount(user, _exchangeRate);
471  
472          uint256 shareRatio = _getRatio(
473              borrowAmount,
474              maxBorrowabe,
475              assetDecimals
476          );
477          return (shareRatio * userCollateralShare[user]) / (10 ** assetDecimals);
478      }
479  
480      function _getRatio(
481          uint256 numerator,
482          uint256 denominator,
483          uint256 precision
484      ) private pure returns (uint256) {
485          if (numerator == 0 || denominator == 0) {
486              return 0;
487          }
488          uint256 _numerator = numerator * 10 ** (precision + 1);
489          uint256 _quotient = ((_numerator / denominator) + 5) / 10;
490          return (_quotient);
491      }
492: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L14-L492

File: contracts/markets/bigBang/BigBang.sol

39   contract BigBang is BoringOwnable, Market {
40       using RebaseLibrary for Rebase;
41       using BoringERC20 for IERC20;
42   
43       // ************ //
44       // *** VARS *** //
45       // ************ //
46       mapping(address => mapping(address => bool)) public operators;
47   
48       IBigBang.AccrueInfo public accrueInfo;
49   
50       uint256 public totalFees;
51   
52       bool private _isEthMarket;
53       uint256 public maxDebtRate;
54       uint256 public minDebtRate;
55       uint256 public debtRateAgainstEthMarket;
56       uint256 public debtStartPoint;
57       uint256 private constant DEBT_PRECISION = 1e18;
58   
59       // ************** //
60       // *** EVENTS *** //
61       // ************** //
62       /// @notice event emitted when accrue is called
63       event LogAccrue(uint256 accruedAmount, uint64 rate);
64       /// @notice event emitted when collateral is added
65       event LogAddCollateral(
66           address indexed from,
67           address indexed to,
68           uint256 share
69       );
70       /// @notice event emitted when collateral is removed
71       event LogRemoveCollateral(
72           address indexed from,
73           address indexed to,
74           uint256 share
75       );
76       /// @notice event emitted when borrow is performed
77       event LogBorrow(
78           address indexed from,
79           address indexed to,
80           uint256 amount,
81           uint256 feeAmount,
82           uint256 part
83       );
84       /// @notice event emitted when a repay operation is performed
85       event LogRepay(
86           address indexed from,
87           address indexed to,
88           uint256 amount,
89           uint256 part
90       );
91       /// @notice event emitted when the minimum debt rate is updated
92       event MinDebtRateUpdated(uint256 oldVal, uint256 newVal);
93       /// @notice event emitted when the maximum debt rate is updated
94       event MaxDebtRateUpdated(uint256 oldVal, uint256 newVal);
95       /// @notice event emitted when the debt rate against the main market is updated
96       event DebtRateAgainstEthUpdated(uint256 oldVal, uint256 newVal);
97   
98       constructor() MarketERC20("Tapioca BigBang") {}
99   
100      /// @notice The init function that acts as a constructor
101      function init(bytes calldata data) external onlyOnce {
102          (
103              IPenrose tapiocaBar_,
104              IERC20 _collateral,
105              uint256 _collateralId,
106              IOracle _oracle,
107              uint256 _exchangeRatePrecision,
108              uint256 _debtRateAgainstEth,
109              uint256 _debtRateMin,
110              uint256 _debtRateMax,
111              uint256 _debtStartPoint
112          ) = abi.decode(
113                  data,
114                  (
115                      IPenrose,
116                      IERC20,
117                      uint256,
118                      IOracle,
119                      uint256,
120                      uint256,
121                      uint256,
122                      uint256,
123                      uint256
124                  )
125              );
126  
127          penrose = tapiocaBar_;
128          yieldBox = YieldBox(tapiocaBar_.yieldBox());
129          owner = address(penrose);
130  
131          address _asset = penrose.usdoToken();
132  
133          require(
134              address(_collateral) != address(0) &&
135                  address(_asset) != address(0) &&
136                  address(_oracle) != address(0),
137              "BigBang: bad pair"
138          );
139  
140          asset = IERC20(_asset);
141          assetId = penrose.usdoAssetId();
142          collateral = _collateral;
143          collateralId = _collateralId;
144          oracle = _oracle;
145  
146          updateExchangeRate();
147  
148          callerFee = 90000; // 90%
149          protocolFee = 10000; // 10%
150          collateralizationRate = 75000; // 75%
151  
152          EXCHANGE_RATE_PRECISION = _exchangeRatePrecision > 0
153              ? _exchangeRatePrecision
154              : 1e18;
155  
156          _isEthMarket = collateralId == penrose.wethAssetId();
157          if (!_isEthMarket) {
158              debtRateAgainstEthMarket = _debtRateAgainstEth;
159              maxDebtRate = _debtRateMax;
160              minDebtRate = _debtRateMin;
161              debtStartPoint = _debtStartPoint;
162          }
163  
164          minLiquidatorReward = 1e3;
165          maxLiquidatorReward = 1e4;
166          liquidationBonusAmount = 1e4;
167          borrowOpeningFee = 50; // 0.05%
168          liquidationMultiplier = 12000; //12%
169      }
170  
171      // ********************** //
172      // *** VIEW FUNCTIONS *** //
173      // ********************** //
174      /// @notice returns total market debt
175      function getTotalDebt() external view returns (uint256) {
176          return totalBorrow.elastic;
177      }
178  
179      /// @notice returns the current debt rate
180      function getDebtRate() public view returns (uint256) {
181          if (_isEthMarket) return penrose.bigBangEthDebtRate(); // default 0.5%
182          if (totalBorrow.elastic == 0) return minDebtRate;
183  
184          uint256 _ethMarketTotalDebt = BigBang(penrose.bigBangEthMarket())
185              .getTotalDebt();
186          uint256 _currentDebt = totalBorrow.elastic;
187          uint256 _maxDebtPoint = (_ethMarketTotalDebt *
188              debtRateAgainstEthMarket) / 1e18;
189  
190          if (_currentDebt >= _maxDebtPoint) return maxDebtRate;
191  
192          uint256 debtPercentage = ((_currentDebt - debtStartPoint) *
193              DEBT_PRECISION) / (_maxDebtPoint - debtStartPoint);
194          uint256 debt = ((maxDebtRate - minDebtRate) * debtPercentage) /
195              DEBT_PRECISION +
196              minDebtRate;
197  
198          if (debt > maxDebtRate) return maxDebtRate;
199  
200          return debt;
201      }
202  
203      // ************************ //
204      // *** PUBLIC FUNCTIONS *** //
205      // ************************ //
206      /// @notice Allows batched call to BingBang.
207      /// @param calls An array encoded call data.
208      /// @param revertOnFail If True then reverts after a failed call and stops doing further calls.
209      function execute(
210          bytes[] calldata calls,
211          bool revertOnFail
212      ) external returns (bool[] memory successes, string[] memory results) {
213          successes = new bool[](calls.length);
214          results = new string[](calls.length);
215          for (uint256 i = 0; i < calls.length; i++) {
216              (bool success, bytes memory result) = address(this).delegatecall(
217                  calls[i]
218              );
219              require(success || !revertOnFail, _getRevertMsg(result));
220              successes[i] = success;
221              results[i] = _getRevertMsg(result);
222          }
223      }
224  
225      /// @notice allows 'operator' to act on behalf of the sender
226      /// @param status true/false
227      function updateOperator(address operator, bool status) external {
228          operators[msg.sender][operator] = status;
229      }
230  
231      /// @notice Accrues the interest on the borrowed tokens and handles the accumulation of fees.
232      function accrue() public {
233          _accrue();
234      }
235  
236      /// @notice Sender borrows `amount` and transfers it to `to`.
237      /// @param from Account to borrow for.
238      /// @param to The receiver of borrowed tokens.
239      /// @param amount Amount to borrow.
240      /// @return part Total part of the debt held by borrowers.
241      /// @return share Total amount in shares borrowed.
242      function borrow(
243          address from,
244          address to,
245          uint256 amount
246      ) public notPaused solvent(from) returns (uint256 part, uint256 share) {
247          uint256 allowanceShare = _computeAllowanceAmountInAsset(
248              from,
249              exchangeRate,
250              amount,
251              asset.safeDecimals()
252          );
253          _allowedBorrow(from, allowanceShare);
254          (part, share) = _borrow(from, to, amount);
255      }
256  
257      /// @notice Repays a loan.
258      /// @dev The bool param is not used but we added it to respect the ISingularity interface for MarketsHelper compatibility
259      /// @param from Address to repay from.
260      /// @param to Address of the user this payment should go.
261      /// @param part The amount to repay. See `userBorrowPart`.
262      /// @return amount The total amount repayed.
263      function repay(
264          address from,
265          address to,
266          bool,
267          uint256 part
268      ) public notPaused allowedBorrow(from, part) returns (uint256 amount) {
269          updateExchangeRate();
270  
271          accrue();
272  
273          amount = _repay(from, to, part);
274      }
275  
276      /// @notice Adds `collateral` from msg.sender to the account `to`.
277      /// @param from Account to transfer shares from.
278      /// @param to The receiver of the tokens.
279      /// @param skim True if the amount should be skimmed from the deposit balance of msg.sender.
280      /// False if tokens from msg.sender in `yieldBox` should be transferred.
281      /// @param share The amount of shares to add for `to`.
282      function addCollateral(
283          address from,
284          address to,
285          bool skim,
286          uint256 amount,
287          uint256 share
288      ) public allowedBorrow(from, share) notPaused {
289          _addCollateral(from, to, skim, amount, share);
290      }
291  
292      /// @notice Removes `share` amount of collateral and transfers it to `to`.
293      /// @param from Account to debit collateral from.
294      /// @param to The receiver of the shares.
295      /// @param share Amount of shares to remove.
296      function removeCollateral(
297          address from,
298          address to,
299          uint256 share
300      ) public notPaused solvent(from) allowedBorrow(from, share) {
301          _removeCollateral(from, to, share);
302      }
303  
304      /// @notice Entry point for liquidations.
305      /// @param users An array of user addresses.
306      /// @param maxBorrowParts A one-to-one mapping to `users`, contains maximum (partial) borrow amounts (to liquidate) of the respective user.
307      /// @param swapper Contract address of the `MultiSwapper` implementation. See `setSwapper`.
308      /// @param collateralToAssetSwapData Extra swap data
309      function liquidate(
310          address[] calldata users,
311          uint256[] calldata maxBorrowParts,
312          ISwapper swapper,
313          bytes calldata collateralToAssetSwapData
314      ) external notPaused {
315          // Oracle can fail but we still need to allow liquidations
316          (, uint256 _exchangeRate) = updateExchangeRate();
317          _accrue();
318  
319          _closedLiquidation(
320              users,
321              maxBorrowParts,
322              swapper,
323              _exchangeRate,
324              collateralToAssetSwapData
325          );
326      }
327  
328      /// @notice Lever up: Borrow more and buy collateral with it.
329      /// @param from The user who buys
330      /// @param borrowAmount Amount of extra asset borrowed
331      /// @param supplyAmount Amount of asset supplied (down payment)
332      /// @param minAmountOut Mininal collateral amount to receive
333      /// @param swapper Swapper to execute the purchase
334      /// @param dexData Additional data to pass to the swapper
335      /// @return amountOut Actual collateral amount purchased
336      function buyCollateral(
337          address from,
338          uint256 borrowAmount,
339          uint256 supplyAmount,
340          uint256 minAmountOut,
341          ISwapper swapper,
342          bytes calldata dexData
343      ) external notPaused solvent(from) returns (uint256 amountOut) {
344          require(penrose.swappers(swapper), "SGL: Invalid swapper");
345  
346          // Let this fail first to save gas:
347          uint256 supplyShare = yieldBox.toShare(assetId, supplyAmount, true);
348          if (supplyShare > 0) {
349              yieldBox.transfer(from, address(swapper), assetId, supplyShare);
350          }
351  
352          uint256 borrowShare;
353          (, borrowShare) = _borrow(from, address(swapper), borrowAmount);
354  
355          ISwapper.SwapData memory swapData = swapper.buildSwapData(
356              assetId,
357              collateralId,
358              0,
359              supplyShare + borrowShare,
360              true,
361              true
362          );
363  
364          uint256 collateralShare;
365          (amountOut, collateralShare) = swapper.swap(
366              swapData,
367              minAmountOut,
368              from,
369              dexData
370          );
371          require(amountOut >= minAmountOut, "SGL: not enough");
372  
373          _allowedBorrow(from, collateralShare);
374          _addCollateral(from, from, false, 0, collateralShare);
375      }
376  
377      /// @notice Lever down: Sell collateral to repay debt; excess goes to YB
378      /// @param from The user who sells
379      /// @param share Collateral YieldBox-shares to sell
380      /// @param minAmountOut Mininal proceeds required for the sale
381      /// @param swapper Swapper to execute the sale
382      /// @param dexData Additional data to pass to the swapper
383      /// @return amountOut Actual asset amount received in the sale
384      function sellCollateral(
385          address from,
386          uint256 share,
387          uint256 minAmountOut,
388          ISwapper swapper,
389          bytes calldata dexData
390      ) external notPaused solvent(from) returns (uint256 amountOut) {
391          require(penrose.swappers(swapper), "SGL: Invalid swapper");
392  
393          _allowedBorrow(from, share);
394          _removeCollateral(from, address(swapper), share);
395          ISwapper.SwapData memory swapData = swapper.buildSwapData(
396              collateralId,
397              assetId,
398              0,
399              share,
400              true,
401              true
402          );
403          uint256 shareOut;
404          (amountOut, shareOut) = swapper.swap(
405              swapData,
406              minAmountOut,
407              from,
408              dexData
409          );
410          // As long as the ratio is correct, we trust `amountOut` resp.
411          // `shareOut`, because all money received by the swapper gets used up
412          // one way or another, or the transaction will revert.
413          require(amountOut >= minAmountOut, "SGL: not enough");
414          uint256 partOwed = userBorrowPart[from];
415          uint256 amountOwed = totalBorrow.toElastic(partOwed, true);
416          uint256 shareOwed = yieldBox.toShare(assetId, amountOwed, true);
417          if (shareOwed <= shareOut) {
418              _repay(from, from, partOwed);
419          } else {
420              //repay as much as we can
421              uint256 partOut = totalBorrow.toBase(amountOut, false);
422              _repay(from, from, partOut);
423          }
424      }
425  
426      function transfer(
427          address to,
428          uint256 amount
429      ) public override returns (bool) {}
430  
431      function transferFrom(
432          address from,
433          address to,
434          uint256 amount
435      ) public override returns (bool) {}
436  
437      // ************************* //
438      // *** OWNER FUNCTIONS ***** //
439      // ************************* //
440  
441      /// @notice Transfers fees to penrose
442      function refreshPenroseFees(
443          address
444      ) external onlyOwner notPaused returns (uint256 feeShares) {
445          uint256 balance = asset.balanceOf(address(this));
446          totalFees += balance;
447          feeShares = yieldBox.toShare(assetId, totalFees, false);
448  
449          if (totalFees > 0) {
450              asset.approve(address(yieldBox), totalFees);
451  
452              yieldBox.depositAsset(
453                  assetId,
454                  address(this),
455                  msg.sender,
456                  totalFees,
457                  0
458              );
459  
460              totalFees = 0;
461          }
462      }
463  
464      /// @notice sets BigBang specific configuration
465      /// @dev values are updated only if > 0 or not address(0)
466      function setBigBangConfig(
467          uint256 _minDebtRate,
468          uint256 _maxDebtRate,
469          uint256 _debtRateAgainstEthMarket,
470          uint256 _liquidationMultiplier
471      ) external onlyOwner {
472          _isEthMarket = collateralId == penrose.wethAssetId();
473  
474          if (!_isEthMarket) {
475              if (_minDebtRate > 0) {
476                  require(_minDebtRate < maxDebtRate, "BigBang: not valid");
477                  emit MinDebtRateUpdated(minDebtRate, _minDebtRate);
478                  minDebtRate = _minDebtRate;
479              }
480  
481              if (_maxDebtRate > 0) {
482                  require(_maxDebtRate > minDebtRate, "BigBang: not valid");
483                  emit MaxDebtRateUpdated(maxDebtRate, _maxDebtRate);
484                  maxDebtRate = _maxDebtRate;
485              }
486  
487              if (_debtRateAgainstEthMarket > 0) {
488                  emit DebtRateAgainstEthUpdated(
489                      debtRateAgainstEthMarket,
490                      _debtRateAgainstEthMarket
491                  );
492                  debtRateAgainstEthMarket = _debtRateAgainstEthMarket;
493              }
494  
495              if (_liquidationMultiplier > 0) {
496                  require(
497                      _liquidationMultiplier < FEE_PRECISION,
498                      "BigBang: not valid"
499                  );
500                  emit LiquidationMultiplierUpdated(
501                      liquidationMultiplier,
502                      _liquidationMultiplier
503                  );
504                  liquidationMultiplier = _liquidationMultiplier;
505              }
506          }
507      }
508  
509      // ************************* //
510      // *** PRIVATE FUNCTIONS *** //
511      // ************************* //
512      function _accrue() internal override {
513          IBigBang.AccrueInfo memory _accrueInfo = accrueInfo;
514          // Number of seconds since accrue was called
515          uint256 elapsedTime = block.timestamp - _accrueInfo.lastAccrued;
516          if (elapsedTime == 0) {
517              return;
518          }
519          //update debt rate
520          uint256 annumDebtRate = getDebtRate();
521          _accrueInfo.debtRate = uint64(annumDebtRate / 31536000); //per second
522  
523          _accrueInfo.lastAccrued = uint64(block.timestamp);
524  
525          Rebase memory _totalBorrow = totalBorrow;
526  
527          uint256 extraAmount = 0;
528  
529          // Calculate fees
530          extraAmount =
531              (uint256(_totalBorrow.elastic) *
532                  _accrueInfo.debtRate *
533                  elapsedTime) /
534              1e18;
535          _totalBorrow.elastic += uint128(extraAmount);
536  
537          totalBorrow = _totalBorrow;
538          accrueInfo = _accrueInfo;
539  
540          emit LogAccrue(extraAmount, _accrueInfo.debtRate);
541      }
542  
543      function _addCollateral(
544          address from,
545          address to,
546          bool skim,
547          uint256 amount,
548          uint256 share
549      ) internal {
550          if (share == 0) {
551              share = yieldBox.toShare(collateralId, amount, false);
552          }
553          userCollateralShare[to] += share;
554          uint256 oldTotalCollateralShare = totalCollateralShare;
555          totalCollateralShare = oldTotalCollateralShare + share;
556          _addTokens(from, collateralId, share, oldTotalCollateralShare, skim);
557          emit LogAddCollateral(skim ? address(yieldBox) : from, to, share);
558      }
559  
560      function _liquidateUser(
561          address user,
562          uint256 maxBorrowPart,
563          ISwapper swapper,
564          uint256 _exchangeRate,
565          bytes calldata _dexData
566      ) private {
567          if (_isSolvent(user, _exchangeRate)) return;
568  
569          (
570              uint256 startTVLInAsset,
571              uint256 maxTVLInAsset
572          ) = _computeMaxAndMinLTVInAsset(
573                  userCollateralShare[user],
574                  _exchangeRate
575              );
576          uint256 callerReward = _getCallerReward(
577              userBorrowPart[user],
578              startTVLInAsset,
579              maxTVLInAsset
580          );
581  
582          (
583              uint256 borrowAmount,
584              uint256 borrowPart,
585              uint256 collateralShare
586          ) = _updateBorrowAndCollateralShare(user, maxBorrowPart, _exchangeRate);
587          emit LogRemoveCollateral(user, address(swapper), collateralShare);
588          emit LogRepay(address(swapper), user, borrowAmount, borrowPart);
589  
590          uint256 borrowShare = yieldBox.toShare(assetId, borrowAmount, true);
591  
592          // Closed liquidation using a pre-approved swapper
593          require(penrose.swappers(swapper), "BigBang: Invalid swapper");
594  
595          // Swaps the users collateral for the borrowed asset
596          yieldBox.transfer(
597              address(this),
598              address(swapper),
599              collateralId,
600              collateralShare
601          );
602  
603          uint256 minAssetMount = 0;
604          if (_dexData.length > 0) {
605              minAssetMount = abi.decode(_dexData, (uint256));
606          }
607  
608          uint256 balanceBefore = yieldBox.balanceOf(address(this), assetId);
609  
610          ISwapper.SwapData memory swapData = swapper.buildSwapData(
611              collateralId,
612              assetId,
613              0,
614              collateralShare,
615              true,
616              true
617          );
618          swapper.swap(swapData, minAssetMount, address(this), "");
619          uint256 balanceAfter = yieldBox.balanceOf(address(this), assetId);
620  
621          uint256 returnedShare = balanceAfter - balanceBefore;
622          (uint256 feeShare, uint256 callerShare) = _extractLiquidationFees(
623              returnedShare,
624              borrowShare,
625              callerReward
626          );
627          address[] memory _users = new address[](1);
628          _users[0] = user;
629          emit Liquidated(
630              msg.sender,
631              _users,
632              callerShare,
633              feeShare,
634              borrowAmount,
635              collateralShare
636          );
637      }
638  
639      function _extractLiquidationFees(
640          uint256 returnedShare,
641          uint256 borrowShare,
642          uint256 callerReward
643      ) private returns (uint256 feeShare, uint256 callerShare) {
644          uint256 extraShare = returnedShare - borrowShare;
645          feeShare = (extraShare * protocolFee) / FEE_PRECISION; // x% of profit goes to fee.
646          callerShare = (extraShare * callerReward) / FEE_PRECISION; //  y%  of profit goes to caller.
647  
648          yieldBox.transfer(address(this), penrose.feeTo(), assetId, feeShare);
649          yieldBox.transfer(address(this), msg.sender, assetId, callerShare);
650      }
651  
652      /// @notice Handles the liquidation of users' balances, once the users' amount of collateral is too low.
653      /// @dev Closed liquidations Only, 90% of extra shares goes to caller and 10% to protocol
654      /// @param users An array of user addresses.
655      /// @param maxBorrowParts A one-to-one mapping to `users`, contains maximum (partial) borrow amounts (to liquidate) of the respective user.
656      /// @param swapper Contract address of the `MultiSwapper` implementation. See `setSwapper`.
657      /// @param swapData Swap necessar data
658      function _closedLiquidation(
659          address[] calldata users,
660          uint256[] calldata maxBorrowParts,
661          ISwapper swapper,
662          uint256 _exchangeRate,
663          bytes calldata swapData
664      ) private {
665          uint256 liquidatedCount = 0;
666          for (uint256 i = 0; i < users.length; i++) {
667              address user = users[i];
668              if (!_isSolvent(user, _exchangeRate)) {
669                  liquidatedCount++;
670                  _liquidateUser(
671                      user,
672                      maxBorrowParts[i],
673                      swapper,
674                      _exchangeRate,
675                      swapData
676                  );
677              }
678          }
679  
680          require(liquidatedCount > 0, "SGL: no users found");
681      }
682  
683      /// @dev Helper function to move tokens.
684      /// @param from Account to debit tokens from, in `yieldBox`.
685      /// @param _tokenId The ERC-20 token asset ID in yieldBox.
686      /// @param share The amount in shares to add.
687      /// @param total Grand total amount to deduct from this contract's balance. Only applicable if `skim` is True.
688      /// Only used for accounting checks.
689      /// @param skim If True, only does a balance check on this contract.
690      /// False if tokens from msg.sender in `yieldBox` should be transferred.
691      function _addTokens(
692          address from,
693          uint256 _tokenId,
694          uint256 share,
695          uint256 total,
696          bool skim
697      ) internal {
698          if (skim) {
699              require(
700                  share <= yieldBox.balanceOf(address(this), _tokenId) - total,
701                  "BigBang: too much"
702              );
703          } else {
704              yieldBox.transfer(from, address(this), _tokenId, share);
705          }
706      }
707  
708      /// @dev Concrete implementation of `removeCollateral`.
709      function _removeCollateral(
710          address from,
711          address to,
712          uint256 share
713      ) internal {
714          userCollateralShare[from] -= share;
715          totalCollateralShare -= share;
716          emit LogRemoveCollateral(from, to, share);
717          yieldBox.transfer(address(this), to, collateralId, share);
718      }
719  
720      /// @dev Concrete implementation of `repay`.
721      function _repay(
722          address from,
723          address to,
724          uint256 part
725      ) internal returns (uint256 amount) {
726          (totalBorrow, amount) = totalBorrow.sub(part, true);
727  
728          userBorrowPart[to] -= part;
729  
730          uint256 toWithdraw = (amount - part); //acrrued
731          uint256 toBurn = amount - toWithdraw;
732          yieldBox.withdraw(assetId, from, address(this), amount, 0);
733          //burn USDO
734          if (toBurn > 0) {
735              IUSDOBase(address(asset)).burn(address(this), toBurn);
736          }
737  
738          emit LogRepay(from, to, amount, part);
739      }
740  
741      /// @dev Concrete implementation of `borrow`.
742      function _borrow(
743          address from,
744          address to,
745          uint256 amount
746      ) internal returns (uint256 part, uint256 share) {
747          uint256 feeAmount = (amount * borrowOpeningFee) / FEE_PRECISION; // A flat % fee is charged for any borrow
748  
749          (totalBorrow, part) = totalBorrow.add(amount + feeAmount, true);
750          require(
751              totalBorrowCap == 0 || totalBorrow.elastic <= totalBorrowCap,
752              "BigBang: borrow cap reached"
753          );
754  
755          userBorrowPart[from] += part;
756  
757          //mint USDO
758          IUSDOBase(address(asset)).mint(address(this), amount);
759  
760          //deposit borrowed amount to user
761          asset.approve(address(yieldBox), amount);
762          yieldBox.depositAsset(assetId, address(this), to, amount, 0);
763  
764          share = yieldBox.toShare(assetId, amount, false);
765  
766          emit LogBorrow(from, to, amount, feeAmount, part);
767      }
768  
769      function _updateBorrowAndCollateralShare(
770          address user,
771          uint256 maxBorrowPart,
772          uint256 _exchangeRate
773      )
774          private
775          returns (
776              uint256 borrowAmount,
777              uint256 borrowPart,
778              uint256 collateralShare
779          )
780      {
781          uint256 collateralPartInAsset = (yieldBox.toAmount(
782              collateralId,
783              userCollateralShare[user],
784              false
785          ) * EXCHANGE_RATE_PRECISION) / _exchangeRate;
786  
787          uint256 borrowAssetDecimals = asset.safeDecimals();
788          uint256 collateralDecimals = collateral.safeDecimals();
789  
790          uint256 availableBorrowPart = computeClosingFactor(
791              userBorrowPart[user],
792              collateralPartInAsset,
793              borrowAssetDecimals,
794              collateralDecimals,
795              FEE_PRECISION_DECIMALS
796          );
797          borrowPart = maxBorrowPart > availableBorrowPart
798              ? availableBorrowPart
799              : maxBorrowPart;
800  
801          if (borrowPart > userBorrowPart[user]) {
802              borrowPart = userBorrowPart[user];
803          }
804  
805          userBorrowPart[user] = userBorrowPart[user] - borrowPart;
806  
807          borrowAmount = totalBorrow.toElastic(borrowPart, false);
808          uint256 amountWithBonus = borrowAmount +
809              (borrowAmount * liquidationMultiplier) /
810              FEE_PRECISION;
811          collateralShare = yieldBox.toShare(
812              collateralId,
813              (amountWithBonus * _exchangeRate) / EXCHANGE_RATE_PRECISION,
814              false
815          );
816          if (collateralShare > userCollateralShare[user]) {
817              collateralShare = userCollateralShare[user];
818          }
819          userCollateralShare[user] -= collateralShare;
820          require(borrowAmount != 0, "SGL: solvent");
821  
822          totalBorrow.elastic -= uint128(borrowAmount);
823          totalBorrow.base -= uint128(borrowPart);
824      }
825: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L39-L825

File: contracts/markets/singularity/Singularity.sol

37   contract Singularity is SGLCommon {
38       using RebaseLibrary for Rebase;
39   
40       // ************ //
41       // *** VARS *** //
42       // ************ //
43       /// @notice enum representing each type of module associated with a Singularity market
44       /// @dev modules are contracts that holds a portion of the market's logic
45       enum Module {
46           Base,
47           Borrow,
48           Collateral,
49           Liquidation,
50           Leverage
51       }
52       /// @notice returns the liquidation module
53       SGLLiquidation public liquidationModule;
54       /// @notice returns the borrow module
55       SGLBorrow public borrowModule;
56       /// @notice returns the collateral module
57       SGLCollateral public collateralModule;
58       /// @notice returns the leverage module
59       SGLLeverage public leverageModule;
60   
61       /// @notice The init function that acts as a constructor
62       function init(bytes calldata data) external onlyOnce {
63           (
64               address _liquidationModule,
65               address _borrowModule,
66               address _collateralModule,
67               address _leverageModule,
68               IPenrose tapiocaBar_,
69               IERC20 _asset,
70               uint256 _assetId,
71               IERC20 _collateral,
72               uint256 _collateralId,
73               IOracle _oracle,
74               uint256 _exchangeRatePrecision
75           ) = abi.decode(
76                   data,
77                   (
78                       address,
79                       address,
80                       address,
81                       address,
82                       IPenrose,
83                       IERC20,
84                       uint256,
85                       IERC20,
86                       uint256,
87                       IOracle,
88                       uint256
89                   )
90               );
91   
92           liquidationModule = SGLLiquidation(_liquidationModule);
93           collateralModule = SGLCollateral(_collateralModule);
94           borrowModule = SGLBorrow(_borrowModule);
95           leverageModule = SGLLeverage(_leverageModule);
96           penrose = tapiocaBar_;
97           yieldBox = YieldBox(tapiocaBar_.yieldBox());
98           owner = address(penrose);
99   
100          require(
101              address(_collateral) != address(0) &&
102                  address(_asset) != address(0) &&
103                  address(_oracle) != address(0),
104              "SGL: bad pair"
105          );
106          asset = _asset;
107          collateral = _collateral;
108          assetId = _assetId;
109          collateralId = _collateralId;
110          oracle = _oracle;
111  
112          minimumInterestPerSecond = 951293760; // approx 3% APR
113          maximumInterestPerSecond = 2536783360; // approx 8% APR
114          interestElasticity = 7200e36; // Half or double in 28800 seconds (1 hours) if linear
115          startingInterestPerSecond = minimumInterestPerSecond;
116  
117          accrueInfo.interestPerSecond = uint64(startingInterestPerSecond); // 1% APR, with 1e18 being 100%
118  
119          updateExchangeRate();
120  
121          //default fees
122          callerFee = 1000; // 1%
123          protocolFee = 10000; // 10%
124          borrowOpeningFee = 50; // 0.05%
125  
126          //liquidation
127          liquidationMultiplier = 12000; //12%
128  
129          collateralizationRate = 75000;
130          lqCollateralizationRate = 25000;
131          EXCHANGE_RATE_PRECISION = _exchangeRatePrecision > 0
132              ? _exchangeRatePrecision
133              : 1e18;
134  
135          minLiquidatorReward = 1e3;
136          maxLiquidatorReward = 1e4;
137          liquidationBonusAmount = 1e4;
138  
139          minimumTargetUtilization = 3e17;
140          maximumTargetUtilization = 5e17;
141          fullUtilizationMinusMax = FULL_UTILIZATION - maximumTargetUtilization;
142      }
143  
144      // ********************** //
145      // *** VIEW FUNCTIONS *** //
146      // ********************** //
147      /// @notice transforms amount to shares for a market's permit operation
148      /// @param amount the amount to transform
149      /// @param tokenId the YieldBox asset id
150      /// @return share amount transformed into shares
151      function computeAllowedLendShare(
152          uint256 amount,
153          uint256 tokenId
154      ) external view returns (uint256 share) {
155          uint256 allShare = totalAsset.elastic +
156              yieldBox.toShare(tokenId, totalBorrow.elastic, true);
157          share = (amount * allShare) / totalAsset.base;
158      }
159  
160      /// @notice returns Total yieldBox shares for user
161      /// @param _user The user to check shares for
162      /// @param _assetId The asset id to check shares for
163      /// @return shares value
164      function yieldBoxShares(
165          address _user,
166          uint256 _assetId
167      ) external view returns (uint256) {
168          bytes32 sig = _assetId == assetId ? ASSET_SIG : COLLATERAL_SIG;
169          return
170              yieldBox.balanceOf(_user, _assetId) + _yieldBoxShares[_user][sig];
171      }
172  
173      // ************************ //
174      // *** PUBLIC FUNCTIONS *** //
175      // ************************ //
176      /// @notice Allows batched call to Singularity.
177      /// @param calls An array encoded call data.
178      /// @param revertOnFail If True then reverts after a failed call and stops doing further calls.
179      /// @return successes count of successful operations
180      /// @return results array of revert messages
181      function execute(
182          bytes[] calldata calls,
183          bool revertOnFail
184      ) external returns (bool[] memory successes, string[] memory results) {
185          successes = new bool[](calls.length);
186          results = new string[](calls.length);
187          for (uint256 i = 0; i < calls.length; i++) {
188              (bool success, bytes memory result) = address(this).delegatecall(
189                  calls[i]
190              );
191              require(success || !revertOnFail, _getRevertMsg(result));
192              successes[i] = success;
193              results[i] = _getRevertMsg(result);
194          }
195      }
196  
197      /// @notice Adds assets to the lending pair.
198      /// @param from Address to add asset from.
199      /// @param to The address of the user to receive the assets.
200      /// @param skim True if the amount should be skimmed from the deposit balance of msg.sender.
201      /// False if tokens from msg.sender in `yieldBox` should be transferred.
202      /// @param share The amount of shares to add.
203      /// @return fraction Total fractions added.
204      function addAsset(
205          address from,
206          address to,
207          bool skim,
208          uint256 share
209      ) public notPaused allowedLend(from, share) returns (uint256 fraction) {
210          _accrue();
211          fraction = _addAsset(from, to, skim, share);
212      }
213  
214      /// @notice Removes an asset from msg.sender and transfers it to `to`.
215      /// @param from Account to debit Assets from.
216      /// @param to The user that receives the removed assets.
217      /// @param fraction The amount/fraction of assets held to remove.
218      /// @return share The amount of shares transferred to `to`.
219      function removeAsset(
220          address from,
221          address to,
222          uint256 fraction
223      ) public notPaused returns (uint256 share) {
224          _accrue();
225          share = _removeAsset(from, to, fraction, true);
226          _allowedLend(from, share);
227      }
228  
229      /// @notice Adds `collateral` from msg.sender to the account `to`.
230      /// @param from Account to transfer shares from.
231      /// @param to The receiver of the tokens.
232      /// @param skim True if the amount should be skimmed from the deposit balance of msg.sender.
233      /// False if tokens from msg.sender in `yieldBox` should be transferred.
234      /// @param share The amount of shares to add for `to`.
235      function addCollateral(
236          address from,
237          address to,
238          bool skim,
239          uint256 amount,
240          uint256 share
241      ) public {
242          _executeModule(
243              Module.Collateral,
244              abi.encodeWithSelector(
245                  SGLCollateral.addCollateral.selector,
246                  from,
247                  to,
248                  skim,
249                  amount,
250                  share
251              )
252          );
253      }
254  
255      /// @notice Removes `share` amount of collateral and transfers it to `to`.
256      /// @param from Account to debit collateral from.
257      /// @param to The receiver of the shares.
258      /// @param share Amount of shares to remove.
259      function removeCollateral(address from, address to, uint256 share) public {
260          _executeModule(
261              Module.Collateral,
262              abi.encodeWithSelector(
263                  SGLCollateral.removeCollateral.selector,
264                  from,
265                  to,
266                  share
267              )
268          );
269      }
270  
271      /// @notice Sender borrows `amount` and transfers it to `to`.
272      /// @param from Account to borrow for.
273      /// @param to The receiver of borrowed tokens.
274      /// @param amount Amount to borrow.
275      /// @return part Total part of the debt held by borrowers.
276      /// @return share Total amount in shares borrowed.
277      function borrow(
278          address from,
279          address to,
280          uint256 amount
281      ) public returns (uint256 part, uint256 share) {
282          bytes memory result = _executeModule(
283              Module.Borrow,
284              abi.encodeWithSelector(SGLBorrow.borrow.selector, from, to, amount)
285          );
286          (part, share) = abi.decode(result, (uint256, uint256));
287      }
288  
289      /// @notice Repays a loan.
290      /// @param from Address to repay from.
291      /// @param to Address of the user this payment should go.
292      /// @param skim True if the amount should be skimmed from the deposit balance of msg.sender.
293      /// False if tokens from msg.sender in `yieldBox` should be transferred.
294      /// @param part The amount to repay. See `userBorrowPart`.
295      /// @return amount The total amount repayed.
296      function repay(
297          address from,
298          address to,
299          bool skim,
300          uint256 part
301      ) public returns (uint256 amount) {
302          bytes memory result = _executeModule(
303              Module.Borrow,
304              abi.encodeWithSelector(
305                  SGLBorrow.repay.selector,
306                  from,
307                  to,
308                  skim,
309                  part
310              )
311          );
312          amount = abi.decode(result, (uint256));
313      }
314  
315      /// @notice Lever down: Sell collateral to repay debt; excess goes to YB
316      /// @param from The user who sells
317      /// @param share Collateral YieldBox-shares to sell
318      /// @param minAmountOut Mininal proceeds required for the sale
319      /// @param swapper Swapper to execute the sale
320      /// @param dexData Additional data to pass to the swapper
321      /// @return amountOut Actual asset amount received in the sale
322      function sellCollateral(
323          address from,
324          uint256 share,
325          uint256 minAmountOut,
326          ISwapper swapper,
327          bytes calldata dexData
328      ) external returns (uint256 amountOut) {
329          bytes memory result = _executeModule(
330              Module.Leverage,
331              abi.encodeWithSelector(
332                  SGLLeverage.sellCollateral.selector,
333                  from,
334                  share,
335                  minAmountOut,
336                  swapper,
337                  dexData
338              )
339          );
340          amountOut = abi.decode(result, (uint256));
341      }
342  
343      /// @notice Lever up: Borrow more and buy collateral with it.
344      /// @param from The user who buys
345      /// @param borrowAmount Amount of extra asset borrowed
346      /// @param supplyAmount Amount of asset supplied (down payment)
347      /// @param minAmountOut Mininal collateral amount to receive
348      /// @param swapper Swapper to execute the purchase
349      /// @param dexData Additional data to pass to the swapper
350      /// @return amountOut Actual collateral amount purchased
351      function buyCollateral(
352          address from,
353          uint256 borrowAmount,
354          uint256 supplyAmount,
355          uint256 minAmountOut,
356          ISwapper swapper,
357          bytes calldata dexData
358      ) external returns (uint256 amountOut) {
359          bytes memory result = _executeModule(
360              Module.Leverage,
361              abi.encodeWithSelector(
362                  SGLLeverage.buyCollateral.selector,
363                  from,
364                  borrowAmount,
365                  supplyAmount,
366                  minAmountOut,
367                  swapper,
368                  dexData
369              )
370          );
371          amountOut = abi.decode(result, (uint256));
372      }
373  
374      /// @notice Level up cross-chain: Borrow more and buy collateral with it.
375      /// @param from The user who sells
376      /// @param collateralAmount Extra collateral to be added
377      /// @param borrowAmount Borrowed amount that will be swapped into collateral
378      /// @param swapData Swap data used on destination chain for swapping USDO to the underlying TOFT token
379      /// @param lzData LayerZero specific data
380      /// @param externalData External contracts used for the cross chain operation
381      function multiHopBuyCollateral(
382          address from,
383          uint256 collateralAmount,
384          uint256 borrowAmount,
385          IUSDOBase.ILeverageSwapData calldata swapData,
386          IUSDOBase.ILeverageLZData calldata lzData,
387          IUSDOBase.ILeverageExternalContractsData calldata externalData
388      ) external payable {
389          _executeModule(
390              Module.Leverage,
391              abi.encodeWithSelector(
392                  SGLLeverage.multiHopBuyCollateral.selector,
393                  from,
394                  collateralAmount,
395                  borrowAmount,
396                  swapData,
397                  lzData,
398                  externalData
399              )
400          );
401      }
402  
403      /// @notice Level up cross-chain: Borrow more and buy collateral with it.
404      /// @param from The user who sells
405      /// @param share Collateral YieldBox-shares to sell
406      /// @param swapData Swap data used on destination chain for swapping USDO to the underlying TOFT token
407      /// @param lzData LayerZero specific data
408      /// @param externalData External contracts used for the cross chain operation
409      function multiHopSellCollateral(
410          address from,
411          uint256 share,
412          IUSDOBase.ILeverageSwapData calldata swapData,
413          IUSDOBase.ILeverageLZData calldata lzData,
414          IUSDOBase.ILeverageExternalContractsData calldata externalData
415      ) external payable {
416          _executeModule(
417              Module.Leverage,
418              abi.encodeWithSelector(
419                  SGLLeverage.multiHopSellCollateral.selector,
420                  from,
421                  share,
422                  swapData,
423                  lzData,
424                  externalData
425              )
426          );
427      }
428  
429      /// @notice Entry point for liquidations.
430      /// @dev Will call `closedLiquidation()` if not LQ exists or no LQ bid avail exists. Otherwise use LQ.
431      /// @param users An array of user addresses.
432      /// @param maxBorrowParts A one-to-one mapping to `users`, contains maximum (partial) borrow amounts (to liquidate) of the respective user.
433      ///        Ignore for `orderBookLiquidation()`
434      /// @param swapper Contract address of the `MultiSwapper` implementation. See `setSwapper`.
435      ///        Ignore for `orderBookLiquidation()`
436      /// @param collateralToAssetSwapData Extra swap data
437      ///        Ignore for `orderBookLiquidation()`
438      /// @param usdoToBorrowedSwapData Extra swap data
439      ///        Ignore for `closedLiquidation()`
440      function liquidate(
441          address[] calldata users,
442          uint256[] calldata maxBorrowParts,
443          ISwapper swapper,
444          bytes calldata collateralToAssetSwapData,
445          bytes calldata usdoToBorrowedSwapData
446      ) external {
447          _executeModule(
448              Module.Liquidation,
449              abi.encodeWithSelector(
450                  SGLLiquidation.liquidate.selector,
451                  users,
452                  maxBorrowParts,
453                  swapper,
454                  collateralToAssetSwapData,
455                  usdoToBorrowedSwapData
456              )
457          );
458      }
459  
460      /// @notice Withdraw the fees accumulated in `accrueInfo.feesEarnedFraction` to the balance of `feeTo`.
461      function withdrawFeesEarned() public {
462          _accrue();
463          address _feeTo = penrose.feeTo();
464          uint256 _feesEarnedFraction = accrueInfo.feesEarnedFraction;
465          balanceOf[_feeTo] += _feesEarnedFraction;
466          emit Transfer(address(0), _feeTo, _feesEarnedFraction);
467          accrueInfo.feesEarnedFraction = 0;
468          emit LogWithdrawFees(_feeTo, _feesEarnedFraction);
469      }
470  
471      // *********************** //
472      // *** OWNER FUNCTIONS *** //
473      // *********************** //
474      /// @notice Transfers fees to penrose
475      /// @dev can only be called by the owner
476      /// @param feeTo fees receiver
477      function refreshPenroseFees(
478          address feeTo
479      ) external onlyOwner notPaused returns (uint256 feeShares) {
480          if (accrueInfo.feesEarnedFraction > 0) {
481              withdrawFeesEarned();
482          }
483  
484          feeShares = _removeAsset(feeTo, msg.sender, balanceOf[feeTo], false);
485      }
486  
487      /// @notice sets Singularity specific configuration
488      /// @dev values are updated only if > 0 or not address(0)
489      function setSingularityConfig(
490          uint256 _lqCollateralizationRate,
491          uint256 _liquidationMultiplier,
492          uint256 _minimumTargetUtilization,
493          uint256 _maximumTargetUtilization,
494          uint64 _minimumInterestPerSecond,
495          uint64 _maximumInterestPerSecond,
496          uint256 _interestElasticity
497      ) external onlyOwner {
498          if (_minimumTargetUtilization > 0) {
499              emit MinimumTargetUtilizationUpdated(
500                  minimumTargetUtilization,
501                  _minimumTargetUtilization
502              );
503              minimumTargetUtilization = _minimumTargetUtilization;
504          }
505  
506          if (_maximumTargetUtilization > 0) {
507              require(
508                  _maximumTargetUtilization < FULL_UTILIZATION,
509                  "SGL: not valid"
510              );
511              emit MaximumTargetUtilizationUpdated(
512                  maximumTargetUtilization,
513                  _maximumTargetUtilization
514              );
515              maximumTargetUtilization = _maximumTargetUtilization;
516              fullUtilizationMinusMax =
517                  FULL_UTILIZATION -
518                  maximumTargetUtilization;
519          }
520  
521          if (_minimumInterestPerSecond > 0) {
522              require(
523                  _minimumInterestPerSecond < maximumInterestPerSecond,
524                  "SGL: not valid"
525              );
526              emit MinimumInterestPerSecondUpdated(
527                  minimumInterestPerSecond,
528                  _minimumInterestPerSecond
529              );
530              minimumInterestPerSecond = _minimumInterestPerSecond;
531          }
532  
533          if (_maximumInterestPerSecond > 0) {
534              require(
535                  _maximumInterestPerSecond > minimumInterestPerSecond,
536                  "SGL: not valid"
537              );
538              emit MaximumInterestPerSecondUpdated(
539                  maximumInterestPerSecond,
540                  _maximumInterestPerSecond
541              );
542              maximumInterestPerSecond = _maximumInterestPerSecond;
543          }
544  
545          if (_interestElasticity > 0) {
546              emit InterestElasticityUpdated(
547                  interestElasticity,
548                  _interestElasticity
549              );
550              interestElasticity = _interestElasticity;
551          }
552  
553          if (_lqCollateralizationRate > 0) {
554              require(
555                  _lqCollateralizationRate <= FEE_PRECISION,
556                  "SGL: not valid"
557              );
558              emit LqCollateralizationRateUpdated(
559                  lqCollateralizationRate,
560                  _lqCollateralizationRate
561              );
562              lqCollateralizationRate = _lqCollateralizationRate;
563          }
564  
565          if (_liquidationMultiplier > 0) {
566              require(_liquidationMultiplier < FEE_PRECISION, "SGL: not valid");
567              emit LiquidationMultiplierUpdated(
568                  liquidationMultiplier,
569                  _liquidationMultiplier
570              );
571              liquidationMultiplier = _liquidationMultiplier;
572          }
573      }
574  
575      /// @notice sets LQ specific confinguration
576      function setLiquidationQueueConfig(
577          ILiquidationQueue _liquidationQueue,
578          address _bidExecutionSwapper,
579          address _usdoSwapper
580      ) external onlyOwner {
581          if (address(_liquidationQueue) != address(0)) {
582              require(_liquidationQueue.onlyOnce(), "SGL: LQ not initalized");
583              liquidationQueue = _liquidationQueue;
584          }
585  
586          if (_bidExecutionSwapper != address(0)) {
587              emit BidExecutionSwapperUpdated(_bidExecutionSwapper);
588              liquidationQueue.setBidExecutionSwapper(_bidExecutionSwapper);
589          }
590  
591          if (_usdoSwapper != address(0)) {
592              emit UsdoSwapperUpdated(_usdoSwapper);
593              liquidationQueue.setUsdoSwapper(_usdoSwapper);
594          }
595      }
596  
597      // ************************* //
598      // *** PRIVATE FUNCTIONS *** //
599      // ************************* //
600      function _extractModule(Module _module) private view returns (address) {
601          address module;
602          if (_module == Module.Borrow) {
603              module = address(borrowModule);
604          } else if (_module == Module.Collateral) {
605              module = address(collateralModule);
606          } else if (_module == Module.Liquidation) {
607              module = address(liquidationModule);
608          } else if (_module == Module.Leverage) {
609              module = address(leverageModule);
610          }
611          if (module == address(0)) {
612              revert("SGL: module not set");
613          }
614  
615          return module;
616      }
617  
618      function _executeModule(
619          Module _module,
620          bytes memory _data
621      ) private returns (bytes memory returnData) {
622          bool success = true;
623          address module = _extractModule(_module);
624  
625          (success, returnData) = module.delegatecall(_data);
626          if (!success) {
627              revert(_getRevertMsg(returnData));
628          }
629      }
630  
631      function _executeViewModule(
632          Module _module,
633          bytes memory _data
634      ) private view returns (bytes memory returnData) {
635          bool success = true;
636          address module = _extractModule(_module);
637  
638          (success, returnData) = module.staticcall(_data);
639          if (!success) {
640              revert(_getRevertMsg(returnData));
641          }
642      }
643  
644      receive() external payable {}
645: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L37-L645

File: contracts/usd0/BaseUSDO.sol

46   contract BaseUSDO is BaseUSDOStorage, ERC20Permit {
47       using SafeERC20 for IERC20;
48       using BytesLib for bytes;
49       // ************ //
50       // *** VARS *** //
51       // ************ //
52       enum Module {
53           Leverage,
54           Market,
55           Options
56       }
57   
58       /// @notice returns the leverage module
59       USDOLeverageModule public leverageModule;
60   
61       /// @notice returns the market module
62       USDOMarketModule public marketModule;
63   
64       /// @notice returns the options module
65       USDOOptionsModule public optionsModule;
66   
67       constructor(
68           address _lzEndpoint,
69           IYieldBoxBase _yieldBox,
70           address _owner,
71           address payable _leverageModule,
72           address payable _marketModule,
73           address payable _optionsModule
74       ) BaseUSDOStorage(_lzEndpoint, _yieldBox) ERC20Permit("USDO") {
75           leverageModule = USDOLeverageModule(_leverageModule);
76           marketModule = USDOMarketModule(_marketModule);
77           optionsModule = USDOOptionsModule(_optionsModule);
78   
79           transferOwnership(_owner);
80       }
81   
82       // *********************** //
83       // *** OWNER FUNCTIONS *** //
84       // *********************** //
85       /// @notice set the max allowed USDO mintable through flashloan
86       /// @dev can only be called by the owner
87       /// @param _val the new amount
88       function setMaxFlashMintable(uint256 _val) external onlyOwner {
89           emit MaxFlashMintUpdated(maxFlashMint, _val);
90           maxFlashMint = _val;
91       }
92   
93       /// @notice set the flashloan fee
94       /// @dev can only be called by the owner
95       /// @param _val the new fee
96       function setFlashMintFee(uint256 _val) external onlyOwner {
97           require(_val < FLASH_MINT_FEE_PRECISION, "USDO: fee too big");
98           emit FlashMintFeeUpdated(flashMintFee, _val);
99           flashMintFee = _val;
100      }
101  
102      /// @notice set the Conservator address
103      /// @dev conservator can pause the contract
104      /// @param _conservator the new address
105      function setConservator(address _conservator) external onlyOwner {
106          require(_conservator != address(0), "USDO: address not valid");
107          emit ConservatorUpdated(conservator, _conservator);
108          conservator = _conservator;
109      }
110  
111      /// @notice updates the pause state of the contract
112      /// @dev can only be called by the conservator
113      /// @param val the new value
114      function updatePause(bool val) external {
115          require(msg.sender == conservator, "USDO: unauthorized");
116          require(val != paused, "USDO: same state");
117          emit PausedUpdated(paused, val);
118          paused = val;
119      }
120  
121      /// @notice sets/unsets address as minter
122      /// @dev can only be called by the owner
123      /// @param _for role receiver
124      /// @param _status true/false
125      function setMinterStatus(address _for, bool _status) external onlyOwner {
126          allowedMinter[_getChainId()][_for] = _status;
127          emit SetMinterStatus(_for, _status);
128      }
129  
130      /// @notice sets/unsets address as burner
131      /// @dev can only be called by the owner
132      /// @param _for role receiver
133      /// @param _status true/false
134      function setBurnerStatus(address _for, bool _status) external onlyOwner {
135          allowedBurner[_getChainId()][_for] = _status;
136          emit SetBurnerStatus(_for, _status);
137      }
138  
139      // ************************ //
140      // *** VIEW FUNCTIONS *** //
141      // ************************ //
142      /// @notice returns token's decimals
143      function decimals() public pure override returns (uint8) {
144          return 18;
145      }
146  
147      // ************************ //
148      // *** PUBLIC FUNCTIONS *** //
149      // ************************ //
150  
151      /// @notice triggers a sendFrom to another layer from destination
152      /// @param lzDstChainId LZ destination id
153      /// @param airdropAdapterParams airdrop params
154      /// @param zroPaymentAddress ZRO payment address
155      /// @param amount amount to send back
156      /// @param sendFromData data needed to trigger sendFrom on destination
157      /// @param approvals approvals array
158      function triggerSendFrom(
159          uint16 lzDstChainId,
160          bytes calldata airdropAdapterParams,
161          address zroPaymentAddress,
162          uint256 amount,
163          ISendFrom.LzCallParams calldata sendFromData,
164          ICommonData.IApproval[] calldata approvals
165      ) external payable {
166          _executeModule(
167              Module.Options,
168              abi.encodeWithSelector(
169                  USDOOptionsModule.triggerSendFrom.selector,
170                  lzDstChainId,
171                  airdropAdapterParams,
172                  zroPaymentAddress,
173                  amount,
174                  sendFromData,
175                  approvals
176              ),
177              false
178          );
179      }
180  
181      /// @notice Exercise an oTAP position
182      /// @param optionsData oTap exerciseOptions data
183      /// @param lzData data needed for the cross chain transer
184      /// @param tapSendData needed for withdrawing Tap token
185      /// @param approvals array
186      function exerciseOption(
187          ITapiocaOptionsBrokerCrossChain.IExerciseOptionsData
188              calldata optionsData,
189          ITapiocaOptionsBrokerCrossChain.IExerciseLZData calldata lzData,
190          ITapiocaOptionsBrokerCrossChain.IExerciseLZSendTapData
191              calldata tapSendData,
192          ICommonData.IApproval[] calldata approvals
193      ) external payable {
194          _executeModule(
195              Module.Options,
196              abi.encodeWithSelector(
197                  USDOOptionsModule.exerciseOption.selector,
198                  optionsData,
199                  lzData,
200                  tapSendData,
201                  approvals
202              ),
203              false
204          );
205      }
206  
207      /// @notice inits multiHopBuyCollateral
208      /// @param from The user who sells
209      /// @param collateralAmount Extra collateral to be added
210      /// @param borrowAmount Borrowed amount that will be swapped into collateral
211      /// @param swapData Swap data used on destination chain for swapping USDO to the underlying TOFT token
212      /// @param lzData LayerZero specific data
213      /// @param externalData External contracts used for the cross chain operation
214      /// @param approvals array
215      function initMultiHopBuy(
216          address from,
217          uint256 collateralAmount,
218          uint256 borrowAmount,
219          IUSDOBase.ILeverageSwapData calldata swapData,
220          IUSDOBase.ILeverageLZData calldata lzData,
221          IUSDOBase.ILeverageExternalContractsData calldata externalData,
222          bytes calldata airdropAdapterParams,
223          ICommonData.IApproval[] memory approvals
224      ) external payable {
225          _executeModule(
226              Module.Leverage,
227              abi.encodeWithSelector(
228                  USDOLeverageModule.initMultiHopBuy.selector,
229                  from,
230                  collateralAmount,
231                  borrowAmount,
232                  swapData,
233                  lzData,
234                  externalData,
235                  airdropAdapterParams,
236                  approvals
237              ),
238              false
239          );
240      }
241  
242      /// @notice calls removeAssetAndRepay on Magnetar from the destination layer
243      /// @param from sending address
244      /// @param to receiver address
245      /// @param lzDstChainId LayerZero destination chain id
246      /// @param zroPaymentAddress ZRO payment address
247      /// @param adapterParams LZ adapter params
248      /// @param externalData external addresses needed for the operation
249      /// @param removeAndRepayData removeAssetAndRepay params
250      /// @param approvals approvals params
251      function removeAsset(
252          address from,
253          address to,
254          uint16 lzDstChainId,
255          address zroPaymentAddress,
256          bytes calldata adapterParams,
257          ICommonData.ICommonExternalContracts calldata externalData,
258          IUSDOBase.IRemoveAndRepay calldata removeAndRepayData,
259          ICommonData.IApproval[] calldata approvals
260      ) external payable {
261          _executeModule(
262              Module.Market,
263              abi.encodeWithSelector(
264                  USDOMarketModule.removeAsset.selector,
265                  from,
266                  to,
267                  lzDstChainId,
268                  zroPaymentAddress,
269                  adapterParams,
270                  externalData,
271                  removeAndRepayData,
272                  approvals
273              ),
274              false
275          );
276      }
277  
278      /// @notice sends USDO to a specific chain and performs a leverage up operation
279      /// @param amount the amount to use
280      /// @param leverageFor the receiver address
281      /// @param lzData LZ specific data
282      /// @param swapData ISwapper specific data
283      /// @param externalData external contracts used for the flow
284      function sendForLeverage(
285          uint256 amount,
286          address leverageFor,
287          IUSDOBase.ILeverageLZData calldata lzData,
288          IUSDOBase.ILeverageSwapData calldata swapData,
289          IUSDOBase.ILeverageExternalContractsData calldata externalData
290      ) external payable {
291          _executeModule(
292              Module.Leverage,
293              abi.encodeWithSelector(
294                  USDOLeverageModule.sendForLeverage.selector,
295                  amount,
296                  leverageFor,
297                  lzData,
298                  swapData,
299                  externalData
300              ),
301              false
302          );
303      }
304  
305      /// @notice sends to YieldBox over layer and lends asset to market
306      /// @param _from sending address
307      /// @param _to receiver address
308      /// @param lzDstChainId LayerZero destination chain id
309      /// @param lendParams lend specific params
310      /// @param approvals approvals specific params
311      /// @param withdrawParams parameter to withdraw the SGL collateral
312      /// @param adapterParams adapter params of the withdrawn collateral
313      function sendAndLendOrRepay(
314          address _from,
315          address _to,
316          uint16 lzDstChainId,
317          address zroPaymentAddress,
318          IUSDOBase.ILendOrRepayParams calldata lendParams,
319          ICommonData.IApproval[] calldata approvals,
320          ICommonData.IWithdrawParams calldata withdrawParams,
321          bytes calldata adapterParams
322      ) external payable {
323          _executeModule(
324              Module.Market,
325              abi.encodeWithSelector(
326                  USDOMarketModule.sendAndLendOrRepay.selector,
327                  _from,
328                  _to,
329                  lzDstChainId,
330                  zroPaymentAddress,
331                  lendParams,
332                  approvals,
333                  withdrawParams,
334                  adapterParams
335              ),
336              false
337          );
338      }
339  
340      // ************************* //
341      // *** PRIVATE FUNCTIONS *** //
342      // ************************* //
343  
344      function _extractModule(Module _module) private view returns (address) {
345          address module;
346          if (_module == Module.Leverage) {
347              module = address(leverageModule);
348          } else if (_module == Module.Market) {
349              module = address(marketModule);
350          } else if (_module == Module.Options) {
351              module = address(optionsModule);
352          }
353  
354          if (module == address(0)) {
355              revert("USDO: module not found");
356          }
357  
358          return module;
359      }
360  
361      function _executeModule(
362          Module _module,
363          bytes memory _data,
364          bool _forwardRevert
365      ) private returns (bool success, bytes memory returnData) {
366          success = true;
367          address module = _extractModule(_module);
368  
369          (success, returnData) = module.delegatecall(_data);
370          if (!success && !_forwardRevert) {
371              revert(_getRevertMsg(returnData));
372          }
373      }
374  
375      function _executeOnDestination(
376          Module _module,
377          bytes memory _data,
378          uint16 _srcChainId,
379          bytes memory _srcAddress,
380          uint64 _nonce,
381          bytes memory _payload
382      ) private {
383          (bool success, bytes memory returnData) = _executeModule(
384              _module,
385              _data,
386              true
387          );
388          if (!success) {
389              _storeFailedMessage(
390                  _srcChainId,
391                  _srcAddress,
392                  _nonce,
393                  _payload,
394                  returnData
395              );
396          }
397      }
398  
399      function _nonblockingLzReceive(
400          uint16 _srcChainId,
401          bytes memory _srcAddress,
402          uint64 _nonce,
403          bytes memory _payload
404      ) internal virtual override {
405          uint256 packetType = _payload.toUint256(0);
406  
407          if (packetType == PT_YB_SEND_SGL_LEND_OR_REPAY) {
408              _executeOnDestination(
409                  Module.Market,
410                  abi.encodeWithSelector(
411                      USDOMarketModule.lend.selector,
412                      marketModule,
413                      _srcChainId,
414                      _srcAddress,
415                      _nonce,
416                      _payload
417                  ),
418                  _srcChainId,
419                  _srcAddress,
420                  _nonce,
421                  _payload
422              );
423          } else if (packetType == PT_LEVERAGE_MARKET_UP) {
424              _executeOnDestination(
425                  Module.Leverage,
426                  abi.encodeWithSelector(
427                      USDOLeverageModule.leverageUp.selector,
428                      leverageModule,
429                      _srcChainId,
430                      _srcAddress,
431                      _nonce,
432                      _payload
433                  ),
434                  _srcChainId,
435                  _srcAddress,
436                  _nonce,
437                  _payload
438              );
439          } else if (packetType == PT_MARKET_REMOVE_ASSET) {
440              _executeOnDestination(
441                  Module.Market,
442                  abi.encodeWithSelector(
443                      USDOMarketModule.remove.selector,
444                      _payload
445                  ),
446                  _srcChainId,
447                  _srcAddress,
448                  _nonce,
449                  _payload
450              );
451          } else if (packetType == PT_MARKET_MULTIHOP_BUY) {
452              _executeOnDestination(
453                  Module.Leverage,
454                  abi.encodeWithSelector(
455                      USDOLeverageModule.multiHop.selector,
456                      _payload
457                  ),
458                  _srcChainId,
459                  _srcAddress,
460                  _nonce,
461                  _payload
462              );
463          } else if (packetType == PT_TAP_EXERCISE) {
464              _executeOnDestination(
465                  Module.Options,
466                  abi.encodeWithSelector(
467                      USDOOptionsModule.exercise.selector,
468                      optionsModule,
469                      _srcChainId,
470                      _srcAddress,
471                      _nonce,
472                      _payload
473                  ),
474                  _srcChainId,
475                  _srcAddress,
476                  _nonce,
477                  _payload
478              );
479          } else if (packetType == PT_SEND_FROM) {
480              _executeOnDestination(
481                  Module.Options,
482                  abi.encodeWithSelector(
483                      USDOOptionsModule.sendFromDestination.selector,
484                      _payload
485                  ),
486                  _srcChainId,
487                  _srcAddress,
488                  _nonce,
489                  _payload
490              );
491          } else {
492              packetType = _payload.toUint8(0);
493              if (packetType == PT_SEND) {
494                  _sendAck(_srcChainId, _srcAddress, _nonce, _payload);
495              } else if (packetType == PT_SEND_AND_CALL) {
496                  _sendAndCallAck(_srcChainId, _srcAddress, _nonce, _payload);
497              } else {
498                  revert("OFTCoreV2: unknown packet type");
499              }
500          }
501      }
502: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDO.sol#L46-L502

File: contracts/Balancer.sol

34   contract Balancer is Owned {
35       // ************ //
36       // *** VARS *** //
37       // ************ //
38       /// @notice current OFT => chain => destination OFT
39       /// @dev chain ids (https://stargateprotocol.gitbook.io/stargate/developers/chain-ids):
40       ///         - Ethereum: 101
41       ///         - BNB: 102
42       ///         - Avalanche: 106
43       ///         - Polygon: 109
44       ///         - Arbitrum: 110
45       ///         - Optimism: 111
46       ///         - Fantom: 112
47       ///         - Metis: 151
48       ///     pool ids https://stargateprotocol.gitbook.io/stargate/developers/pool-ids
49       mapping(address => mapping(uint16 => OFTData)) public connectedOFTs;
50   
51       struct OFTData {
52           uint256 srcPoolId;
53           uint256 dstPoolId;
54           address dstOft;
55           uint256 rebalanceable;
56       }
57   
58       /// @notice StargetETH router address
59       IStargateRouter public immutable routerETH;
60       /// @notice Stargate router address
61       IStargateRouter public immutable router;
62   
63       uint256 private constant SLIPPAGE_PRECISION = 1e5;
64   
65       // ************************ //
66       // *** EVENTS FUNCTIONS *** //
67       // ************************ //
68       /// @notice event emitted when mTapiocaOFT is initialized
69       event ConnectedChainUpdated(
70           address indexed _srcOft,
71           uint16 _dstChainId,
72           address indexed _dstOft
73       );
74       /// @notice event emitted when a rebalance operation is performed
75       /// @dev rebalancing means sending an amount of the underlying token to one of the connected chains
76       event Rebalanced(
77           address indexed _srcOft,
78           uint16 _dstChainId,
79           uint256 _slippage,
80           uint256 _amount,
81           bool _isNative
82       );
83       /// @notice event emitted when max rebalanceable amount is updated
84       event RebalanceAmountUpdated(
85           address _srcOft,
86           uint16 _dstChainId,
87           uint256 _amount,
88           uint256 _totalAmount
89       );
90   
91       // ************************ //
92       // *** ERRORS FUNCTIONS *** //
93       // ************************ //
94       /// @notice error thrown when IStargetRouter address is not valid
95       error RouterNotValid();
96       /// @notice error thrown when value exceeds balance
97       error ExceedsBalance();
98       /// @notice error thrown when chain destination is not valid
99       error DestinationNotValid();
100      /// @notice error thrown when dex slippage is not valid
101      error SlippageNotValid();
102      /// @notice error thrown when fee amount is not set
103      error FeeAmountNotSet();
104      error PoolInfoRequired();
105      error RebalanceAmountNotSet();
106      error DestinationOftNotValid();
107  
108      // *************************** //
109      // *** MODIFIERS FUNCTIONS *** //
110      // *************************** //
111      modifier onlyValidDestination(address _srcOft, uint16 _dstChainId) {
112          if (connectedOFTs[_srcOft][_dstChainId].dstOft == address(0))
113              revert DestinationNotValid();
114          _;
115      }
116  
117      modifier onlyValidSlippage(uint256 _slippage) {
118          if (_slippage >= 1e5) revert SlippageNotValid();
119          _;
120      }
121  
122      constructor(
123          address _routerETH,
124          address _router,
125          address _owner
126      ) Owned(_owner) {
127          if (_router == address(0)) revert RouterNotValid();
128          if (_routerETH == address(0)) revert RouterNotValid();
129          routerETH = IStargateRouter(_routerETH);
130          router = IStargateRouter(_router);
131      }
132  
133      // ************************ //
134      // *** PUBLIC FUNCTIONS *** //
135      // ************************ //
136  
137      function checker(
138          address payable _srcOft,
139          uint16 _dstChainId
140      ) external view returns (bool canExec, bytes memory execPayload) {
141          bytes memory ercData;
142          if (ITapiocaOFT(_srcOft).erc20() == address(0)) {
143              ercData = abi.encode(
144                  connectedOFTs[_srcOft][_dstChainId].srcPoolId,
145                  connectedOFTs[_srcOft][_dstChainId].dstPoolId
146              );
147          }
148  
149          canExec = connectedOFTs[_srcOft][_dstChainId].rebalanceable > 0;
150          execPayload = abi.encodeCall(
151              Balancer.rebalance,
152              (
153                  _srcOft,
154                  _dstChainId,
155                  1e3, //1% slippage
156                  connectedOFTs[_srcOft][_dstChainId].rebalanceable,
157                  ercData
158              )
159          );
160      }
161  
162      // *********************** //
163      // *** OWNER FUNCTIONS *** //
164      // *********************** //
165      /// @notice performs a rebalance operation
166      /// @dev callable only by the owner
167      /// @param _srcOft the source TOFT address
168      /// @param _dstChainId the destination LayerZero id
169      /// @param _slippage the destination LayerZero id
170      /// @param _amount the rebalanced amount
171      /// @param _ercData custom send data
172      function rebalance(
173          address payable _srcOft,
174          uint16 _dstChainId,
175          uint256 _slippage,
176          uint256 _amount,
177          bytes memory _ercData
178      )
179          external
180          payable
181          onlyOwner
182          onlyValidDestination(_srcOft, _dstChainId)
183          onlyValidSlippage(_slippage)
184      {
185          if (connectedOFTs[_srcOft][_dstChainId].rebalanceable < _amount)
186              revert RebalanceAmountNotSet();
187  
188          //check if OFT is still valid
189          if (
190              !_isValidOft(
191                  _srcOft,
192                  connectedOFTs[_srcOft][_dstChainId].dstOft,
193                  _dstChainId
194              )
195          ) revert DestinationOftNotValid();
196  
197          //extract
198          ITapiocaOFT(_srcOft).extractUnderlying(_amount);
199  
200          //send
201          bool _isNative = ITapiocaOFT(_srcOft).erc20() == address(0);
202          if (_isNative) {
203              if (msg.value <= _amount) revert FeeAmountNotSet();
204              _sendNative(_srcOft, _amount, _dstChainId, _slippage);
205          } else {
206              if (msg.value == 0) revert FeeAmountNotSet();
207              _sendToken(_srcOft, _amount, _dstChainId, _slippage, _ercData);
208          }
209  
210          connectedOFTs[_srcOft][_dstChainId].rebalanceable -= _amount;
211          emit Rebalanced(_srcOft, _dstChainId, _slippage, _amount, _isNative);
212      }
213  
214      /// @notice registeres mTapiocaOFT for rebalancing
215      /// @param _srcOft the source TOFT address
216      /// @param _dstChainId the destination LayerZero id
217      /// @param _dstOft the destination TOFT address
218      /// @param _ercData custom send data
219      function initConnectedOFT(
220          address _srcOft,
221          uint16 _dstChainId,
222          address _dstOft,
223          bytes memory _ercData
224      ) external onlyOwner {
225          bool isNative = ITapiocaOFT(_srcOft).erc20() == address(0);
226          if (!isNative && _ercData.length == 0) revert PoolInfoRequired();
227          if (!_isValidOft(_srcOft, _dstOft, _dstChainId))
228              revert DestinationOftNotValid();
229  
230          (uint256 _srcPoolId, uint256 _dstPoolId) = abi.decode(
231              _ercData,
232              (uint256, uint256)
233          );
234  
235          OFTData memory oftData = OFTData({
236              srcPoolId: _srcPoolId,
237              dstPoolId: _dstPoolId,
238              dstOft: _dstOft,
239              rebalanceable: 0
240          });
241  
242          connectedOFTs[_srcOft][_dstChainId] = oftData;
243          emit ConnectedChainUpdated(_srcOft, _dstChainId, _dstOft);
244      }
245  
246      /// @notice assings more rebalanceable amount for TOFT
247      /// @param _srcOft the source TOFT address
248      /// @param _dstChainId the destination LayerZero id
249      /// @param _amount the rebalanced amount
250      function addRebalanceAmount(
251          address _srcOft,
252          uint16 _dstChainId,
253          uint256 _amount
254      ) external onlyValidDestination(_srcOft, _dstChainId) onlyOwner {
255          connectedOFTs[_srcOft][_dstChainId].rebalanceable += _amount;
256          emit RebalanceAmountUpdated(
257              _srcOft,
258              _dstChainId,
259              _amount,
260              connectedOFTs[_srcOft][_dstChainId].rebalanceable
261          );
262      }
263  
264      // ************************* //
265      // *** PRIVATE FUNCTIONS *** //
266      // ************************* //
267      function _isValidOft(
268          address _srcOft,
269          address _dstOft,
270          uint16 _dstChainId
271      ) private view returns (bool) {
272          bytes memory trustedRemotePath = abi.encodePacked(_dstOft, _srcOft);
273          return
274              ITapiocaOFT(_srcOft).isTrustedRemote(
275                  _dstChainId,
276                  trustedRemotePath
277              );
278      }
279  
280      function _sendNative(
281          address payable _oft,
282          uint256 _amount,
283          uint16 _dstChainId,
284          uint256 _slippage
285      ) private {
286          if (address(this).balance < _amount) revert ExceedsBalance();
287  
288          routerETH.swapETH(
289              _dstChainId,
290              _oft, //refund
291              abi.encodePacked(connectedOFTs[_oft][_dstChainId].dstOft),
292              _amount,
293              _computeMinAmount(_amount, _slippage)
294          );
295      }
296  
297      function _sendToken(
298          address payable _oft,
299          uint256 _amount,
300          uint16 _dstChainId,
301          uint256 _slippage,
302          bytes memory _data
303      ) private {
304          IERC20Metadata erc20 = IERC20Metadata(ITapiocaOFT(_oft).erc20());
305          if (erc20.balanceOf(address(this)) < _amount) revert ExceedsBalance();
306  
307          (uint256 _srcPoolId, uint256 _dstPoolId) = abi.decode(
308              _data,
309              (uint256, uint256)
310          );
311  
312          IStargateRouter.lzTxObj memory _lzTxParams = IStargateRouterBase
313              .lzTxObj({
314                  dstGasForCall: 0,
315                  dstNativeAmount: msg.value,
316                  dstNativeAddr: abi.encode(
317                      connectedOFTs[_oft][_dstChainId].dstOft
318                  )
319              });
320  
321          erc20.approve(address(router), _amount);
322          router.swap(
323              _dstChainId,
324              _srcPoolId,
325              _dstPoolId,
326              _oft, //refund,
327              _amount,
328              _computeMinAmount(_amount, _slippage),
329              _lzTxParams,
330              _lzTxParams.dstNativeAddr,
331              "0x"
332          );
333      }
334  
335      function _computeMinAmount(
336          uint256 _amount,
337          uint256 _slippage
338      ) private pure returns (uint256) {
339          return _amount - ((_amount * _slippage) / SLIPPAGE_PRECISION);
340      }
341  
342      receive() external payable {}
343: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L34-L343

File: contracts/TapiocaWrapper.sol

26   contract TapiocaWrapper is Ownable {
27       struct ExecutionCall {
28           address toft;
29           bytes bytecode;
30           bool revertOnFailure;
31       }
32   
33       // ************ //
34       // *** VARS *** //
35       // ************ //
36       /// @notice Array of deployed TOFT contracts.
37       ITapiocaOFT[] public tapiocaOFTs;
38       /// @notice Array of harvestable TOFT fees.
39       ITapiocaOFT[] private harvestableTapiocaOFTs;
40       /// @notice Map of deployed TOFT contracts by ERC20.
41       mapping(address => ITapiocaOFT) public tapiocaOFTsByErc20;
42   
43       // ************** //
44       // *** EVENTS *** //
45       // ************** //
46       /// @notice Called when a new OFT is deployed.
47       event CreateOFT(ITapiocaOFT indexed _tapiocaOFT, address indexed _erc20);
48       /// @notice Called when fees are harvested.
49       event HarvestFees(address indexed _caller);
50       /// @notice Called when fees are changed.
51       event SetFees(uint256 _newFee);
52   
53       // ************** //
54       // *** ERRORS *** //
55       // ************** //
56       /// @notice If the TOFT is already deployed.
57       error TapiocaWrapper__AlreadyDeployed(address _erc20);
58       /// @notice Failed to deploy the TapiocaWrapper contract.
59       error TapiocaWrapper__FailedDeploy();
60       /// @notice The management fee is too high. Currently set to a max of 50 BPS or 0.5%.
61       error TapiocaWrapper__MngmtFeeTooHigh();
62       /// @notice The TapiocaOFT execution failed.
63       error TapiocaWrapper__TOFTExecutionFailed(bytes message);
64       /// @notice No TOFT has been deployed yet.
65       error TapiocaWrapper__NoTOFTDeployed();
66   
67       constructor(address _owner) {
68           _transferOwnership(_owner);
69       }
70   
71       // ********************** //
72       // *** VIEW FUNCTIONS *** //
73       // ********************** //
74       /// @notice Return the number of TOFT contracts deployed on the current chain.
75       function tapiocaOFTLength() external view returns (uint256) {
76           return tapiocaOFTs.length;
77       }
78   
79       /// @notice Return the number of harvestable TOFT contracts deployed on the current chain.
80       function harvestableTapiocaOFTsLength() external view returns (uint256) {
81           return harvestableTapiocaOFTs.length;
82       }
83   
84       /// @notice Return the latest TOFT contract deployed on the current chain.
85       function lastTOFT() external view returns (ITapiocaOFT) {
86           if (tapiocaOFTs.length == 0) {
87               revert TapiocaWrapper__NoTOFTDeployed();
88           }
89           return tapiocaOFTs[tapiocaOFTs.length - 1];
90       }
91   
92       // ************************ //
93       // *** PUBLIC FUNCTIONS *** //
94       // ************************ //
95   
96       /// @notice Harvest fees from all the deployed TOFT contracts. Fees are transferred to the owner.
97       function harvestFees() external {
98           for (uint256 i = 0; i < harvestableTapiocaOFTs.length; i++) {
99               harvestableTapiocaOFTs[i].harvestFees();
100          }
101          emit HarvestFees(msg.sender);
102      }
103  
104      // *********************** //
105      // *** OWNER FUNCTIONS *** //
106      // *********************** //
107  
108      /// @notice Execute the `_bytecode` against the `_toft`. Callable only by the owner.
109      /// @dev Used to call derived OFT functions to a TOFT contract.
110      /// @param _toft The TOFT contract to execute against.
111      /// @param _bytecode The executable bytecode of the TOFT contract.
112      /// @param _revertOnFailure Whether to revert on failure.
113      /// @return success If the execution was successful.
114      /// @return result The error message if the execution failed.
115      function executeTOFT(
116          address _toft,
117          bytes calldata _bytecode,
118          bool _revertOnFailure
119      ) external payable onlyOwner returns (bool success, bytes memory result) {
120          (success, result) = payable(_toft).call{value: msg.value}(_bytecode);
121          if (_revertOnFailure && !success) {
122              revert TapiocaWrapper__TOFTExecutionFailed(result);
123          }
124      }
125  
126      /// @notice Execute the `_bytecode` against the `_toft`. Callable only by the owner.
127      /// @dev Used to call derived OFT functions to a TOFT contract.
128      /// @param _call The array calls to do.
129      /// @return success If the execution was successful.
130      /// @return results The message of the execution, could be an error message.
131      function executeCalls(
132          ExecutionCall[] calldata _call
133      )
134          external
135          payable
136          onlyOwner
137          returns (bool success, bytes[] memory results)
138      {
139          results = new bytes[](_call.length);
140          for (uint256 i = 0; i < _call.length; i++) {
141              (success, results[i]) = payable(_call[i].toft).call{
142                  value: msg.value
143              }(_call[i].bytecode);
144              if (_call[i].revertOnFailure && !success) {
145                  revert TapiocaWrapper__TOFTExecutionFailed(results[i]);
146              }
147          }
148      }
149  
150      /// @notice Deploy a new TOFT contract. Callable only by the owner.
151      /// @param _erc20 The ERC20 to wrap.
152      /// @param _bytecode The executable bytecode of the TOFT contract.
153      /// @param _salt Create2 salt.
154      function createTOFT(
155          address _erc20,
156          bytes calldata _bytecode,
157          bytes32 _salt,
158          bool _linked
159      ) external onlyOwner {
160          if (address(tapiocaOFTsByErc20[_erc20]) != address(0x0)) {
161              revert TapiocaWrapper__AlreadyDeployed(_erc20);
162          }
163  
164          ITapiocaOFT iOFT = ITapiocaOFT(
165              _createTOFT(_erc20, _bytecode, _salt, _linked)
166          );
167          if (address(iOFT.erc20()) != _erc20) {
168              revert TapiocaWrapper__FailedDeploy();
169          }
170  
171          tapiocaOFTs.push(iOFT);
172          tapiocaOFTsByErc20[_erc20] = iOFT;
173  
174          if (iOFT.hostChainID() == block.chainid) {
175              harvestableTapiocaOFTs.push(iOFT);
176          }
177          emit CreateOFT(iOFT, _erc20);
178      }
179  
180      // ************************* //
181      // *** PRIVATE FUNCTIONS *** //
182      // ************************* //
183      function _createTOFT(
184          address _erc20,
185          bytes calldata _bytecode,
186          bytes32 _salt,
187          bool _linked
188      ) private returns (address) {
189          address oft;
190          if (!_linked) {
191              TapiocaOFT toft = TapiocaOFT(
192                  payable(
193                      Create2.deploy(
194                          0,
195                          keccak256(
196                              abi.encodePacked(
197                                  keccak256(_bytecode),
198                                  address(this),
199                                  _erc20,
200                                  _salt
201                              )
202                          ),
203                          _bytecode
204                      )
205                  )
206              );
207              oft = address(toft);
208          } else {
209              mTapiocaOFT toft = mTapiocaOFT(
210                  payable(
211                      Create2.deploy(
212                          0,
213                          keccak256(
214                              abi.encodePacked(
215                                  keccak256(_bytecode),
216                                  address(this),
217                                  _erc20,
218                                  _salt
219                              )
220                          ),
221                          _bytecode
222                      )
223                  )
224              );
225              oft = address(toft);
226          }
227          return oft;
228      }
229: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L26-L229

File: contracts/tOFT/mTapiocaOFT.sol

9    contract mTapiocaOFT is BaseTOFT {
10       using SafeERC20 for IERC20;
11   
12       // ************ //
13       // *** VARS *** //
14       // ************ //
15   
16       /// @notice allowed chains where you can unwrap your TOFT
17       mapping(uint256 => bool) public connectedChains;
18   
19       /// @notice map of approved balancers
20       /// @dev a balancer can extract the underlying
21       mapping(address => bool) public balancers;
22   
23       // ************** //
24       // *** EVENTS *** //
25       // ************** //
26       /// @notice event emitted when a connected chain is reigstered or unregistered
27       event ConnectedChainStatusUpdated(uint256 _chain, bool _old, bool _new);
28       /// @notice event emitted when balancer status is updated
29       event BalancerStatusUpdated(
30           address indexed _balancer,
31           bool _bool,
32           bool _new
33       );
34       /// @notice event emitted when rebalancing is performed
35       event Rebalancing(
36           address indexed _balancer,
37           uint256 _amount,
38           bool _isNative
39       );
40   
41       /// @notice creates a new mTapiocaOFT
42       /// @param _lzEndpoint LayerZero endpoint address
43       /// @param _erc20 true the underlying ERC20 address
44       /// @param _yieldBox the YieldBox address
45       /// @param _name the TOFT name
46       /// @param _symbol the TOFT symbol
47       /// @param _decimal the TOFT decimal
48       /// @param _hostChainID the TOFT host chain LayerZero id
49       constructor(
50           address _lzEndpoint,
51           address _erc20,
52           IYieldBoxBase _yieldBox,
53           string memory _name,
54           string memory _symbol,
55           uint8 _decimal,
56           uint256 _hostChainID,
57           address payable _leverageModule,
58           address payable _strategyModule,
59           address payable _marketModule,
60           address payable _optionsModule
61       )
62           BaseTOFT(
63               _lzEndpoint,
64               _erc20,
65               _yieldBox,
66               _name,
67               _symbol,
68               _decimal,
69               _hostChainID,
70               _leverageModule,
71               _strategyModule,
72               _marketModule,
73               _optionsModule
74           )
75       {
76           if (block.chainid == _hostChainID) {
77               connectedChains[_hostChainID] = true;
78           }
79       }
80   
81       // ************************ //
82       // *** PUBLIC FUNCTIONS *** //
83       // ************************ //
84       /// @notice Wrap an ERC20 with a 1:1 ratio with a fee if existing.
85       /// @dev Since it can be executed only on the main chain, if an address exists on the OP chain it will not allowed to wrap.
86       /// @param _toAddress The address to wrap the ERC20 to.
87       /// @param _amount The amount of ERC20 to wrap.
88       function wrap(
89           address _fromAddress,
90           address _toAddress,
91           uint256 _amount
92       ) external payable onlyHostChain {
93           require(!balancers[msg.sender], "TOFT_auth");
94           if (erc20 == address(0)) {
95               _wrapNative(_toAddress);
96           } else {
97               _wrap(_fromAddress, _toAddress, _amount);
98           }
99       }
100  
101      /// @notice Unwrap an ERC20/Native with a 1:1 ratio. Called only on host chain.
102      /// @param _toAddress The address to unwrap the tokens to.
103      /// @param _amount The amount of tokens to unwrap.
104      function unwrap(address _toAddress, uint256 _amount) external {
105          require(connectedChains[block.chainid], "TOFT_host");
106          require(!balancers[msg.sender], "TOFT_auth");
107          _unwrap(_toAddress, _amount);
108      }
109  
110      // *********************** //
111      // *** OWNER FUNCTIONS *** //
112      // *********************** //
113      /// @notice updates a connected chain whitelist status
114      /// @param _chain the block.chainid of that specific chain
115      /// @param _status the new whitelist status
116      function updateConnectedChain(
117          uint256 _chain,
118          bool _status
119      ) external onlyOwner {
120          emit ConnectedChainStatusUpdated(
121              _chain,
122              connectedChains[_chain],
123              _status
124          );
125          connectedChains[_chain] = _status;
126      }
127  
128      /// @notice updates a Balancer whitelist status
129      /// @param _balancer the operator address
130      /// @param _status the new whitelist status
131      function updateBalancerState(
132          address _balancer,
133          bool _status
134      ) external onlyOwner {
135          emit BalancerStatusUpdated(_balancer, balancers[_balancer], _status);
136          balancers[_balancer] = _status;
137      }
138  
139      /// @notice extracts the underlying token/native for rebalancing
140      /// @param _amount the amount used for rebalancing
141      function extractUnderlying(uint256 _amount) external {
142          require(balancers[msg.sender], "TOFT_auth");
143  
144          bool _isNative = erc20 == address(0);
145          if (_isNative) {
146              _safeTransferETH(msg.sender, _amount);
147          } else {
148              IERC20(erc20).safeTransfer(msg.sender, _amount);
149          }
150  
151          emit Rebalancing(msg.sender, _amount, _isNative);
152      }
153: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol#L9-L153

File: contracts/Vesting.sol

10   contract Vesting is BoringOwnable, ReentrancyGuard {
11       using SafeERC20 for IERC20;
12   
13       // ************ //
14       // *** VARS *** //
15       // ************ //
16       /// @notice the vested token
17       IERC20 public token;
18   
19       /// @notice returns the start time for vesting
20       uint256 public start;
21   
22       /// @notice returns the cliff period
23       uint256 public cliff;
24   
25       /// @notice returns total vesting duration
26       uint256 public duration;
27   
28       /// @notice returns total available tokens
29       uint256 public seeded = 0;
30   
31       /// @notice user vesting data
32       struct UserData {
33           uint256 amount;
34           uint256 claimed;
35           uint256 latestClaimTimestamp;
36           bool revoked;
37       }
38       mapping(address => UserData) public users;
39   
40       uint256 private _totalAmount;
41       uint256 private _totalClaimed;
42   
43       // ************** //
44       // *** ERRORS *** //
45       // ************** //
46       error NotStarted();
47       error NothingToClaim();
48       error Initialized();
49       error AddressNotValid();
50       error AmountNotValid();
51       error AlreadyRegistered();
52       error NoTokens();
53       error NotEnough();
54       error BalanceTooLow();
55   
56       // *************** //
57       // *** EVENTS *** //
58       // ************** //
59       /// @notice event emitted when a new user is registered
60       event UserRegistered(address indexed user, uint256 amount);
61       /// @notice event emitted when someone claims available tokens
62       event Claimed(address indexed user, uint256 amount);
63   
64       /// @notice creates a new Vesting contract
65       /// @param _cliff cliff period
66       /// @param _duration vesting period
67       constructor(uint256 _cliff, uint256 _duration, address _owner) {
68           require(_duration > 0, "Vesting: no vesting");
69   
70           cliff = _cliff;
71           duration = _duration;
72           owner = _owner;
73       }
74   
75       // ********************** //
76       // *** VIEW FUNCTIONS *** //
77       // ********************** //
78       /// @notice returns total claimable
79       function claimable() external view returns (uint256) {
80           return _vested(seeded) - _totalClaimed;
81       }
82   
83       /// @notice returns total claimable for user
84       /// @param _user the user address
85       function claimable(address _user) public view returns (uint256) {
86           return _vested(users[_user].amount) - users[_user].claimed;
87       }
88   
89       /// @notice returns total vested amount
90       function vested() external view returns (uint256) {
91           return _vested(seeded);
92       }
93   
94       /// @notice returns total vested amount for user
95       /// @param _user the user address
96       function vested(address _user) external view returns (uint256) {
97           return _vested(users[_user].amount);
98       }
99   
100      /// @notice returns total claimed
101      function totalClaimed() external view returns (uint256) {
102          return _totalClaimed;
103      }
104  
105      // ************************ //
106      // *** PUBLIC FUNCTIONS *** //
107      // ************************ //
108      /// @notice claim available tokens
109      /// @dev claim works for msg.sender
110      function claim() external nonReentrant {
111          if (start == 0 || seeded == 0) revert NotStarted();
112          uint256 _claimable = claimable(msg.sender);
113          if (_claimable == 0) revert NothingToClaim();
114  
115          _totalClaimed += _claimable;
116          users[msg.sender].claimed += _claimable;
117          users[msg.sender].latestClaimTimestamp = block.timestamp;
118  
119          token.safeTransfer(msg.sender, _claimable);
120          emit Claimed(msg.sender, _claimable);
121      }
122  
123      // *********************** //
124      // *** OWNER FUNCTIONS *** //
125      // *********************** //
126      /// @notice adds a new user
127      /// @dev should be called before init
128      /// @param _user the user address
129      /// @param _amount user weight
130      function registerUser(address _user, uint256 _amount) external onlyOwner {
131          if (start > 0) revert Initialized();
132          if (_user == address(0)) revert AddressNotValid();
133          if (_amount == 0) revert AmountNotValid();
134          if (users[_user].amount > 0) revert AlreadyRegistered();
135  
136          UserData memory data;
137          data.amount = _amount;
138          data.claimed = 0;
139          data.revoked = false;
140          data.latestClaimTimestamp = 0;
141          users[_user] = data;
142  
143          _totalAmount += _amount;
144  
145          emit UserRegistered(_user, _amount);
146      }
147  
148      /// @notice inits the contract with total amount
149      /// @dev sets the start time to block.timestamp
150      /// @param _seededAmount total vested amount
151      function init(IERC20 _token, uint256 _seededAmount) external onlyOwner {
152          if (start > 0) revert Initialized();
153          if (_seededAmount == 0) revert NoTokens();
154          if (_totalAmount > _seededAmount) revert NotEnough();
155  
156          token = _token;
157          uint256 availableToken = _token.balanceOf(address(this));
158          if (availableToken < _seededAmount) revert BalanceTooLow();
159  
160          seeded = _seededAmount;
161          start = block.timestamp;
162      }
163  
164      // ************************* //
165      // *** PRIVATE FUNCTIONS *** //
166      // ************************* //
167      function _vested(uint256 _total) private view returns (uint256) {
168          if (start == 0) return 0;
169          uint256 total = _total;
170          if (block.timestamp < start + cliff) return 0;
171          if (block.timestamp >= start + duration) return total;
172          return (total * (block.timestamp - start)) / duration;
173      }
174: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L10-L174

File: contracts/governance/twTAP.sol

71   contract TwTAP is TWAML, ONFT721, ERC721Permit {
72       using SafeERC20 for IERC20;
73   
74       TapOFT public immutable tapOFT;
75   
76       /// ===== TWAML ======
77       TWAMLPool public twAML; // sglAssetId => twAMLPool
78   
79       mapping(uint256 => Participation) public participants; // tokenId => part.
80   
81       uint256 constant MIN_WEIGHT_FACTOR = 10; // In BPS, 0.1%
82       uint256 constant dMAX = 100 * 1e4; // 10% - 100% voting power multiplier
83       uint256 constant dMIN = 10 * 1e4;
84       uint256 public constant EPOCH_DURATION = 7 days;
85   
86       // If we assume 128 bit balances for the reward token -- which fit 1e40
87       // "tokens" at the most commonly used 1e18 precision -- then we can use the
88       // other 128 bits to store the tokens allotted to a single vote more
89       // accurately. Votes in turn are proportional to the amount of TAP locked,
90       // weighted by a multiplier. This number is at most 107 bits long (see
91       // definition of `Participation` struct).
92       // the weight ranges from 10-100% where 1% = 1e4, so 1 million (20 bits).
93       // the multiplier is at most 100% = 1M (20 bits), so votes is at most a
94       // 107-bit number.
95       uint256 constant DIST_PRECISION = 2 ** 128;
96   
97       IERC20[] public rewardTokens;
98       mapping(IERC20 => uint256) public rewardTokenIndex;
99       // tokenId -> rewardTokens index -> amount
100      mapping(uint256 => mapping(uint256 => uint256)) public claimed;
101  
102      // The current week is determined by creation, but there are values that
103      // need to be updated weekly. If, for any reason whatsoever, this cannot
104      // be done in time, the `lastProcessedWeek` will be behind until this is
105      // done.
106      uint256 public mintedTWTap;
107      uint256 public creation; // Week 0 starts here
108      uint256 public lastProcessedWeek;
109      mapping(uint256 => WeekTotals) public weekTotals;
110  
111      uint256 public immutable HOST_CHAIN_ID;
112      string private baseURI;
113  
114      /// =====-------======
115      constructor(
116          address payable _tapOFT,
117          address _owner,
118          address _layerZeroEndpoint,
119          uint256 _hostChainID,
120          uint256 _minGas
121      )
122          ONFT721("Time Weighted TAP", "twTAP", _minGas, _layerZeroEndpoint)
123          ERC721Permit("Time Weighted TAP")
124      {
125          tapOFT = TapOFT(_tapOFT);
126          transferOwnership(_owner);
127          creation = block.timestamp;
128          HOST_CHAIN_ID = _hostChainID;
129      }
130  
131      // ==========
132      //   EVENTS
133      // ==========
134      event Participate(
135          address indexed participant,
136          uint256 tapAmount,
137          uint256 multiplier
138      );
139      event AMLDivergence(
140          uint256 cumulative,
141          uint256 averageMagnitude,
142          uint256 totalParticipants
143      );
144      event ExitPosition(uint256 tokenId, uint256 amount);
145  
146      // ==========
147      //    READ
148      // ==========
149  
150      function currentWeek() public view returns (uint256) {
151          return (block.timestamp - creation) / EPOCH_DURATION;
152      }
153  
154      /// @notice Return the participation of a token. Returns 0 votes for expired tokens.
155      function getParticipation(
156          uint _tokenId
157      ) public view returns (Participation memory participant) {
158          participant = participants[_tokenId];
159          if (participant.expiry < block.timestamp) {
160              participant.multiplier = 0;
161          }
162          return participant;
163      }
164  
165      /// @notice Amount currently claimable for each reward token
166      function claimable(
167          uint256 _tokenId
168      ) public view returns (uint256[] memory) {
169          uint256 len = rewardTokens.length;
170          uint256[] memory result = new uint256[](len);
171  
172          Participation memory position = participants[_tokenId];
173          uint256 votes;
174          unchecked {
175              // Math is safe: Types fit
176              votes = uint256(position.tapAmount) * uint256(position.multiplier);
177          }
178  
179          if (votes == 0) {
180              return result;
181          }
182  
183          // If the "last processed week" is behind the actual week, rewards
184          // get processed as if it were earlier.
185          uint256 week = lastProcessedWeek;
186          if (week <= position.lastInactive) {
187              return result;
188          }
189          if (position.lastActive < week) {
190              week = position.lastActive;
191          }
192  
193          WeekTotals storage cur = weekTotals[week];
194          WeekTotals storage prev = weekTotals[position.lastInactive];
195  
196          for (uint256 i = 0; i < len; ) {
197              // Math is safe (but we do the checks anyway):
198              //
199              // -- The `totalDistPerVote[i]` values are increasing as a
200              //    function of weeks (see `advanceWeek()`), and if `week`
201              //    were not greater than `position.lastInactive`, this bit
202              //    of code would not be reached (see above). Therefore the
203              //    subtraction in the calculation of `net` cannot underflow.
204              //
205              // -- `votes * net` is at most the entire reward amount given
206              //    out, ever, in units of
207              //
208              //        (reward tokens) * DIST_PRECISION.
209              //
210              //    If this number were to exceed 256 bits, then
211              //    `distributeReward` would revert.
212              //
213              // -- `claimed[_tokenId][i]` is the sum of all (the i-th values
214              //    of) previous calls to the current function that were made
215              //    by `_claimRewards()`. Let there be n such calls, and let
216              //    r_j be `result[i]`, c_j be `claimed[_tokenId][i]`, and
217              //    net_j be `net` during that j-th call. Then, up to a
218              //    multiplication by votes / DIST_PRECISION:
219              //
220              //              c_1 = 0 <= net_1,
221              //
222              //    and, for n > 1:
223              //
224              //              c_n = r_(n-1) + r_(n-2) + ... + r_1
225              //                  = r_(n-1) + c_(n-1)
226              //                  = (net_(n-1) - c_(n-1) + c_(n-1)
227              //                  = net_(n-1)
228              //                  <= net_n,
229              //
230              //    so that the subtraction net_n - c_n does not underflow.
231              //    (The rounding the calculation favors the greater first
232              //    term).
233              //    (TODO: Word better?)
234              //
235              uint256 net = cur.totalDistPerVote[i] - prev.totalDistPerVote[i];
236              result[i] = ((votes * net) / DIST_PRECISION) - claimed[_tokenId][i];
237              unchecked {
238                  ++i;
239              }
240          }
241          return result;
242      }
243  
244      // ===========
245      //    WRITE
246      // ===========
247  
248      /// @notice Participate in twAMl voting and mint an oTAP position
249      /// @param _participant The address of the participant
250      /// @param _amount The amount of TAP to participate with
251      /// @param _duration The duration of the lock
252      function participate(
253          address _participant,
254          uint256 _amount,
255          uint256 _duration
256      ) external returns (uint256 tokenId) {
257          require(_duration >= EPOCH_DURATION, "twTAP: Lock not a week");
258  
259          // Transfer TAP to this contract
260          tapOFT.transferFrom(msg.sender, address(this), _amount);
261  
262          // Copy to memory
263          TWAMLPool memory pool = twAML;
264  
265          uint256 magnitude = computeMagnitude(_duration, pool.cumulative);
266          bool divergenceForce;
267          uint256 multiplier = computeTarget(
268              dMIN,
269              dMAX,
270              magnitude,
271              pool.cumulative
272          );
273  
274          // Calculate twAML voting weight
275          bool hasVotingPower = _amount >=
276              computeMinWeight(pool.totalDeposited, MIN_WEIGHT_FACTOR);
277          if (hasVotingPower) {
278              pool.totalParticipants++; // Save participation
279              pool.averageMagnitude =
280                  (pool.averageMagnitude + magnitude) /
281                  pool.totalParticipants; // compute new average magnitude
282  
283              // Compute and save new cumulative
284              divergenceForce = _duration > pool.cumulative;
285  
286              if (divergenceForce) {
287                  pool.cumulative += pool.averageMagnitude;
288              } else {
289                  // TODO: Strongly suspect this is never less. Prove it.
290                  if (pool.cumulative > pool.averageMagnitude) {
291                      pool.cumulative -= pool.averageMagnitude;
292                  } else {
293                      pool.cumulative = 0;
294                  }
295              }
296  
297              // Save new weight
298              pool.totalDeposited += _amount;
299  
300              twAML = pool; // Save twAML participation
301              emit AMLDivergence(
302                  pool.cumulative,
303                  pool.averageMagnitude,
304                  pool.totalParticipants
305              );
306          }
307  
308          // Mint twTAP position
309          tokenId = ++mintedTWTap;
310          _safeMint(_participant, tokenId);
311  
312          uint256 expiry = block.timestamp + _duration;
313          require(expiry < type(uint56).max, "twTAP: too long");
314          // Eligibility starts NEXT week, and lasts until the week that the lock
315          // expires. This is guaranteed to be at least one week later by the
316          // check on `_duration`.
317          // If a user locks right before the current week ends, and have a
318          // duration slightly over one week, straddling the two starting points,
319          // then that user is eligible for the rewards during both weeks; the
320          // price for this maneuver is a lower multiplier, and loss of voting
321          // power in the DAO after the lock expires.
322          uint256 w0 = currentWeek();
323          uint256 w1 = (expiry - creation) / EPOCH_DURATION;
324  
325          // Save twAML participation
326          // Casts are safe: see struct definition
327          uint256 votes = _amount * multiplier;
328          participants[tokenId] = Participation({
329              averageMagnitude: pool.averageMagnitude,
330              hasVotingPower: hasVotingPower,
331              divergenceForce: divergenceForce,
332              tapReleased: false,
333              expiry: uint56(expiry),
334              tapAmount: uint88(_amount),
335              multiplier: uint24(multiplier),
336              lastInactive: uint40(w0),
337              lastActive: uint40(w1)
338          });
339  
340          // w0 + 1 = lastInactive + 1 = first active
341          // w1 + 1 = lastActive + 1 = first inactive
342          // Cast is safe: `votes` is the product of a uint88 and a uint24
343          weekTotals[w0 + 1].netActiveVotes += int256(votes);
344          weekTotals[w1 + 1].netActiveVotes -= int256(votes);
345  
346          emit Participate(_participant, _amount, multiplier);
347          // TODO: Mint event?
348      }
349  
350      /// @notice claims all rewards distributed since token mint or last claim.
351      /// @param _tokenId tokenId whose rewards to claim
352      /// @param _to address to receive the rewards
353      function claimRewards(uint256 _tokenId, address _to) external {
354          _requireClaimPermission(_to, _tokenId);
355          _claimRewards(_tokenId, _to);
356      }
357  
358      /// @notice claims all rewards distributed since token mint or last claim, and send them to another chain.
359      /// @param _tokenId The tokenId of the twTAP position
360      /// @param _rewardTokens The address of the reward token
361      function claimAndSendRewards(
362          uint256 _tokenId,
363          IERC20[] memory _rewardTokens
364      ) external {
365          require(msg.sender == address(tapOFT), "twTAP: only tapOFT");
366          _claimRewardsOn(_tokenId, address(tapOFT), _rewardTokens);
367      }
368  
369      /// @notice claims the TAP locked in a position whose votes have expired,
370      /// @notice and undoes the effect on the twAML calculations.
371      /// @param _tokenId tokenId whose locked TAP to claim
372      /// @param _to address to receive the TAP
373      function releaseTap(uint256 _tokenId, address _to) external {
374          _requireClaimPermission(_to, _tokenId);
375          _releaseTap(_tokenId, _to);
376      }
377  
378      /// @notice Exit a twAML participation and delete the voting power if existing
379      /// @param _tokenId The tokenId of the twTAP position
380      function exitPosition(uint256 _tokenId) external {
381          address to = ownerOf(_tokenId);
382          _releaseTap(_tokenId, to);
383      }
384  
385      /// @notice Exit a twAML participation and send the withdrawn TAP to tapOFT to send it to another chain.
386      /// @param _tokenId The tokenId of the twTAP position
387      function exitPositionAndSendTap(
388          uint256 _tokenId
389      ) external returns (uint256) {
390          require(msg.sender == address(tapOFT), "twTAP: only tapOFT");
391          return _releaseTap(_tokenId, address(tapOFT));
392      }
393  
394      /// @notice Indicate that (a) week(s) have passed and update running totals
395      /// @notice Reverts if called in week 0. Let it.
396      /// @param _limit Maximum number of weeks to process in one call
397      function advanceWeek(uint256 _limit) public {
398          // TODO: Make whole function unchecked
399          uint256 cur = currentWeek();
400          uint256 week = lastProcessedWeek;
401          uint256 goal = cur;
402          unchecked {
403              if (goal - week > _limit) {
404                  goal = week + _limit;
405              }
406          }
407          uint256 len = rewardTokens.length;
408          while (week < goal) {
409              WeekTotals storage prev = weekTotals[week];
410              WeekTotals storage next = weekTotals[++week];
411              // TODO: Prove that math is safe
412              next.netActiveVotes += prev.netActiveVotes;
413              for (uint256 i = 0; i < len; ) {
414                  next.totalDistPerVote[i] += prev.totalDistPerVote[i];
415                  unchecked {
416                      ++i;
417                  }
418              }
419          }
420          lastProcessedWeek = goal;
421      }
422  
423      /// @notice distributes a reward among all tokens, weighted by voting power
424      /// @notice The reward gets allocated to all positions that have locked in
425      /// @notice the current week. Fails, intentionally, if this number is zero.
426      /// @notice Total rewards cannot exceed 2^128 tokens.
427      /// @param _rewardTokenId index of the reward in `rewardTokens`
428      /// @param _amount amount of reward token to distribute.
429      function distributeReward(
430          uint256 _rewardTokenId,
431          uint256 _amount
432      ) external {
433          require(
434              lastProcessedWeek == currentWeek(),
435              "twTAP: Advance week first"
436          );
437          WeekTotals storage totals = weekTotals[lastProcessedWeek];
438          IERC20 rewardToken = rewardTokens[_rewardTokenId];
439          // If this is a DBZ then there are no positions to give the reward to.
440          // Since reward eligibility starts in the week after locking, there is
441          // no way to give out rewards THIS week.
442          // Cast is safe: `netActiveVotes` is at most zero by construction of
443          // weekly totals and the requirement that they are up to date.
444          // TODO: Word this better
445          totals.totalDistPerVote[_rewardTokenId] +=
446              (_amount * DIST_PRECISION) /
447              uint256(totals.netActiveVotes);
448          rewardToken.safeTransferFrom(msg.sender, address(this), _amount);
449      }
450  
451      // =========
452      //   OWNER
453      // =========
454  
455      function addRewardToken(IERC20 token) external onlyOwner returns (uint256) {
456          uint256 i = rewardTokens.length;
457          rewardTokens.push(token);
458          rewardTokenIndex[token] = i;
459          return i;
460      }
461  
462      // ============
463      //   INTERNAL
464      // ============
465  
466      /// @dev Mirrors the implementation of _isApprovedOrOwner, with the modification
467      /// that it is allowed if `_to` is the owner:
468      function _requireClaimPermission(
469          address _to,
470          uint256 _tokenId
471      ) internal view {
472          address tokenOwner = ownerOf(_tokenId);
473          require(
474              msg.sender == tokenOwner ||
475                  _to == tokenOwner ||
476                  isApprovedForAll(tokenOwner, msg.sender) ||
477                  getApproved(_tokenId) == msg.sender,
478              "twTAP: cannot claim"
479          );
480      }
481  
482      /// @dev Claim all rewards on a position and send them to `_to`.
483      function _claimRewards(uint256 _tokenId, address _to) internal {
484          uint256[] memory amounts = claimable(_tokenId);
485          uint256 len = amounts.length;
486          unchecked {
487              for (uint256 i = 0; i < len; ++i) {
488                  uint256 amount = amounts[i];
489                  if (amount > 0) {
490                      // Math is safe: `amount` calculated safely in `claimable()`
491                      claimed[_tokenId][i] += amount;
492                      rewardTokens[i].safeTransfer(_to, amount);
493                  }
494              }
495          }
496      }
497  
498      /// @dev Claim rewards of a specific token on a position and send them to `_to`.
499      function _claimRewardsOn(
500          uint256 _tokenId,
501          address _to,
502          IERC20[] memory _rewardTokens
503      ) internal {
504          uint256[] memory amounts = claimable(_tokenId);
505          unchecked {
506              uint256 len = _rewardTokens.length;
507              for (uint256 i = 0; i < len; ) {
508                  uint256 claimableIndex = rewardTokenIndex[_rewardTokens[i]];
509                  uint256 amount = amounts[i];
510  
511                  if (amount > 0) {
512                      // Math is safe: `amount` calculated safely in `claimable()`
513                      claimed[_tokenId][claimableIndex] += amount;
514                      rewardTokens[claimableIndex].safeTransfer(_to, amount);
515                  }
516                  ++i;
517              }
518          }
519      }
520  
521      /// @dev Release the tap of a position and send it to `_to`. Remove the user from twAML.
522      function _releaseTap(
523          uint256 _tokenId,
524          address _to
525      ) internal returns (uint256 releasedAmount) {
526          Participation memory position = participants[_tokenId];
527          if (position.tapReleased) {
528              return 0;
529          }
530          require(position.expiry <= block.timestamp, "twTAP: Lock not expired");
531  
532          releasedAmount = position.tapAmount;
533  
534          // Remove participation
535          if (position.hasVotingPower) {
536              TWAMLPool memory pool = twAML;
537              pool.totalParticipants--;
538  
539              // Inverse of the participation. The participation entry tracks
540              // the average magnitude as it was at the time the participant
541              // entered. When going the other way around, this value matches the
542              // one in the pool, but here it does not.
543              if (position.divergenceForce) {
544                  if (pool.cumulative > position.averageMagnitude) {
545                      pool.cumulative -= position.averageMagnitude;
546                  } else {
547                      pool.cumulative = 0;
548                  }
549              } else {
550                  pool.cumulative += position.averageMagnitude;
551              }
552  
553              // Save new weight
554              pool.totalDeposited -= position.tapAmount;
555  
556              twAML = pool; // Save twAML exit
557              emit AMLDivergence(
558                  pool.cumulative,
559                  pool.averageMagnitude,
560                  pool.totalParticipants
561              ); // Register new voting power event
562          }
563  
564          participants[_tokenId].tapReleased = true;
565          tapOFT.transfer(_to, releasedAmount);
566  
567          emit ExitPosition(_tokenId, releasedAmount);
568      }
569  
570      /// @dev Returns the chain ID of the current network
571      function _getChainId() internal view virtual returns (uint256) {
572          uint256 chainId;
573          assembly {
574              chainId := chainid()
575          }
576          return chainId;
577      }
578  
579      /**
580       * @dev See {IERC165-supportsInterface}.
581       */
582      function supportsInterface(
583          bytes4 interfaceId
584      ) public view virtual override(ONFT721, ERC721) returns (bool) {
585          return super.supportsInterface(interfaceId);
586      }
587: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L71-L587

File: contracts/option-airdrop/AirdropBroker.sol

43   contract AirdropBroker is Pausable, BoringOwnable, FullMath {
44       bytes public tapOracleData;
45       TapOFT public immutable tapOFT;
46       AOTAP public immutable aoTAP;
47       IOracle public tapOracle;
48       IERC721 public immutable PCNFT;
49   
50       uint128 public epochTAPValuation; // TAP price for the current epoch
51       uint64 public lastEpochUpdate; // timestamp of the last epoch update
52       uint64 public epoch; // Represents the number of weeks since the start of the contract
53   
54       mapping(ERC20 => PaymentTokenOracle) public paymentTokens; // Token address => PaymentTokenOracle
55       address public paymentTokenBeneficiary; // Where to collect the payment tokens
56   
57       mapping(uint256 => mapping(uint256 => uint256)) public aoTAPCalls; // oTAPTokenID => epoch => amountExercised
58   
59       /// @notice Record of participation in phase 2 airdrop
60       /// Only applicable for phase 2. To get subphases on phase 2 we do userParticipation[_user][20+roles]
61       mapping(address => mapping(uint256 => bool)) public userParticipation; // user address => phase => participated
62   
63       /// =====-------======
64       ///      Phase 1
65       /// =====-------======
66   
67       /// @notice user address => eligible TAP amount, 0 means no eligibility
68       mapping(address => uint256) public phase1Users;
69       uint256 public constant PHASE_1_DISCOUNT = 50 * 1e4; // 50%
70   
71       /// =====-------======
72       ///      Phase 2
73       /// =====-------======
74   
75       // [OG Pearls, Sushi Frens, Tapiocans, Oysters, Cassava]
76       bytes32[4] public phase2MerkleRoots; // merkle root of phase 2 airdrop
77       uint8[4] public PHASE_2_AMOUNT_PER_USER = [200, 190, 200, 190];
78       uint8[4] public PHASE_2_DISCOUNT_PER_USER = [50, 40, 40, 33];
79   
80       /// =====-------======
81       ///      Phase 3
82       /// =====-------======
83   
84       uint256 public constant PHASE_3_AMOUNT_PER_USER = 714;
85       uint256 public constant PHASE_3_DISCOUNT = 50 * 1e4;
86   
87       /// =====-------======
88       ///      Phase 4
89       /// =====-------======
90   
91       /// @notice user address => eligible TAP amount, 0 means no eligibility
92       mapping(address => uint256) public phase4Users;
93       uint256 public constant PHASE_4_DISCOUNT = 33 * 1e4;
94   
95       uint256 public constant EPOCH_DURATION = 2 days;
96   
97       /// =====-------======
98       constructor(
99           address _aoTAP,
100          address payable _tapOFT,
101          address _pcnft,
102          address _paymentTokenBeneficiary,
103          address _owner
104      ) {
105          paymentTokenBeneficiary = _paymentTokenBeneficiary;
106          tapOFT = TapOFT(_tapOFT);
107          aoTAP = AOTAP(_aoTAP);
108          PCNFT = IERC721(_pcnft);
109          owner = _owner;
110      }
111  
112      // ==========
113      //   EVENTS
114      // ==========
115      event Participate(uint256 indexed epoch, uint256 aoTAPTokenID);
116      event ExerciseOption(
117          uint256 indexed epoch,
118          address indexed to,
119          ERC20 indexed paymentToken,
120          uint256 aoTapTokenID,
121          uint256 amount
122      );
123      event NewEpoch(uint256 indexed epoch, uint256 epochTAPValuation);
124  
125      event SetPaymentToken(ERC20 paymentToken, IOracle oracle, bytes oracleData);
126      event SetTapOracle(IOracle oracle, bytes oracleData);
127  
128      // ==========
129      //    READ
130      // ==========
131  
132      /// @notice Returns the details of an OTC deal for a given oTAP token ID and a payment token.
133      ///         The oracle uses the last peeked value, and not the latest one, so the payment amount may be different.
134      /// @param _aoTAPTokenID The aoTAP token ID
135      /// @param _paymentToken The payment token
136      /// @param _tapAmount The amount of TAP to be exchanged. If 0 it will use the full amount of TAP eligible for the deal
137      /// @return eligibleTapAmount The amount of TAP eligible for the deal
138      /// @return paymentTokenAmount The amount of payment tokens required for the deal
139      /// @return tapAmount The amount of TAP to be exchanged
140  
141      function getOTCDealDetails(
142          uint256 _aoTAPTokenID,
143          ERC20 _paymentToken,
144          uint256 _tapAmount
145      )
146          external
147          view
148          returns (
149              uint256 eligibleTapAmount,
150              uint256 paymentTokenAmount,
151              uint256 tapAmount
152          )
153      {
154          // Load data
155          (, AirdropTapOption memory aoTapOption) = aoTAP.attributes(
156              _aoTAPTokenID
157          );
158          require(aoTapOption.expiry > block.timestamp, "adb: Option expired");
159  
160          uint256 cachedEpoch = epoch;
161  
162          PaymentTokenOracle memory paymentTokenOracle = paymentTokens[
163              _paymentToken
164          ];
165  
166          // Check requirements
167          require(
168              paymentTokenOracle.oracle != IOracle(address(0)),
169              "adb: Payment token not supported"
170          );
171  
172          eligibleTapAmount = aoTapOption.amount;
173          eligibleTapAmount -= aoTAPCalls[_aoTAPTokenID][cachedEpoch]; // Subtract already exercised amount
174          require(eligibleTapAmount >= _tapAmount, "adb: Too high");
175  
176          tapAmount = _tapAmount == 0 ? eligibleTapAmount : _tapAmount;
177          require(tapAmount >= 1e18, "adb: Too low");
178          // Get TAP valuation
179          uint256 otcAmountInUSD = tapAmount * epochTAPValuation; // Divided by TAP decimals
180          // Get payment token valuation
181          (, uint256 paymentTokenValuation) = paymentTokenOracle.oracle.peek(
182              paymentTokenOracle.oracleData
183          );
184          // Get payment token amount
185          paymentTokenAmount = _getDiscountedPaymentAmount(
186              otcAmountInUSD,
187              paymentTokenValuation,
188              aoTapOption.discount,
189              _paymentToken.decimals()
190          );
191      }
192  
193      // ===========
194      //    WRITE
195      // ===========
196  
197      /// @notice Participate in the airdrop
198      /// @param _data The data to be used for the participation, varies by phases
199      function participate(
200          bytes calldata _data
201      ) external returns (uint256 aoTAPTokenID) {
202          uint256 cachedEpoch = epoch;
203          require(cachedEpoch > 0, "adb: Airdrop not started");
204          require(cachedEpoch <= 4, "adb: Airdrop ended");
205  
206          // Phase 1
207          if (cachedEpoch == 1) {
208              aoTAPTokenID = _participatePhase1();
209          } else if (cachedEpoch == 2) {
210              aoTAPTokenID = _participatePhase2(_data); // _data = (uint256 role, bytes32[] _merkleProof)
211          } else if (cachedEpoch == 3) {
212              aoTAPTokenID = _participatePhase3(_data); // _data = (uint256 _tokenID)
213          } else if (cachedEpoch == 4) {
214              aoTAPTokenID = _participatePhase4();
215          }
216  
217          emit Participate(cachedEpoch, aoTAPTokenID);
218      }
219  
220      /// @notice Exercise an aoTAP position
221      /// @param _aoTAPTokenID tokenId of the aoTAP position, position must be active
222      /// @param _paymentToken Address of the payment token to use, must be whitelisted
223      /// @param _tapAmount Amount of TAP to exercise. If 0, the full amount is exercised
224      function exerciseOption(
225          uint256 _aoTAPTokenID,
226          ERC20 _paymentToken,
227          uint256 _tapAmount
228      ) external {
229          // Load data
230          (, AirdropTapOption memory aoTapOption) = aoTAP.attributes(
231              _aoTAPTokenID
232          );
233          require(aoTapOption.expiry > block.timestamp, "adb: Option expired");
234  
235          uint256 cachedEpoch = epoch;
236  
237          PaymentTokenOracle memory paymentTokenOracle = paymentTokens[
238              _paymentToken
239          ];
240  
241          // Check requirements
242          require(
243              paymentTokenOracle.oracle != IOracle(address(0)),
244              "adb: Payment token not supported"
245          );
246          require(
247              aoTAP.isApprovedOrOwner(msg.sender, _aoTAPTokenID),
248              "adb: Not approved or owner"
249          );
250  
251          // Get eligible OTC amount
252  
253          uint256 eligibleTapAmount = aoTapOption.amount;
254          eligibleTapAmount -= aoTAPCalls[_aoTAPTokenID][cachedEpoch]; // Subtract already exercised amount
255          require(eligibleTapAmount >= _tapAmount, "adb: Too high");
256  
257          uint256 chosenAmount = _tapAmount == 0 ? eligibleTapAmount : _tapAmount;
258          require(chosenAmount >= 1e18, "adb: Too low");
259          aoTAPCalls[_aoTAPTokenID][cachedEpoch] += chosenAmount; // Adds up exercised amount to current epoch
260  
261          // Finalize the deal
262          _processOTCDeal(
263              _paymentToken,
264              paymentTokenOracle,
265              chosenAmount,
266              aoTapOption.discount
267          );
268  
269          emit ExerciseOption(
270              cachedEpoch,
271              msg.sender,
272              _paymentToken,
273              _aoTAPTokenID,
274              chosenAmount
275          );
276      }
277  
278      /// @notice Start a new epoch, extract TAP from the TapOFT contract,
279      ///         emit it to the active singularities and get the price of TAP for the epoch.
280      function newEpoch() external {
281          require(
282              block.timestamp >= lastEpochUpdate + EPOCH_DURATION,
283              "adb: too soon"
284          );
285  
286          // Update epoch info
287          lastEpochUpdate = uint64(block.timestamp);
288          epoch++;
289  
290          // Get epoch TAP valuation
291          (, uint256 _epochTAPValuation) = tapOracle.get(tapOracleData);
292          epochTAPValuation = uint128(_epochTAPValuation);
293          emit NewEpoch(epoch, epochTAPValuation);
294      }
295  
296      /// @notice Claim the Broker role of the aoTAP contract
297      function aoTAPBrokerClaim() external {
298          aoTAP.brokerClaim();
299      }
300  
301      // =========
302      //   OWNER
303      // =========
304  
305      /// @notice Set the TapOFT Oracle address and data
306      /// @param _tapOracle The new TapOFT Oracle address
307      /// @param _tapOracleData The new TapOFT Oracle data
308      function setTapOracle(
309          IOracle _tapOracle,
310          bytes calldata _tapOracleData
311      ) external onlyOwner {
312          tapOracle = _tapOracle;
313          tapOracleData = _tapOracleData;
314  
315          emit SetTapOracle(_tapOracle, _tapOracleData);
316      }
317  
318      function setPhase2MerkleRoots(
319          bytes32[4] calldata _merkleRoots
320      ) external onlyOwner {
321          phase2MerkleRoots = _merkleRoots;
322      }
323  
324      function registerUserForPhase(
325          uint256 _phase,
326          address[] calldata _users,
327          uint256[] calldata _amounts
328      ) external onlyOwner {
329          require(_users.length == _amounts.length, "adb: invalid input");
330  
331          if (_phase == 1) {
332              for (uint256 i = 0; i < _users.length; i++) {
333                  phase1Users[_users[i]] = _amounts[i];
334              }
335          } else if (_phase == 4) {
336              for (uint256 i = 0; i < _users.length; i++) {
337                  phase4Users[_users[i]] = _amounts[i];
338              }
339          }
340      }
341  
342      /// @notice Activate or deactivate a payment token
343      /// @dev set the oracle to address(0) to deactivate, expect the same decimal precision as TAP oracle
344      function setPaymentToken(
345          ERC20 _paymentToken,
346          IOracle _oracle,
347          bytes calldata _oracleData
348      ) external onlyOwner {
349          paymentTokens[_paymentToken].oracle = _oracle;
350          paymentTokens[_paymentToken].oracleData = _oracleData;
351  
352          emit SetPaymentToken(_paymentToken, _oracle, _oracleData);
353      }
354  
355      /// @notice Set the payment token beneficiary
356      /// @param _paymentTokenBeneficiary The new payment token beneficiary
357      function setPaymentTokenBeneficiary(
358          address _paymentTokenBeneficiary
359      ) external onlyOwner {
360          paymentTokenBeneficiary = _paymentTokenBeneficiary;
361      }
362  
363      /// @notice Collect the payment tokens from the OTC deals
364      /// @param _paymentTokens The payment tokens to collect
365      function collectPaymentTokens(
366          address[] calldata _paymentTokens
367      ) external onlyOwner {
368          require(
369              paymentTokenBeneficiary != address(0),
370              "adb: Payment token beneficiary not set"
371          );
372          uint256 len = _paymentTokens.length;
373  
374          unchecked {
375              for (uint256 i = 0; i < len; ++i) {
376                  ERC20 paymentToken = ERC20(_paymentTokens[i]);
377                  paymentToken.transfer(
378                      paymentTokenBeneficiary,
379                      paymentToken.balanceOf(address(this))
380                  );
381              }
382          }
383      }
384  
385      // ============
386      //   INTERNAL
387      // ============
388  
389      /// @notice Participate in phase 1 of the Airdrop. LBP users are given aoTAP pro-rata.
390      function _participatePhase1() internal returns (uint256 oTAPTokenID) {
391          uint256 _eligibleAmount = phase1Users[msg.sender];
392          require(_eligibleAmount > 0, "adb: Not eligible");
393  
394          // Close eligibility
395          phase1Users[msg.sender] = 0;
396  
397          // Mint aoTAP
398          uint128 expiry = uint128(lastEpochUpdate + EPOCH_DURATION); // Set expiry to the end of the epoch
399          oTAPTokenID = aoTAP.mint(
400              msg.sender,
401              expiry,
402              uint128(PHASE_1_DISCOUNT),
403              _eligibleAmount
404          );
405      }
406  
407      /// @notice Participate in phase 2 of the Airdrop. Guild members will receive pre-defined discounts and TAP, based on role.
408      /// @param _data The calldata. Needs to be the address of the user.
409      /// _data = (uint256 role, bytes32[] _merkleProof). Refer to {phase2MerkleRoots} for role.
410      function _participatePhase2(
411          bytes calldata _data
412      ) internal returns (uint256 oTAPTokenID) {
413          (uint256 _role, bytes32[] memory _merkleProof) = abi.decode(
414              _data,
415              (uint256, bytes32[])
416          );
417  
418          bytes32 leaf = keccak256(abi.encodePacked(msg.sender));
419          require(
420              MerkleProof.verify(_merkleProof, phase2MerkleRoots[_role], leaf),
421              "adb: Not eligible"
422          );
423  
424          uint256 subPhase = 20 + _role;
425          require(
426              userParticipation[msg.sender][subPhase] == false,
427              "adb: Already participated"
428          );
429          // Close eligibility
430          userParticipation[msg.sender][subPhase] = true;
431  
432          // Mint aoTAP
433          uint128 expiry = uint128(lastEpochUpdate + EPOCH_DURATION); // Set expiry to the end of the epoch
434          uint256 eligibleAmount = uint256(PHASE_2_AMOUNT_PER_USER[_role]) * 1e18;
435          uint128 discount = uint128(PHASE_2_DISCOUNT_PER_USER[_role]) * 1e4;
436          oTAPTokenID = aoTAP.mint(msg.sender, expiry, discount, eligibleAmount);
437      }
438  
439      /// @notice Participate in phase 1 of the Airdrop. PCNFT holder will receive pre-defined discount and TAP.
440      /// @param _data The calldata. Needs to be the address of the user.
441      /// _data = (uint256 _tokenID)
442      function _participatePhase3(
443          bytes calldata _data
444      ) internal returns (uint256 oTAPTokenID) {
445          uint256 _tokenID = abi.decode(_data, (uint256));
446  
447          require(PCNFT.ownerOf(_tokenID) == msg.sender, "adb: Not eligible");
448          address tokenIDToAddress = address(uint160(_tokenID));
449          require(
450              userParticipation[tokenIDToAddress][3] == false,
451              "adb: Already participated"
452          );
453          // Close eligibility
454          // To avoid a potential attack vector, we cast token ID to an address instead of using _to,
455          // no conflict possible, tokenID goes from 0 ... 714.
456          userParticipation[tokenIDToAddress][3] = true;
457  
458          uint128 expiry = uint128(lastEpochUpdate + EPOCH_DURATION); // Set expiry to the end of the epoch
459          uint256 eligibleAmount = PHASE_3_AMOUNT_PER_USER;
460          uint128 discount = uint128(PHASE_3_DISCOUNT);
461          oTAPTokenID = aoTAP.mint(msg.sender, expiry, discount, eligibleAmount);
462      }
463  
464      /// @notice Participate in phase 4 of the Airdrop. twTAP and Cassava guild's role are given TAP pro-rata.
465      function _participatePhase4() internal returns (uint256 oTAPTokenID) {
466          uint256 _eligibleAmount = phase4Users[msg.sender];
467          require(_eligibleAmount > 0, "adb: Not eligible");
468  
469          // Close eligibility
470          phase4Users[msg.sender] = 0;
471  
472          // Mint aoTAP
473          uint128 expiry = uint128(lastEpochUpdate + EPOCH_DURATION); // Set expiry to the end of the epoch
474          oTAPTokenID = aoTAP.mint(
475              msg.sender,
476              expiry,
477              uint128(PHASE_4_DISCOUNT),
478              _eligibleAmount
479          );
480      }
481  
482      /// @notice Process the OTC deal, transfer the payment token to the broker and the TAP amount to the user
483      /// @param _paymentToken The payment token
484      /// @param _paymentTokenOracle The oracle of the payment token
485      /// @param tapAmount The amount of TAP that the user has to receive
486      /// @param discount The discount that the user has to apply to the OTC deal
487      function _processOTCDeal(
488          ERC20 _paymentToken,
489          PaymentTokenOracle memory _paymentTokenOracle,
490          uint256 tapAmount,
491          uint256 discount
492      ) internal {
493          // Get TAP valuation
494          uint256 otcAmountInUSD = tapAmount * epochTAPValuation;
495  
496          // Get payment token valuation
497          (, uint256 paymentTokenValuation) = _paymentTokenOracle.oracle.get(
498              _paymentTokenOracle.oracleData
499          );
500  
501          // Calculate payment amount and initiate the transfers
502          uint256 discountedPaymentAmount = _getDiscountedPaymentAmount(
503              otcAmountInUSD,
504              paymentTokenValuation,
505              discount,
506              _paymentToken.decimals()
507          );
508  
509          _paymentToken.transferFrom(
510              msg.sender,
511              address(this),
512              discountedPaymentAmount
513          );
514          tapOFT.transfer(msg.sender, tapAmount);
515      }
516  
517      /// @notice Computes the discounted payment amount for a given OTC amount in USD
518      /// @param _otcAmountInUSD The OTC amount in USD, 18 decimals
519      /// @param _paymentTokenValuation The payment token valuation in USD, 18 decimals
520      /// @param _discount The discount in BPS
521      /// @param _paymentTokenDecimals The payment token decimals
522      /// @return paymentAmount The discounted payment amount
523      function _getDiscountedPaymentAmount(
524          uint256 _otcAmountInUSD,
525          uint256 _paymentTokenValuation,
526          uint256 _discount,
527          uint256 _paymentTokenDecimals
528      ) internal pure returns (uint256 paymentAmount) {
529          // Calculate payment amount
530          uint256 rawPaymentAmount = _otcAmountInUSD / _paymentTokenValuation;
531          paymentAmount =
532              rawPaymentAmount -
533              muldiv(rawPaymentAmount, _discount, 100e4); // 1e4 is discount decimals, 100 is discount percentage
534  
535          paymentAmount = paymentAmount / (10 ** (18 - _paymentTokenDecimals));
536      }
537: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L43-L537

File: contracts/options/TapiocaOptionBroker.sol

53   contract TapiocaOptionBroker is Pausable, BoringOwnable, TWAML {
54       TapiocaOptionLiquidityProvision public immutable tOLP;
55       bytes public tapOracleData;
56       TapOFT public immutable tapOFT;
57       OTAP public immutable oTAP;
58       IOracle public tapOracle;
59   
60       uint256 public lastEpochUpdate; // timestamp of the last epoch update
61       uint256 public epochTAPValuation; // TAP price for the current epoch
62       uint256 public epoch; // Represents the number of weeks since the start of the contract
63   
64       mapping(uint256 => Participation) public participants; // tOLPTokenID => Participation
65       mapping(uint256 => mapping(uint256 => uint256)) public oTAPCalls; // oTAPTokenID => epoch => amountExercised
66   
67       mapping(uint256 => mapping(uint256 => uint256)) public singularityGauges; // epoch => sglAssetId => availableTAP
68   
69       mapping(ERC20 => PaymentTokenOracle) public paymentTokens; // Token address => PaymentTokenOracle
70       address public paymentTokenBeneficiary; // Where to collect the payment tokens
71   
72       /// ===== TWAML ======
73       mapping(uint256 => TWAMLPool) public twAML; // sglAssetId => twAMLPool
74   
75       uint256 constant MIN_WEIGHT_FACTOR = 10; // In BPS, 0.1%
76       uint256 constant dMAX = 50 * 1e4; // 5% - 50% discount
77       uint256 constant dMIN = 5 * 1e4;
78       uint256 public immutable EPOCH_DURATION; // 7 days = 604800
79   
80       /// =====-------======
81       constructor(
82           address _tOLP,
83           address _oTAP,
84           address payable _tapOFT,
85           address _paymentTokenBeneficiary,
86           uint256 _epochDuration,
87           address _owner
88       ) {
89           paymentTokenBeneficiary = _paymentTokenBeneficiary;
90           tOLP = TapiocaOptionLiquidityProvision(_tOLP);
91           tapOFT = TapOFT(_tapOFT);
92           oTAP = OTAP(_oTAP);
93           EPOCH_DURATION = _epochDuration;
94           owner = _owner;
95       }
96   
97       // ==========
98       //   EVENTS
99       // ==========
100      event Participate(
101          uint256 indexed epoch,
102          uint256 indexed sglAssetID,
103          uint256 totalDeposited,
104          LockPosition lock,
105          uint256 discount
106      );
107      event AMLDivergence(
108          uint256 indexed epoch,
109          uint256 cumulative,
110          uint256 averageMagnitude,
111          uint256 totalParticipants
112      );
113      event ExerciseOption(
114          uint256 indexed epoch,
115          address indexed to,
116          ERC20 indexed paymentToken,
117          uint256 oTapTokenID,
118          uint256 amount
119      );
120      event NewEpoch(
121          uint256 indexed epoch,
122          uint256 extractedTAP,
123          uint256 epochTAPValuation
124      );
125      event ExitPosition(
126          uint256 indexed epoch,
127          uint256 indexed tokenId,
128          uint256 amount
129      );
130      event SetPaymentToken(ERC20 paymentToken, IOracle oracle, bytes oracleData);
131      event SetTapOracle(IOracle oracle, bytes oracleData);
132  
133      // ==========
134      //    READ
135      // ==========
136  
137      /// @notice Returns the details of an OTC deal for a given oTAP token ID and a payment token.
138      ///         The oracle uses the last peeked value, and not the latest one, so the payment amount may be different.
139      /// @param _oTAPTokenID The oTAP token ID
140      /// @param _paymentToken The payment token
141      /// @param _tapAmount The amount of TAP to be exchanged. If 0 it will use the full amount of TAP eligible for the deal
142      /// @return eligibleTapAmount The amount of TAP eligible for the deal
143      /// @return paymentTokenAmount The amount of payment tokens required for the deal
144      /// @return tapAmount The amount of TAP to be exchanged
145      function getOTCDealDetails(
146          uint256 _oTAPTokenID,
147          ERC20 _paymentToken,
148          uint256 _tapAmount
149      )
150          external
151          view
152          returns (
153              uint256 eligibleTapAmount,
154              uint256 paymentTokenAmount,
155              uint256 tapAmount
156          )
157      {
158          // Load data
159          (, TapOption memory oTAPPosition) = oTAP.attributes(_oTAPTokenID);
160          (bool isPositionActive, LockPosition memory tOLPLockPosition) = tOLP
161              .getLock(oTAPPosition.tOLP);
162  
163          uint256 cachedEpoch = epoch;
164  
165          PaymentTokenOracle memory paymentTokenOracle = paymentTokens[
166              _paymentToken
167          ];
168  
169          // Check requirements
170          require(
171              paymentTokenOracle.oracle != IOracle(address(0)),
172              "tOB: Payment token not supported"
173          );
174  
175          require(isPositionActive, "tOB: Option expired");
176  
177          // Get eligible OTC amount
178          uint256 gaugeTotalForEpoch = singularityGauges[cachedEpoch][
179              tOLPLockPosition.sglAssetID
180          ];
181          eligibleTapAmount = muldiv(
182              tOLPLockPosition.amount,
183              gaugeTotalForEpoch,
184              tOLP.getTotalPoolDeposited(tOLPLockPosition.sglAssetID)
185          );
186          eligibleTapAmount -= oTAPCalls[_oTAPTokenID][cachedEpoch]; // Subtract already exercised amount
187          require(eligibleTapAmount >= _tapAmount, "tOB: Too high");
188  
189          tapAmount = _tapAmount == 0 ? eligibleTapAmount : _tapAmount;
190          require(tapAmount >= 1e18, "tOB: Too low");
191          // Get TAP valuation
192          uint256 otcAmountInUSD = tapAmount * epochTAPValuation; // Divided by TAP decimals
193          // Get payment token valuation
194          (, uint256 paymentTokenValuation) = paymentTokenOracle.oracle.peek(
195              paymentTokenOracle.oracleData
196          );
197          // Get payment token amount
198          paymentTokenAmount = _getDiscountedPaymentAmount(
199              otcAmountInUSD,
200              paymentTokenValuation,
201              oTAPPosition.discount,
202              _paymentToken.decimals()
203          );
204      }
205  
206      // ===========
207      //    WRITE
208      // ===========
209  
210      /// @notice Participate in twAMl voting and mint an oTAP position
211      /// @param _tOLPTokenID The tokenId of the tOLP position
212      function participate(
213          uint256 _tOLPTokenID
214      ) external returns (uint256 oTAPTokenID) {
215          // Compute option parameters
216          (bool isPositionActive, LockPosition memory lock) = tOLP.getLock(
217              _tOLPTokenID
218          );
219          require(isPositionActive, "tOB: Position is not active");
220          require(lock.lockDuration >= EPOCH_DURATION, "tOB: Duration too short");
221  
222          TWAMLPool memory pool = twAML[lock.sglAssetID];
223  
224          require(
225              tOLP.isApprovedOrOwner(msg.sender, _tOLPTokenID),
226              "tOB: Not approved or owner"
227          );
228  
229          // Transfer tOLP position to this contract
230          tOLP.transferFrom(msg.sender, address(this), _tOLPTokenID);
231  
232          uint256 magnitude = computeMagnitude(
233              uint256(lock.lockDuration),
234              pool.cumulative
235          );
236          bool divergenceForce;
237          uint256 target = computeTarget(dMIN, dMAX, magnitude, pool.cumulative);
238  
239          // Participate in twAMl voting
240          bool hasVotingPower = lock.amount >=
241              computeMinWeight(pool.totalDeposited, MIN_WEIGHT_FACTOR);
242          if (hasVotingPower) {
243              pool.totalParticipants++; // Save participation
244              pool.averageMagnitude =
245                  (pool.averageMagnitude + magnitude) /
246                  pool.totalParticipants; // compute new average magnitude
247  
248              // Compute and save new cumulative
249              divergenceForce = lock.lockDuration > pool.cumulative;
250              if (divergenceForce) {
251                  pool.cumulative += pool.averageMagnitude;
252              } else {
253                  if (pool.cumulative > pool.averageMagnitude) {
254                      pool.cumulative -= pool.averageMagnitude;
255                  } else {
256                      pool.cumulative = 0;
257                  }
258              }
259  
260              // Save new weight
261              pool.totalDeposited += lock.amount;
262  
263              twAML[lock.sglAssetID] = pool; // Save twAML participation
264              emit AMLDivergence(
265                  epoch,
266                  pool.cumulative,
267                  pool.averageMagnitude,
268                  pool.totalParticipants
269              ); // Register new voting power event
270          }
271          // Save twAML participation
272          participants[_tOLPTokenID] = Participation(
273              hasVotingPower,
274              divergenceForce,
275              pool.averageMagnitude
276          );
277  
278          // Mint oTAP position
279          oTAPTokenID = oTAP.mint(
280              msg.sender,
281              lock.lockTime + lock.lockDuration,
282              uint128(target),
283              _tOLPTokenID
284          );
285          emit Participate(
286              epoch,
287              lock.sglAssetID,
288              pool.totalDeposited,
289              lock,
290              target
291          );
292      }
293  
294      /// @notice Exit a twAML participation and delete the voting power if existing
295      /// @param _oTAPTokenID The tokenId of the oTAP position
296      function exitPosition(uint256 _oTAPTokenID) external {
297          require(oTAP.exists(_oTAPTokenID), "tOB: oTAP position does not exist");
298  
299          // Load data
300          (, TapOption memory oTAPPosition) = oTAP.attributes(_oTAPTokenID);
301          (, LockPosition memory lock) = tOLP.getLock(oTAPPosition.tOLP);
302  
303          require(
304              block.timestamp >= lock.lockTime + lock.lockDuration,
305              "tOB: Lock not expired"
306          );
307  
308          Participation memory participation = participants[oTAPPosition.tOLP];
309  
310          // Remove participation
311          if (participation.hasVotingPower) {
312              TWAMLPool memory pool = twAML[lock.sglAssetID];
313  
314              if (participation.divergenceForce) {
315                  if (pool.cumulative > pool.averageMagnitude) {
316                      pool.cumulative -= pool.averageMagnitude;
317                  } else {
318                      pool.cumulative = 0;
319                  }
320              } else {
321                  pool.cumulative += pool.averageMagnitude;
322              }
323  
324              pool.totalDeposited -= lock.amount;
325              pool.totalParticipants--;
326  
327              twAML[lock.sglAssetID] = pool; // Save twAML exit
328              emit AMLDivergence(
329                  epoch,
330                  pool.cumulative,
331                  pool.averageMagnitude,
332                  pool.totalParticipants
333              ); // Register new voting power event
334          }
335  
336          // Delete participation and burn oTAP position
337          address otapOwner = oTAP.ownerOf(_oTAPTokenID);
338          delete participants[oTAPPosition.tOLP];
339          oTAP.burn(_oTAPTokenID);
340  
341          // Transfer position back to oTAP owner
342          tOLP.transferFrom(address(this), otapOwner, oTAPPosition.tOLP);
343  
344          emit ExitPosition(epoch, oTAPPosition.tOLP, lock.amount);
345      }
346  
347      /// @notice Exercise an oTAP position
348      /// @param _oTAPTokenID tokenId of the oTAP position, position must be active
349      /// @param _paymentToken Address of the payment token to use, must be whitelisted
350      /// @param _tapAmount Amount of TAP to exercise. If 0, the full amount is exercised
351      function exerciseOption(
352          uint256 _oTAPTokenID,
353          ERC20 _paymentToken,
354          uint256 _tapAmount
355      ) external {
356          // Load data
357          (, TapOption memory oTAPPosition) = oTAP.attributes(_oTAPTokenID);
358          (bool isPositionActive, LockPosition memory tOLPLockPosition) = tOLP
359              .getLock(oTAPPosition.tOLP);
360  
361          uint256 cachedEpoch = epoch;
362  
363          PaymentTokenOracle memory paymentTokenOracle = paymentTokens[
364              _paymentToken
365          ];
366  
367          // Check requirements
368          require(
369              paymentTokenOracle.oracle != IOracle(address(0)),
370              "tOB: Payment token not supported"
371          );
372          require(
373              oTAP.isApprovedOrOwner(msg.sender, _oTAPTokenID),
374              "tOB: Not approved or owner"
375          );
376          require(isPositionActive, "tOB: Option expired");
377  
378          // Get eligible OTC amount
379          uint256 gaugeTotalForEpoch = singularityGauges[cachedEpoch][
380              tOLPLockPosition.sglAssetID
381          ];
382          uint256 eligibleTapAmount = muldiv(
383              tOLPLockPosition.amount,
384              gaugeTotalForEpoch,
385              tOLP.getTotalPoolDeposited(tOLPLockPosition.sglAssetID)
386          );
387          eligibleTapAmount -= oTAPCalls[_oTAPTokenID][cachedEpoch]; // Subtract already exercised amount
388          require(eligibleTapAmount >= _tapAmount, "tOB: Too high");
389  
390          uint256 chosenAmount = _tapAmount == 0 ? eligibleTapAmount : _tapAmount;
391          require(chosenAmount >= 1e18, "tOB: Too low");
392          oTAPCalls[_oTAPTokenID][cachedEpoch] += chosenAmount; // Adds up exercised amount to current epoch
393  
394          // Finalize the deal
395          _processOTCDeal(
396              _paymentToken,
397              paymentTokenOracle,
398              chosenAmount,
399              oTAPPosition.discount
400          );
401  
402          emit ExerciseOption(
403              cachedEpoch,
404              msg.sender,
405              _paymentToken,
406              _oTAPTokenID,
407              chosenAmount
408          );
409      }
410  
411      /// @notice Start a new epoch, extract TAP from the TapOFT contract,
412      ///         emit it to the active singularities and get the price of TAP for the epoch.
413      function newEpoch() external {
414          require(
415              block.timestamp >= lastEpochUpdate + EPOCH_DURATION,
416              "tOB: too soon"
417          );
418          uint256[] memory singularities = tOLP.getSingularities();
419          require(singularities.length > 0, "tOB: No active singularities");
420  
421          // Update epoch info
422          lastEpochUpdate = block.timestamp;
423          epoch++;
424  
425          // Extract TAP
426          uint256 epochTAP = tapOFT.emitForWeek();
427          _emitToGauges(epochTAP);
428  
429          // Get epoch TAP valuation
430          (, epochTAPValuation) = tapOracle.get(tapOracleData);
431          emit NewEpoch(epoch, epochTAP, epochTAPValuation);
432      }
433  
434      /// @notice Claim the Broker role of the oTAP contract
435      function oTAPBrokerClaim() external {
436          oTAP.brokerClaim();
437      }
438  
439      // =========
440      //   OWNER
441      // =========
442  
443      /// @notice Set the TapOFT Oracle address and data
444      /// @param _tapOracle The new TapOFT Oracle address
445      /// @param _tapOracleData The new TapOFT Oracle data
446      function setTapOracle(
447          IOracle _tapOracle,
448          bytes calldata _tapOracleData
449      ) external onlyOwner {
450          tapOracle = _tapOracle;
451          tapOracleData = _tapOracleData;
452  
453          emit SetTapOracle(_tapOracle, _tapOracleData);
454      }
455  
456      /// @notice Activate or deactivate a payment token
457      /// @dev set the oracle to address(0) to deactivate, expect the same decimal precision as TAP oracle
458      function setPaymentToken(
459          ERC20 _paymentToken,
460          IOracle _oracle,
461          bytes calldata _oracleData
462      ) external onlyOwner {
463          paymentTokens[_paymentToken].oracle = _oracle;
464          paymentTokens[_paymentToken].oracleData = _oracleData;
465  
466          emit SetPaymentToken(_paymentToken, _oracle, _oracleData);
467      }
468  
469      /// @notice Set the payment token beneficiary
470      /// @param _paymentTokenBeneficiary The new payment token beneficiary
471      function setPaymentTokenBeneficiary(
472          address _paymentTokenBeneficiary
473      ) external onlyOwner {
474          paymentTokenBeneficiary = _paymentTokenBeneficiary;
475      }
476  
477      /// @notice Collect the payment tokens from the OTC deals
478      /// @param _paymentTokens The payment tokens to collect
479      function collectPaymentTokens(
480          address[] calldata _paymentTokens
481      ) external onlyOwner {
482          require(
483              paymentTokenBeneficiary != address(0),
484              "tOB: Payment token beneficiary not set"
485          );
486          uint256 len = _paymentTokens.length;
487  
488          unchecked {
489              for (uint256 i = 0; i < len; ++i) {
490                  ERC20 paymentToken = ERC20(_paymentTokens[i]);
491                  paymentToken.transfer(
492                      paymentTokenBeneficiary,
493                      paymentToken.balanceOf(address(this))
494                  );
495              }
496          }
497      }
498  
499      // ============
500      //   INTERNAL
501      // ============
502  
503      /// @notice Process the OTC deal, transfer the payment token to the broker and the TAP amount to the user
504      /// @param _paymentToken The payment token
505      /// @param _paymentTokenOracle The oracle of the payment token
506      /// @param tapAmount The amount of TAP that the user has to receive
507      /// @param discount The discount that the user has to apply to the OTC deal
508      function _processOTCDeal(
509          ERC20 _paymentToken,
510          PaymentTokenOracle memory _paymentTokenOracle,
511          uint256 tapAmount,
512          uint256 discount
513      ) internal {
514          // Get TAP valuation
515          uint256 otcAmountInUSD = tapAmount * epochTAPValuation;
516  
517          // Get payment token valuation
518          (, uint256 paymentTokenValuation) = _paymentTokenOracle.oracle.get(
519              _paymentTokenOracle.oracleData
520          );
521  
522          // Calculate payment amount and initiate the transfers
523          uint256 discountedPaymentAmount = _getDiscountedPaymentAmount(
524              otcAmountInUSD,
525              paymentTokenValuation,
526              discount,
527              _paymentToken.decimals()
528          );
529  
530          _paymentToken.transferFrom(
531              msg.sender,
532              address(this),
533              discountedPaymentAmount
534          );
535          tapOFT.extractTAP(msg.sender, tapAmount);
536      }
537  
538      /// @notice Computes the discounted payment amount for a given OTC amount in USD
539      /// @param _otcAmountInUSD The OTC amount in USD, 18 decimals
540      /// @param _paymentTokenValuation The payment token valuation in USD, 18 decimals
541      /// @param _discount The discount in BPS
542      /// @param _paymentTokenDecimals The payment token decimals
543      /// @return paymentAmount The discounted payment amount
544      function _getDiscountedPaymentAmount(
545          uint256 _otcAmountInUSD,
546          uint256 _paymentTokenValuation,
547          uint256 _discount,
548          uint256 _paymentTokenDecimals
549      ) internal pure returns (uint256 paymentAmount) {
550          // Calculate payment amount
551          uint256 rawPaymentAmount = _otcAmountInUSD / _paymentTokenValuation;
552          paymentAmount =
553              rawPaymentAmount -
554              muldiv(rawPaymentAmount, _discount, 100e4); // 1e4 is discount decimals, 100 is discount percentage
555          paymentAmount = paymentAmount / (10 ** (18 - _paymentTokenDecimals));
556      }
557  
558      /// @notice Emit TAP to the gauges equitably
559      function _emitToGauges(uint256 _epochTAP) internal {
560          SingularityPool[] memory sglPools = tOLP.getSingularityPools();
561          uint256 totalWeights = tOLP.totalSingularityPoolWeights();
562  
563          uint256 len = sglPools.length;
564          unchecked {
565              for (uint256 i = 0; i < len; ++i) {
566                  uint256 currentPoolWeight = sglPools[i].poolWeight;
567                  uint256 quotaPerSingularity = muldiv(
568                      currentPoolWeight,
569                      _epochTAP,
570                      totalWeights
571                  );
572                  singularityGauges[epoch][
573                      sglPools[i].sglAssetID
574                  ] = quotaPerSingularity;
575              }
576          }
577      }
578: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L53-L578

File: contracts/options/TapiocaOptionLiquidityProvision.sol

48   contract TapiocaOptionLiquidityProvision is
49       ERC721,
50       ERC721Permit,
51       BaseBoringBatchable,
52       Pausable,
53       BoringOwnable
54   {
55       uint256 public tokenCounter; // Counter for token IDs
56       mapping(uint256 => LockPosition) public lockPositions; // TokenID => LockPosition
57   
58       IYieldBox public immutable yieldBox;
59   
60       // Singularity market address => SingularityPool (YieldBox Asset ID is 0 if not active)
61       mapping(IERC20 => SingularityPool) public activeSingularities;
62       mapping(uint256 => IERC20) public sglAssetIDToAddress; // Singularity market YieldBox asset ID => Singularity market address
63       uint256[] public singularities; // Array of active singularity asset IDs
64   
65       uint256 public totalSingularityPoolWeights; // Total weight of all active singularity pools
66   
67       constructor(
68           address _yieldBox,
69           address _owner
70       )
71           ERC721("TapiocaOptionLiquidityProvision", "tOLP")
72           ERC721Permit("TapiocaOptionLiquidityProvision")
73       {
74           yieldBox = IYieldBox(_yieldBox);
75           owner = _owner;
76       }
77   
78       // ==========
79       //   EVENTS
80       // ==========
81       event Mint(
82           address indexed to,
83           uint128 indexed sglAssetID,
84           LockPosition lockPosition
85       );
86       event Burn(
87           address indexed to,
88           uint128 indexed sglAssetID,
89           LockPosition lockPosition
90       );
91       event UpdateTotalSingularityPoolWeights(
92           uint256 totalSingularityPoolWeights
93       );
94       event SetSGLPoolWeight(address sgl, uint256 poolWeight);
95       event RegisterSingularity(address sgl, uint256 assetID);
96       event UnregisterSingularity(address sgl, uint256 assetID);
97   
98       // ===============
99       //    MODIFIERS
100      // ===============
101      modifier updateTotalSGLPoolWeights() {
102          _;
103          totalSingularityPoolWeights = _computeSGLPoolWeights();
104          emit UpdateTotalSingularityPoolWeights(totalSingularityPoolWeights);
105      }
106  
107      // =========
108      //    READ
109      // =========
110      /// @notice Returns the lock position of a given tOLP NFT and if it's active
111      /// @param _tokenId tOLP NFT ID
112      function getLock(
113          uint256 _tokenId
114      ) external view returns (bool, LockPosition memory) {
115          LockPosition memory lockPosition = lockPositions[_tokenId];
116  
117          return (_isPositionActive(_tokenId), lockPosition);
118      }
119  
120      /// @notice Returns the active singularity YieldBox ID markets
121      function getSingularities() external view returns (uint256[] memory) {
122          return singularities;
123      }
124  
125      /// @notice Returns the active singularity pool data
126      function getSingularityPools()
127          external
128          view
129          returns (SingularityPool[] memory)
130      {
131          uint256[] memory _singularities = singularities;
132          uint256 len = _singularities.length;
133  
134          SingularityPool[] memory pools = new SingularityPool[](len);
135          unchecked {
136              for (uint256 i = 0; i < len; ++i) {
137                  pools[i] = activeSingularities[
138                      sglAssetIDToAddress[_singularities[i]]
139                  ];
140              }
141          }
142          return pools;
143      }
144  
145      /// @notice Returns the total amount of locked tokens for a given singularity market
146      function getTotalPoolDeposited(
147          uint256 _sglAssetId
148      ) external view returns (uint256) {
149          return
150              activeSingularities[sglAssetIDToAddress[_sglAssetId]]
151                  .totalDeposited;
152      }
153  
154      function isApprovedOrOwner(
155          address _spender,
156          uint256 _tokenId
157      ) external view returns (bool) {
158          return _isApprovedOrOwner(_spender, _tokenId);
159      }
160  
161      // ==========
162      //    WRITE
163      // ==========
164  
165      /// @notice Locks tOLR tokens for a given duration
166      /// @param _to Address to mint the tOLP NFT to
167      /// @param _singularity Singularity market address
168      /// @param _lockDuration Duration of the lock
169      /// @param _amount Amount of tOLR tokens to lock
170      /// @return tokenId The ID of the minted NFT
171      function lock(
172          address _to,
173          IERC20 _singularity,
174          uint128 _lockDuration,
175          uint128 _amount
176      ) external returns (uint256 tokenId) {
177          require(_lockDuration > 0, "tOLP: lock duration must be > 0");
178          require(_amount > 0, "tOLP: amount must be > 0");
179  
180          uint256 sglAssetID = activeSingularities[_singularity].sglAssetID;
181          require(sglAssetID > 0, "tOLP: singularity not active");
182  
183          // Transfer the Singularity position to this contract
184          uint256 sharesIn = yieldBox.toShare(sglAssetID, _amount, false);
185  
186          yieldBox.transfer(msg.sender, address(this), sglAssetID, sharesIn);
187          activeSingularities[_singularity].totalDeposited += _amount;
188  
189          // Mint the tOLP NFT position
190          tokenId = ++tokenCounter;
191          _safeMint(_to, tokenId);
192  
193          // Create the lock position
194          LockPosition storage lockPosition = lockPositions[tokenId];
195          lockPosition.lockTime = uint128(block.timestamp);
196          lockPosition.sglAssetID = uint128(sglAssetID);
197          lockPosition.lockDuration = _lockDuration;
198          lockPosition.amount = _amount;
199  
200          emit Mint(_to, uint128(sglAssetID), lockPosition);
201      }
202  
203      /// @notice Unlocks tOLP tokens
204      /// @param _tokenId ID of the position to unlock
205      /// @param _singularity Singularity market address
206      /// @param _to Address to send the tokens to
207      function unlock(
208          uint256 _tokenId,
209          IERC20 _singularity,
210          address _to
211      ) external returns (uint256 sharesOut) {
212          require(_exists(_tokenId), "tOLP: Expired position");
213  
214          LockPosition memory lockPosition = lockPositions[_tokenId];
215          require(
216              block.timestamp >=
217                  lockPosition.lockTime + lockPosition.lockDuration,
218              "tOLP: Lock not expired"
219          );
220          require(
221              activeSingularities[_singularity].sglAssetID ==
222                  lockPosition.sglAssetID,
223              "tOLP: Invalid singularity"
224          );
225  
226          require(
227              _isApprovedOrOwner(msg.sender, _tokenId),
228              "tOLP: not owner nor approved"
229          );
230  
231          _burn(_tokenId);
232          delete lockPositions[_tokenId];
233  
234          // Transfer the tOLR tokens back to the owner
235          sharesOut = yieldBox.toShare(
236              lockPosition.sglAssetID,
237              lockPosition.amount,
238              false
239          );
240  
241          yieldBox.transfer(
242              address(this),
243              _to,
244              lockPosition.sglAssetID,
245              sharesOut
246          );
247          activeSingularities[_singularity].totalDeposited -= lockPosition.amount;
248  
249          emit Burn(_to, lockPosition.sglAssetID, lockPosition);
250      }
251  
252      // =========
253      //   OWNER
254      // =========
255  
256      /// @notice Sets the pool weight of a given singularity market
257      /// @param singularity Singularity market address
258      /// @param weight Weight of the pool
259      function setSGLPoolWEight(
260          IERC20 singularity,
261          uint256 weight
262      ) external onlyOwner updateTotalSGLPoolWeights {
263          require(
264              activeSingularities[singularity].sglAssetID > 0,
265              "tOLP: not registered"
266          );
267          activeSingularities[singularity].poolWeight = weight;
268  
269          emit SetSGLPoolWeight(address(singularity), weight);
270      }
271  
272      /// @notice Registers a new singularity market
273      /// @param singularity Singularity market address
274      /// @param assetID YieldBox asset ID of the singularity market
275      /// @param weight Weight of the pool
276      function registerSingularity(
277          IERC20 singularity,
278          uint256 assetID,
279          uint256 weight
280      ) external onlyOwner updateTotalSGLPoolWeights {
281          require(assetID > 0, "tOLP: invalid asset ID");
282          require(
283              activeSingularities[singularity].sglAssetID == 0,
284              "tOLP: already registered"
285          );
286  
287          activeSingularities[singularity].sglAssetID = assetID;
288          activeSingularities[singularity].poolWeight = weight > 0 ? weight : 1;
289          sglAssetIDToAddress[assetID] = singularity;
290          singularities.push(assetID);
291  
292          emit RegisterSingularity(address(singularity), assetID);
293      }
294  
295      /// @notice Un-registers a singularity market
296      /// @param singularity Singularity market address
297      function unregisterSingularity(
298          IERC20 singularity
299      ) external onlyOwner updateTotalSGLPoolWeights {
300          uint256 sglAssetID = activeSingularities[singularity].sglAssetID;
301          require(sglAssetID > 0, "tOLP: not registered");
302  
303          unchecked {
304              uint256[] memory _singularities = singularities;
305              uint256 sglLength = _singularities.length;
306              uint256 sglLastIndex = sglLength - 1;
307  
308              for (uint256 i = 0; i < sglLength; i++) {
309                  // If last element, just pop
310                  if (i == sglLastIndex) {
311                      delete activeSingularities[singularity];
312                      delete sglAssetIDToAddress[sglAssetID];
313                      singularities.pop();
314                  } else if (
315                      _singularities[i] == sglAssetID && i < sglLastIndex
316                  ) {
317                      // If in the middle, copy last element on deleted element, then pop
318                      delete activeSingularities[singularity];
319                      delete sglAssetIDToAddress[sglAssetID];
320  
321                      singularities[i] = _singularities[sglLastIndex];
322                      singularities.pop();
323                      break;
324                  }
325              }
326          }
327  
328          emit UnregisterSingularity(address(singularity), sglAssetID);
329      }
330  
331      // =========
332      //  INTERNAL
333      // =========
334  
335      /// @notice Compute the total pool weight of all active singularity markets
336      function _computeSGLPoolWeights() internal view returns (uint256) {
337          uint256 total;
338          uint256 len = singularities.length;
339          for (uint256 i = 0; i < len; i++) {
340              total += activeSingularities[sglAssetIDToAddress[singularities[i]]]
341                  .poolWeight;
342          }
343  
344          return total;
345      }
346  
347      /// @notice Checks if the lock position is still active
348      function _isPositionActive(uint256 tokenId) internal view returns (bool) {
349          LockPosition memory lockPosition = lockPositions[tokenId];
350  
351          return
352              (lockPosition.lockTime + lockPosition.lockDuration) >=
353              block.timestamp;
354      }
355  
356      /// @notice ERC1155 compliance
357      function onERC1155Received(
358          address,
359          address,
360          uint256,
361          uint256,
362          bytes calldata
363      ) external pure returns (bytes4) {
364          return
365              bytes4(
366                  keccak256(
367                      "onERC1155Received(address,address,uint256,uint256,bytes)"
368                  )
369              );
370      }
371: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L48-L371

File: contracts/tokens/BaseTapOFT.sol

31   abstract contract BaseTapOFT is OFTV2 {
32       using ExcessivelySafeCall for address;
33       using BytesLib for bytes;
34   
35       TwTAP public twTap;
36   
37       uint16 internal constant PT_LOCK_TWTAP = 870;
38       uint16 internal constant PT_UNLOCK_TWTAP = 871;
39       uint16 internal constant PT_CLAIM_REWARDS = 872;
40   
41       event CallFailedStr(uint16 _srcChainId, bytes _payload, string _reason);
42       event CallFailedBytes(uint16 _srcChainId, bytes _payload, bytes _reason);
43   
44       constructor(
45           string memory _name,
46           string memory _symbol,
47           uint8 _sharedDec,
48           address _lzEndpoint
49       ) OFTV2(_name, _symbol, _sharedDec, _lzEndpoint) {}
50   
51       //---LZ---
52       function _nonblockingLzReceive(
53           uint16 _srcChainId,
54           bytes memory _srcAddress,
55           uint64 _nonce,
56           bytes memory _payload
57       ) internal virtual override {
58           uint256 packetType = _payload.toUint256(0);
59   
60           if (packetType == PT_LOCK_TWTAP) {
61               _lockTwTapPosition(_srcChainId, _payload);
62           } else if (packetType == PT_UNLOCK_TWTAP) {
63               _unlockTwTapPosition(_srcChainId, _payload);
64           } else if (packetType == PT_CLAIM_REWARDS) {
65               _claimRewards(_srcChainId, _payload);
66           } else {
67               packetType = _payload.toUint8(0);
68               if (packetType == PT_SEND) {
69                   _sendAck(_srcChainId, _srcAddress, _nonce, _payload);
70               } else if (packetType == PT_SEND_AND_CALL) {
71                   _sendAndCallAck(_srcChainId, _srcAddress, _nonce, _payload);
72               } else {
73                   revert("TOFT_packet");
74               }
75           }
76       }
77   
78       /// --------------------------
79       /// ------- LOCK TWTAP -------
80       /// --------------------------
81   
82       /// @notice Opens a twTAP by participating in twAML.
83       /// @param to The address to add the twTAP position to.
84       /// @param amount The amount to add.
85       /// @param lzDstChainId The destination chain id.
86       /// @param zroPaymentAddress The address to send the ZRO payment to.
87       /// @param adapterParams The adapter params.
88       function lockTwTapPosition(
89           address to,
90           uint256 amount, // Amount to add
91           uint256 duration, // Duration of the position.
92           uint16 lzDstChainId,
93           address zroPaymentAddress,
94           bytes calldata adapterParams
95       ) external payable {
96           bytes memory lzPayload = abi.encode(
97               PT_LOCK_TWTAP, // packet type
98               msg.sender,
99               to,
100              amount,
101              duration
102          );
103  
104          require(duration > 0, "TapOFT: Small duration");
105          bytes32 senderBytes = LzLib.addressToBytes32(msg.sender);
106          _debitFrom(msg.sender, lzEndpoint.getChainId(), senderBytes, amount);
107  
108          _lzSend(
109              lzDstChainId,
110              lzPayload,
111              payable(msg.sender),
112              zroPaymentAddress,
113              adapterParams,
114              msg.value
115          );
116  
117          emit SendToChain(
118              lzDstChainId,
119              msg.sender,
120              LzLib.addressToBytes32(to),
121              0
122          );
123      }
124  
125      function _lockTwTapPosition(
126          uint16 _srcChainId,
127          bytes memory _payload
128      ) internal virtual {
129          (, , address to, uint256 amount, uint duration) = abi.decode(
130              _payload,
131              (uint16, address, address, uint256, uint256)
132          );
133  
134          _creditTo(_srcChainId, address(this), amount);
135          approve(address(twTap), amount);
136  
137          // We participate and mint with TapOFT as a receiver
138          try twTap.participate(to, amount, duration) {} catch Error(
139              string memory _reason
140          ) {
141              // If the process fails, we send back the funds to the user
142              // We send back the funds to the user
143              emit CallFailedStr(_srcChainId, _payload, _reason);
144              _transferFrom(address(this), to, amount);
145          } catch (bytes memory _reason) {
146              emit CallFailedBytes(_srcChainId, _payload, _reason);
147              _transferFrom(address(this), to, amount);
148          }
149      }
150  
151      /// ------------------------------
152      /// ------- CLAIM REWARDS --------
153      /// ------------------------------
154  
155      /// @notice Claim rewards from a twTAP position.
156      /// @param to The address to add the twTAP position to.
157      /// @param tokenID Token ID of the twTAP position.
158      /// @param rewardTokens The address of the reward tokens.
159      /// @param lzDstChainId The destination chain id.
160      /// @param zroPaymentAddress The address to send the ZRO payment to.
161      /// @param adapterParams The adapter params.
162      /// @param rewardClaimSendParams The adapter params to send back the TAP token.
163      function claimRewards(
164          address to,
165          uint256 tokenID,
166          address[] memory rewardTokens,
167          uint16 lzDstChainId,
168          address zroPaymentAddress,
169          bytes calldata adapterParams,
170          IRewardClaimSendFromParams[] calldata rewardClaimSendParams
171      ) external payable {
172          bytes memory lzPayload = abi.encode(
173              PT_CLAIM_REWARDS, // packet type
174              msg.sender,
175              to,
176              tokenID,
177              rewardTokens,
178              rewardClaimSendParams
179          );
180  
181          _lzSend(
182              lzDstChainId,
183              lzPayload,
184              payable(msg.sender),
185              zroPaymentAddress,
186              adapterParams,
187              msg.value
188          );
189  
190          emit SendToChain(
191              lzDstChainId,
192              msg.sender,
193              LzLib.addressToBytes32(to),
194              0
195          );
196      }
197  
198      function _claimRewards(
199          uint16 _srcChainId,
200          bytes memory _payload
201      ) internal virtual {
202          (
203              ,
204              ,
205              address to,
206              uint256 tokenID,
207              IERC20[] memory rewardTokens,
208              IRewardClaimSendFromParams[] memory rewardClaimSendParams
209          ) = abi.decode(
210                  _payload,
211                  (
212                      uint16,
213                      address,
214                      address,
215                      uint256,
216                      IERC20[],
217                      IRewardClaimSendFromParams[]
218                  )
219              );
220  
221          // Only the owner can unlock
222          require(twTap.ownerOf(tokenID) == to, "TapOFT: Not owner");
223  
224          // Exit and receive tokens to this contract
225          try twTap.claimAndSendRewards(tokenID, rewardTokens) {
226              // Transfer them to the user
227              uint256 len = rewardTokens.length;
228              for (uint i = 0; i < len; ) {
229                  ISendFrom(address(rewardTokens[i])).sendFrom{
230                      value: rewardClaimSendParams[i].ethValue
231                  }(
232                      address(this),
233                      _srcChainId,
234                      LzLib.addressToBytes32(to),
235                      IERC20(rewardTokens[i]).balanceOf(address(this)),
236                      rewardClaimSendParams[i].callParams
237                  );
238                  ++i;
239              }
240          } catch Error(string memory _reason) {
241              emit CallFailedStr(_srcChainId, _payload, _reason);
242          } catch (bytes memory _reason) {
243              emit CallFailedBytes(_srcChainId, _payload, _reason);
244          }
245      }
246  
247      /// --------------------------
248      /// ------- UNLOCK TWTAP -------
249      /// --------------------------
250  
251      /// @notice Exit a twTAP by participating in twAML.
252      /// @param to The address to add the twTAP position to.
253      /// @param tokenID Token ID of the twTAP position.
254      /// @param lzDstChainId The destination chain id.
255      /// @param zroPaymentAddress The address to send the ZRO payment to.
256      /// @param adapterParams The adapter params.
257      /// @param twTapSendBackAdapterParams The adapter params to send back the TAP token.
258      function unlockTwTapPosition(
259          address to,
260          uint256 tokenID,
261          uint16 lzDstChainId,
262          address zroPaymentAddress,
263          bytes calldata adapterParams,
264          LzCallParams calldata twTapSendBackAdapterParams
265      ) external payable {
266          bytes memory lzPayload = abi.encode(
267              PT_UNLOCK_TWTAP, // packet type
268              msg.sender,
269              to,
270              tokenID,
271              twTapSendBackAdapterParams
272          );
273  
274          _lzSend(
275              lzDstChainId,
276              lzPayload,
277              payable(msg.sender),
278              zroPaymentAddress,
279              adapterParams,
280              msg.value
281          );
282  
283          emit SendToChain(
284              lzDstChainId,
285              msg.sender,
286              LzLib.addressToBytes32(to),
287              0
288          );
289      }
290  
291      function _unlockTwTapPosition(
292          uint16 _srcChainId,
293          bytes memory _payload
294      ) internal virtual {
295          (
296              ,
297              ,
298              address to,
299              uint256 tokenID,
300              LzCallParams memory twTapSendBackAdapterParams
301          ) = abi.decode(
302                  _payload,
303                  (uint16, address, address, uint256, LzCallParams)
304              );
305  
306          // Only the owner can unlock
307          require(twTap.ownerOf(tokenID) == to, "TapOFT: Not owner");
308  
309          // Exit and receive tokens to this contract
310          try twTap.exitPositionAndSendTap(tokenID) returns (uint256 _amount) {
311              // Transfer them to the user
312              this.sendFrom{value: address(this).balance}(
313                  address(this),
314                  _srcChainId,
315                  LzLib.addressToBytes32(to),
316                  _amount,
317                  twTapSendBackAdapterParams
318              );
319          } catch Error(string memory _reason) {
320              emit CallFailedStr(_srcChainId, _payload, _reason);
321          } catch (bytes memory _reason) {
322              emit CallFailedBytes(_srcChainId, _payload, _reason);
323          }
324      }
325  
326      function setTwTap(address _twTap) external onlyOwner {
327          twTap = TwTAP(_twTap);
328      }
329  
330      receive() external payable virtual {}
331  
332      function _callApproval(ICommonData.IApproval[] memory approvals) private {
333          for (uint256 i = 0; i < approvals.length; ) {
334              try
335                  IERC20Permit(approvals[i].target).permit(
336                      approvals[i].owner,
337                      approvals[i].spender,
338                      approvals[i].value,
339                      approvals[i].deadline,
340                      approvals[i].v,
341                      approvals[i].r,
342                      approvals[i].s
343                  )
344              {} catch Error(string memory reason) {
345                  if (!approvals[i].allowFailure) {
346                      revert(reason);
347                  }
348              }
349  
350              unchecked {
351                  ++i;
352              }
353          }
354      }
355: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L31-L355

File: contracts/tokens/LTap.sol

23   contract LTap is BoringOwnable, ERC20Permit {
24       IERC20 tapToken;
25       uint256 public lockedUntil;
26       uint256 public maxLockedUntil;
27   
28       /// @notice Creates a new LTAP token
29       /// @dev LTAP tokens are minted by depositing TAP
30       /// @param _tapToken Address of the TAP token
31       /// @param _maxLockedUntil Latest possible end of locking period
32       constructor(
33           IERC20 _tapToken,
34           uint256 _maxLockedUntil
35       ) ERC20("LTAP", "LTAP") ERC20Permit("LTAP") {
36           tapToken = _tapToken;
37           lockedUntil = _maxLockedUntil;
38           maxLockedUntil = _maxLockedUntil;
39       }
40   
41       function deposit(uint256 amount) external {
42           tapToken.transferFrom(msg.sender, address(this), amount);
43           _mint(msg.sender, amount);
44       }
45   
46       function redeem() external {
47           require(block.timestamp > lockedUntil, "Still locked");
48           uint256 amount = balanceOf(msg.sender);
49           _burn(msg.sender, amount);
50           tapToken.transfer(msg.sender, amount);
51       }
52   
53       function setLockedUntil(uint256 _lockedUntil) external onlyOwner {
54           require(_lockedUntil <= maxLockedUntil, "Too late");
55           lockedUntil = _lockedUntil;
56       }
57:  }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L23-L57

File: contracts/tokens/TapOFT.sol

26   contract TapOFT is BaseTapOFT, ERC20Permit {
27       // ==========
28       // *DATA*
29       // ==========
30   
31       //  Allocation:
32       // =========
33       // * DSO: 53,313,405
34       // * DAO: 8m
35       // * Contributors: 15m
36       // * Early supporters: 3,686,595
37       // * Supporters: 12.5m
38       // * LBP: 5m
39       // * Airdrop: 2.5m
40       // == 100M ==
41       uint256 public constant INITIAL_SUPPLY = 46_686_595 * 1e18; // Everything minus DSO
42       uint256 public dso_supply = 53_313_405 * 1e18;
43   
44       /// @notice the a parameter used in the emission function;
45       uint256 constant decay_rate = 8800000000000000; // 0.88%
46       uint256 constant DECAY_RATE_DECIMAL = 1e18;
47   
48       /// @notice seconds in a week
49       uint256 public constant WEEK = 604800;
50   
51       /// @notice starts time for emissions
52       /// @dev initialized in the constructor with block.timestamp
53       uint256 public immutable emissionsStartTime;
54   
55       /// @notice returns the amount of emitted TAP for a specific week
56       /// @dev week is computed using (timestamp - emissionStartTime) / WEEK
57       mapping(uint256 => uint256) public emissionForWeek;
58   
59       /// @notice returns the amount minted for a specific week
60       /// @dev week is computed using (timestamp - emissionStartTime) / WEEK
61       mapping(uint256 => uint256) public mintedInWeek;
62   
63       /// @notice returns the minter address
64       address public minter;
65   
66       /// @notice LayerZero governance chain identifier
67       uint256 public governanceChainIdentifier;
68   
69       /// @notice returns the pause state of the contract
70       bool public paused;
71   
72       // ==========
73       // *EVENTS*
74       // ==========
75       /// @notice event emitted when a new minter is set
76       event MinterUpdated(address indexed _old, address indexed _new);
77       /// @notice event emitted when a new emission is called
78       event Emitted(uint256 week, uint256 amount);
79       /// @notice event emitted when new TAP is minted
80       event Minted(address indexed _by, address indexed _to, uint256 _amount);
81       /// @notice event emitted when new TAP is burned
82       event Burned(address indexed _from, uint256 _amount);
83       /// @notice event emitted when the governance chain identifier is updated
84       event GovernanceChainIdentifierUpdated(uint256 _old, uint256 _new);
85       /// @notice event emitted when pause state is changed
86       event PausedUpdated(bool oldState, bool newState);
87   
88       modifier notPaused() {
89           require(!paused, "TAP: paused");
90           _;
91       }
92   
93       // ==========
94       // * METHODS *
95       // ==========
96       /// @notice Creates a new TAP OFT type token
97       /// @dev The initial supply of 100M is not minted here as we have the wrap method
98       /// @param _lzEndpoint the layer zero address endpoint deployed on the current chain
99       /// @param _contributors address of the  contributors. 15m
100      /// @param _earlySupporters address of early supporters. 3,686,595
101      /// @param _supporters address of supporters. 12.5m
102      /// @param _lbp address of the LBP. 5m
103      /// @param _dao address of the DAO. 8m
104      /// @param _airdrop address of the airdrop contract. 2.5m
105      /// @param _governanceChainId LayerZero governance chain identifier
106      /// @param _conservator address of the conservator/owner
107      constructor(
108          address _lzEndpoint,
109          address _contributors,
110          address _earlySupporters,
111          address _supporters,
112          address _lbp,
113          address _dao,
114          address _airdrop,
115          uint256 _governanceChainId,
116          address _conservator
117      ) BaseTapOFT("TapOFT", "TAP", 8, _lzEndpoint) ERC20Permit("TapOFT") {
118          require(_lzEndpoint != address(0), "LZ endpoint not valid");
119          governanceChainIdentifier = _governanceChainId;
120          if (_getChainId() == governanceChainIdentifier) {
121              _mint(_contributors, 1e18 * 15_000_000);
122              _mint(_earlySupporters, 1e18 * 3_686_595);
123              _mint(_supporters, 1e18 * 12_500_000);
124              _mint(_lbp, 1e18 * 5_000_000);
125              _mint(_dao, 1e18 * 8_000_000);
126              _mint(_airdrop, 1e18 * 2_500_000);
127              require(
128                  totalSupply() == INITIAL_SUPPLY,
129                  "initial supply not valid"
130              );
131          }
132          emissionsStartTime = block.timestamp;
133  
134          transferOwnership(_conservator);
135      }
136  
137      ///-- Owner methods --
138      /// @notice sets the governance chain identifier
139      /// @param _identifier LayerZero chain identifier
140      function setGovernanceChainIdentifier(
141          uint256 _identifier
142      ) external onlyOwner {
143          emit GovernanceChainIdentifierUpdated(
144              governanceChainIdentifier,
145              _identifier
146          );
147          governanceChainIdentifier = _identifier;
148      }
149  
150      /// @notice updates the pause state of the contract
151      /// @param val the new value
152      function updatePause(bool val) external onlyOwner {
153          require(val != paused, "TAP: same state");
154          emit PausedUpdated(paused, val);
155          paused = val;
156      }
157  
158      /// @notice sets a new minter address
159      /// @param _minter the new address
160      function setMinter(address _minter) external onlyOwner {
161          require(_minter != address(0), "address not valid");
162          emit MinterUpdated(minter, _minter);
163          minter = _minter;
164      }
165  
166      //-- View methods --
167      /// @notice returns token's decimals
168      function decimals() public pure override returns (uint8) {
169          return 18;
170      }
171  
172      /// @notice Returns the current week given a timestamp
173      function timestampToWeek(
174          uint256 timestamp
175      ) external view returns (uint256) {
176          if (timestamp == 0) {
177              timestamp = block.timestamp;
178          }
179          if (timestamp < emissionsStartTime) return 0;
180  
181          return _timestampToWeek(timestamp);
182      }
183  
184      /// @notice Returns the current week
185      function getCurrentWeek() external view returns (uint256) {
186          return _timestampToWeek(block.timestamp);
187      }
188  
189      /// @notice Returns the current week emission
190      function getCurrentWeekEmission() external view returns (uint256) {
191          return emissionForWeek[_timestampToWeek(block.timestamp)];
192      }
193  
194      ///-- Write methods --
195      /// @notice Emit the TAP for the current week
196      /// @return the emitted amount
197      function emitForWeek() external notPaused returns (uint256) {
198          require(_getChainId() == governanceChainIdentifier, "chain not valid");
199  
200          uint256 week = _timestampToWeek(block.timestamp);
201          if (emissionForWeek[week] > 0) return 0;
202  
203          // Update DSO supply from last minted emissions
204          dso_supply -= mintedInWeek[week - 1];
205  
206          // Compute unclaimed emission from last week and add it to the current week emission
207          uint256 unclaimed = emissionForWeek[week - 1] - mintedInWeek[week - 1];
208          uint256 emission = uint256(_computeEmission());
209          emission += unclaimed;
210          emissionForWeek[week] = emission;
211  
212          emit Emitted(week, emission);
213  
214          return emission;
215      }
216  
217      /// @notice extracts from the minted TAP
218      /// @param _to Address to send the minted TAP to
219      /// @param _amount TAP amount
220      function extractTAP(address _to, uint256 _amount) external notPaused {
221          require(msg.sender == minter, "unauthorized");
222          require(_amount > 0, "amount not valid");
223  
224          uint256 week = _timestampToWeek(block.timestamp);
225          require(emissionForWeek[week] >= _amount, "exceeds allowable amount");
226          _mint(_to, _amount);
227          mintedInWeek[week] += _amount;
228          emit Minted(msg.sender, _to, _amount);
229      }
230  
231      /// @notice burns TAP
232      /// @param _amount TAP amount
233      function removeTAP(uint256 _amount) external notPaused {
234          _burn(msg.sender, _amount);
235          emit Burned(msg.sender, _amount);
236      }
237  
238      ///-- Internal methods --
239      function _timestampToWeek(
240          uint256 timestamp
241      ) internal view returns (uint256) {
242          return ((timestamp - emissionsStartTime) / WEEK) + 1; // Starts at week 1
243      }
244  
245      ///-- Private methods --
246      /// @notice Return the current chain ID.
247      /// @dev Useful for testing.
248      function _getChainId() private view returns (uint256) {
249          return block.chainid;
250      }
251  
252      /// @notice returns the available emissions for a given supply
253      function _computeEmission() internal view returns (uint256 result) {
254          result = (dso_supply * decay_rate) / DECAY_RATE_DECIMAL;
255      }
256: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L26-L256

File: contracts/Swapper/UniswapV3Swapper.sol

28   contract UniswapV3Swapper is BaseSwapper {
29       using SafeERC20 for IERC20;
30   
31       // ************ //
32       // *** VARS *** //
33       // ************ //
34       IYieldBox private immutable yieldBox;
35       ISwapRouter public immutable swapRouter;
36       IUniswapV3Factory public immutable factory;
37   
38       uint24 public poolFee = 3000;
39   
40       // ************** //
41       // *** EVENTS *** //
42       // ************** //
43       event PoolFee(uint256 _old, uint256 _new);
44   
45       constructor(
46           IYieldBox _yieldBox,
47           ISwapRouter _swapRouter,
48           IUniswapV3Factory _factory
49       )
50           validAddress(address(_yieldBox))
51           validAddress(address(_swapRouter))
52           validAddress(address(_factory))
53       {
54           yieldBox = _yieldBox;
55           swapRouter = _swapRouter;
56           factory = _factory;
57       }
58   
59       /// *** OWNER METHODS ***
60       /// ***  ***
61       function setPoolFee(uint24 _newFee) external onlyOwner {
62           emit PoolFee(poolFee, _newFee);
63           poolFee = _newFee;
64       }
65   
66       /// *** VIEW METHODS ***
67       /// ***  ***
68       /// @notice returns default bytes swap data
69       function getDefaultDexOptions()
70           public
71           view
72           override
73           returns (bytes memory)
74       {
75           return abi.encode(block.timestamp + 1 hours);
76       }
77   
78       /// @notice Computes amount out for amount in
79       /// @param swapData operation data
80       function getOutputAmount(
81           SwapData calldata swapData,
82           bytes calldata
83       ) external view override returns (uint256 amountOut) {
84           (address tokenIn, address tokenOut) = _getTokens(
85               swapData.tokensData,
86               yieldBox
87           );
88   
89           (uint256 amountIn, ) = _getAmounts(
90               swapData.amountData,
91               swapData.tokensData.tokenInId,
92               swapData.tokensData.tokenOutId,
93               yieldBox
94           );
95   
96           address pool = factory.getPool(tokenIn, tokenOut, poolFee);
97           (int24 tick, ) = OracleLibrary.consult(pool, 60);
98   
99           amountOut = OracleLibrary.getQuoteAtTick(
100              tick,
101              uint128(amountIn),
102              tokenIn,
103              tokenOut
104          );
105      }
106  
107      /// @notice Comutes amount in for amount out
108      function getInputAmount(
109          SwapData calldata swapData,
110          bytes calldata
111      ) external view override returns (uint256 amountIn) {
112          (address tokenIn, address tokenOut) = _getTokens(
113              swapData.tokensData,
114              yieldBox
115          );
116  
117          (, uint256 amountOut) = _getAmounts(
118              swapData.amountData,
119              swapData.tokensData.tokenInId,
120              swapData.tokensData.tokenOutId,
121              yieldBox
122          );
123  
124          address pool = factory.getPool(tokenIn, tokenOut, poolFee);
125  
126          (int24 tick, ) = OracleLibrary.consult(pool, 60);
127          amountIn = OracleLibrary.getQuoteAtTick(
128              tick,
129              uint128(amountOut),
130              tokenOut,
131              tokenIn
132          );
133      }
134  
135      /// *** PUBLIC METHODS ***
136      /// ***  ***
137      /// @notice swaps amount in
138      /// @param swapData operation data
139      /// @param amountOutMin min amount out to receive
140      /// @param to receiver address
141      /// @param data AMM data
142      function swap(
143          SwapData calldata swapData,
144          uint256 amountOutMin,
145          address to,
146          bytes memory data
147      ) external override returns (uint256 amountOut, uint256 shareOut) {
148          // Get tokens' addresses
149          (address tokenIn, address tokenOut) = _getTokens(
150              swapData.tokensData,
151              yieldBox
152          );
153  
154          // Get tokens' amounts
155          (uint256 amountIn, ) = _getAmounts(
156              swapData.amountData,
157              swapData.tokensData.tokenInId,
158              swapData.tokensData.tokenOutId,
159              yieldBox
160          );
161  
162          // Retrieve tokens from sender or from YieldBox
163          amountIn = _extractTokens(
164              swapData.yieldBoxData,
165              yieldBox,
166              tokenIn,
167              swapData.tokensData.tokenInId,
168              amountIn,
169              swapData.amountData.shareIn
170          );
171  
172          TransferHelper.safeApprove(tokenIn, address(swapRouter), amountIn);
173  
174          // Perform the swap operation
175          if (data.length == 0) {
176              data = getDefaultDexOptions();
177          }
178          uint256 deadline = abi.decode(data, (uint256));
179  
180          ISwapRouter.ExactInputSingleParams memory params = ISwapRouter
181              .ExactInputSingleParams({
182                  tokenIn: tokenIn,
183                  tokenOut: tokenOut,
184                  fee: poolFee,
185                  recipient: swapData.yieldBoxData.depositToYb
186                      ? address(this)
187                      : to,
188                  deadline: deadline,
189                  amountIn: amountIn,
190                  amountOutMinimum: amountOutMin,
191                  sqrtPriceLimitX96: 0
192              });
193  
194          // Compute outputs
195          amountOut = swapRouter.exactInputSingle(params);
196          if (swapData.yieldBoxData.depositToYb) {
197              _safeApprove(tokenOut, address(yieldBox), amountOut);
198              (, shareOut) = yieldBox.depositAsset(
199                  swapData.tokensData.tokenOutId,
200                  address(this),
201                  to,
202                  amountOut,
203                  0
204              );
205          }
206      }
207: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L28-L207

File: contracts/NativeTokenFactory.sol

21   contract NativeTokenFactory is AssetRegister {
22       using BoringMath for uint256;
23   
24       mapping(uint256 => NativeToken) public nativeTokens;
25       mapping(uint256 => address) public owner;
26       mapping(uint256 => address) public pendingOwner;
27   
28       event TokenCreated(address indexed creator, string name, string symbol, uint8 decimals, uint256 tokenId);
29       event OwnershipTransferred(uint256 indexed tokenId, address indexed previousOwner, address indexed newOwner);
30   
31       // ***************** //
32       // *** MODIFIERS *** //
33       // ***************** //
34   
35       /// Modifier to check if the msg.sender is allowed to use funds belonging to the 'from' address.
36       /// If 'from' is msg.sender, it's allowed.
37       /// If 'msg.sender' is an address (an operator) that is approved by 'from', it's allowed.
38       modifier allowed(address _from, uint256 _id) {
39           _requireTransferAllowed(_from, isApprovedForAsset[_from][msg.sender][_id]);
40           _;
41       }
42   
43       /// @notice Only allows the `owner` to execute the function.
44       /// @param tokenId The `tokenId` that the sender has to be owner of.
45       modifier onlyOwner(uint256 tokenId) {
46           require(msg.sender == owner[tokenId], "NTF: caller is not the owner");
47           _;
48       }
49   
50       /// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.
51       /// Can only be invoked by the current `owner`.
52       /// @param tokenId The `tokenId` of the token that ownership whose ownership will be transferred/renounced.
53       /// @param newOwner Address of the new owner.
54       /// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.
55       /// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.
56       function transferOwnership(uint256 tokenId, address newOwner, bool direct, bool renounce) public onlyOwner(tokenId) {
57           if (direct) {
58               // Checks
59               require(newOwner != address(0) || renounce, "NTF: zero address");
60   
61               // Effects
62               emit OwnershipTransferred(tokenId, owner[tokenId], newOwner);
63               owner[tokenId] = newOwner;
64               pendingOwner[tokenId] = address(0);
65           } else {
66               // Effects
67               pendingOwner[tokenId] = newOwner;
68           }
69       }
70   
71       /// @notice Needs to be called by `pendingOwner` to claim ownership.
72       /// @param tokenId The `tokenId` of the token that ownership is claimed for.
73       function claimOwnership(uint256 tokenId) public {
74           address _pendingOwner = pendingOwner[tokenId];
75   
76           // Checks
77           require(msg.sender == _pendingOwner, "NTF: caller != pending owner");
78   
79           // Effects
80           emit OwnershipTransferred(tokenId, owner[tokenId], _pendingOwner);
81           owner[tokenId] = _pendingOwner;
82           pendingOwner[tokenId] = address(0);
83       }
84   
85       /// @notice Create a new native token. This will be an ERC1155 token. If later it's needed as an ERC20 token it can
86       /// be wrapped into an ERC20 token. Native support for ERC1155 tokens is growing though.
87       /// @param name The name of the token.
88       /// @param symbol The symbol of the token.
89       /// @param decimals The number of decimals of the token (this is just for display purposes). Should be set to 18 in normal cases.
90       function createToken(string calldata name, string calldata symbol, uint8 decimals, string calldata uri) public returns (uint32 tokenId) {
91           // To keep each Token unique in the AssetRegister, we use the assetId as the tokenId. So for native assets, the tokenId is always equal to the assetId.
92           tokenId = assets.length.to32();
93           _registerAsset(TokenType.Native, address(0), NO_STRATEGY, tokenId);
94           // Initial supply is 0, use owner can mint. For a fixed supply the owner can mint and revoke ownership.
95           // The msg.sender is the initial owner, can be changed after.
96           nativeTokens[tokenId] = NativeToken(name, symbol, decimals, uri);
97           owner[tokenId] = msg.sender;
98   
99           emit TokenCreated(msg.sender, name, symbol, decimals, tokenId);
100          emit TransferSingle(msg.sender, address(0), address(0), tokenId, 0);
101          emit OwnershipTransferred(tokenId, address(0), msg.sender);
102      }
103  
104      /// @notice The `owner` can mint tokens. If a fixed supply is needed, the `owner` should mint the totalSupply and renounce ownership.
105      /// @param tokenId The token to be minted.
106      /// @param to The account to transfer the minted tokens to.
107      /// @param amount The amount of tokens to mint.
108      /// @dev For security reasons, operators are not allowed to mint. Only the actual owner can do this. Of course the owner can be a contract.
109      function mint(uint256 tokenId, address to, uint256 amount) public onlyOwner(tokenId) {
110          _mint(to, tokenId, amount);
111      }
112  
113      /// @notice Burns tokens. Only the holder of tokens can burn them or an approved operator.
114      /// @param tokenId The token to be burned.
115      /// @param amount The amount of tokens to burn.
116      function burn(uint256 tokenId, address from, uint256 amount) public allowed(from, tokenId) {
117          require(assets[tokenId].tokenType == TokenType.Native, "NTF: Not native");
118          _burn(from, tokenId, amount);
119      }
120  
121      /// @notice The `owner` can mint tokens. If a fixed supply is needed, the `owner` should mint the totalSupply and renounce ownership.
122      /// @param tokenId The token to be minted.
123      /// @param tos The accounts to transfer the minted tokens to.
124      /// @param amounts The amounts of tokens to mint.
125      /// @dev If the tos array is longer than the amounts array there will be an out of bounds error. If the amounts array is longer, the extra amounts are simply ignored.
126      /// @dev For security reasons, operators are not allowed to mint. Only the actual owner can do this. Of course the owner can be a contract.
127      function batchMint(uint256 tokenId, address[] calldata tos, uint256[] calldata amounts) public onlyOwner(tokenId) {
128          uint256 len = tos.length;
129          for (uint256 i = 0; i < len; i++) {
130              _mint(tos[i], tokenId, amounts[i]);
131          }
132      }
133  
134      /// @notice Burns tokens. This is only useful to be used by an operator.
135      /// @param tokenId The token to be burned.
136      /// @param froms The accounts to burn tokens from.
137      /// @param amounts The amounts of tokens to burn.
138      function batchBurn(uint256 tokenId, address[] calldata froms, uint256[] calldata amounts) public {
139          require(assets[tokenId].tokenType == TokenType.Native, "NTF: Not native");
140          uint256 len = froms.length;
141          for (uint256 i = 0; i < len; i++) {
142              _requireTransferAllowed(froms[i], isApprovedForAsset[froms[i]][msg.sender][tokenId]);
143              _burn(froms[i], tokenId, amounts[i]);
144          }
145      }
146: }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L21-L146

[N‑13] Events may be emitted out of order due to reentrancy

Ensure that events follow the best practice of check-effects-interaction, and are emitted before external calls

There are 23 instances of this issue:

see instances
File: contracts/markets/bigBang/BigBang.sol

/// @audit swappers() prior to emission of Liquidated()
629          emit Liquidated(
630              msg.sender,
631              _users,
632              callerShare,
633              feeShare,
634              borrowAmount,
635              collateralShare
636:         );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L629-L636

File: contracts/markets/singularity/SGLLiquidation.sol

/// @audit swappers() prior to emission of Liquidated()
360          emit Liquidated(
361              msg.sender,
362              _users,
363              callerShare,
364              feeShare,
365              borrowAmount,
366              collateralShare
367:         );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L360-L367

File: contracts/usd0/modules/USDOLeverageModule.sol

/// @audit safeTransfer() prior to emission of ReceiveFromChain()
187:         emit ReceiveFromChain(_srcChainId, leverageFor, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L187-L187

File: contracts/usd0/modules/USDOMarketModule.sol

/// @audit safeTransfer() prior to emission of ReceiveFromChain()
188:         emit ReceiveFromChain(_srcChainId, to, lendParams.depositAmount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol#L188-L188

File: contracts/usd0/modules/USDOOptionsModule.sol

/// @audit safeTransfer() prior to emission of ReceiveFromChain()
199          emit ReceiveFromChain(
200              _srcChainId,
201              optionsData.from,
202              optionsData.paymentTokenAmount
203:         );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol#L199-L203

File: contracts/TapiocaWrapper.sol

/// @audit push() prior to emission of CreateOFT()
177:         emit CreateOFT(iOFT, _erc20);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L177-L177

File: contracts/tOFT/mTapiocaOFT.sol

/// @audit safeTransfer() prior to emission of Rebalancing()
151:         emit Rebalancing(msg.sender, _amount, _isNative);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol#L151-L151

File: contracts/tOFT/modules/BaseTOFTLeverageModule.sol

/// @audit safeTransfer() prior to emission of ReceiveFromChain()
202:         emit ReceiveFromChain(_srcChainId, leverageFor, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L202-L202

File: contracts/tOFT/modules/BaseTOFTMarketModule.sol

/// @audit safeTransfer() prior to emission of ReceiveFromChain()
177:         emit ReceiveFromChain(_srcChainId, _from, borrowParams.amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L177-L177

File: contracts/tOFT/modules/BaseTOFTOptionsModule.sol

/// @audit safeTransfer() prior to emission of ReceiveFromChain()
214          emit ReceiveFromChain(
215              _srcChainId,
216              optionsData.from,
217              optionsData.paymentTokenAmount
218:         );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol#L214-L218

File: contracts/tOFT/modules/BaseTOFTStrategyModule.sol

/// @audit safeTransfer() prior to emission of ReceiveFromChain()
170:         emit ReceiveFromChain(_srcChainId, onBehalfOf, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol#L170-L170

File: contracts/Vesting.sol

/// @audit safeTransfer() prior to emission of Claimed()
120:         emit Claimed(msg.sender, _claimable);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L120-L120

File: contracts/aave/AaveStrategy.sol

/// @audit safeTransfer() prior to emission of AmountWithdrawn()
274:         emit AmountWithdrawn(to, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L274-L274

File: contracts/balancer/BalancerStrategy.sol

/// @audit safeTransfer() prior to emission of AmountWithdrawn()
215:         emit AmountWithdrawn(to, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L215-L215

File: contracts/compound/CompoundStrategy.sol

/// @audit safeTransfer() prior to emission of AmountWithdrawn()
161:         emit AmountWithdrawn(to, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L161-L161

File: contracts/convex/ConvexTricryptoStrategy.sol

/// @audit safeTransfer() prior to emission of AmountWithdrawn()
351:         emit AmountWithdrawn(to, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L351-L351

File: contracts/curve/TricryptoLPStrategy.sol

/// @audit safeTransfer() prior to emission of AmountWithdrawn()
253:         emit AmountWithdrawn(to, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L253-L253

File: contracts/curve/TricryptoNativeStrategy.sol

/// @audit safeTransfer() prior to emission of AmountWithdrawn()
244:         emit AmountWithdrawn(to, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L244-L244

File: contracts/lido/LidoEthStrategy.sol

/// @audit safeTransfer() prior to emission of AmountWithdrawn()
166:         emit AmountWithdrawn(to, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L166-L166

File: contracts/stargate/StargateStrategy.sol

/// @audit safeTransfer() prior to emission of AmountWithdrawn()
268:         emit AmountWithdrawn(to, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L268-L268

File: contracts/yearn/YearnStrategy.sol

/// @audit safeTransfer() prior to emission of AmountWithdrawn()
149:         emit AmountWithdrawn(to, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L149-L149

File: contracts/YieldBox.sol

/// @audit safeTransferFrom() prior to emission of Deposited()
157:         emit Deposited(msg.sender, from, to, assetId, amount, share, amountOut, shareOut, false);

/// @audit safeTransfer() prior to emission of Deposited()
212:         emit Deposited(msg.sender, msg.sender, to, assetId, amount, share, amountOut, shareOut, false);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L157-L157

[N‑14] Function names should use lowerCamelCase

According to the Solidity style guide function names should be in mixedCase (lowerCamelCase)

There are 17 instances of this issue:

File: contracts/markets/Market.sol

305      function computeTVLInfo(
306          address user,
307          uint256 _exchangeRate
308      )
309          public
310          view
311          returns (uint256 amountToSolvency, uint256 minTVL, uint256 maxTVL)
312:     {

428      function _computeMaxAndMinLTVInAsset(
429          uint256 collateralShare,
430          uint256 _exchangeRate
431:     ) internal view returns (uint256 min, uint256 max) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L305-L312

File: contracts/TapiocaWrapper.sol

75:      function tapiocaOFTLength() external view returns (uint256) {

85:      function lastTOFT() external view returns (ITapiocaOFT) {

115      function executeTOFT(
116          address _toft,
117          bytes calldata _bytecode,
118          bool _revertOnFailure
119:     ) external payable onlyOwner returns (bool success, bytes memory result) {

154      function createTOFT(
155          address _erc20,
156          bytes calldata _bytecode,
157          bytes32 _salt,
158          bool _linked
159:     ) external onlyOwner {

183      function _createTOFT(
184          address _erc20,
185          bytes calldata _bytecode,
186          bytes32 _salt,
187          bool _linked
188:     ) private returns (address) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L75-L75

File: contracts/option-airdrop/AirdropBroker.sol

141      function getOTCDealDetails(
142          uint256 _aoTAPTokenID,
143          ERC20 _paymentToken,
144          uint256 _tapAmount
145      )
146          external
147          view
148          returns (
149              uint256 eligibleTapAmount,
150              uint256 paymentTokenAmount,
151              uint256 tapAmount
152          )
153:     {

297:     function aoTAPBrokerClaim() external {

487      function _processOTCDeal(
488          ERC20 _paymentToken,
489          PaymentTokenOracle memory _paymentTokenOracle,
490          uint256 tapAmount,
491          uint256 discount
492:     ) internal {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L141-L153

File: contracts/options/TapiocaOptionBroker.sol

145      function getOTCDealDetails(
146          uint256 _oTAPTokenID,
147          ERC20 _paymentToken,
148          uint256 _tapAmount
149      )
150          external
151          view
152          returns (
153              uint256 eligibleTapAmount,
154              uint256 paymentTokenAmount,
155              uint256 tapAmount
156          )
157:     {

435:     function oTAPBrokerClaim() external {

508      function _processOTCDeal(
509          ERC20 _paymentToken,
510          PaymentTokenOracle memory _paymentTokenOracle,
511          uint256 tapAmount,
512          uint256 discount
513:     ) internal {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L145-L157

File: contracts/options/TapiocaOptionLiquidityProvision.sol

259      function setSGLPoolWEight(
260          IERC20 singularity,
261          uint256 weight
262:     ) external onlyOwner updateTotalSGLPoolWeights {

336:     function _computeSGLPoolWeights() internal view returns (uint256) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L259-L262

File: contracts/YieldBox.sol

168      function depositNFTAsset(
169          uint256 assetId,
170          address from,
171          address to
172:     ) public allowed(from, assetId) returns (uint256 amountOut, uint256 shareOut) {

196:     function depositETHAsset(uint256 assetId, address to, uint256 amount) public payable returns (uint256 amountOut, uint256 shareOut) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L168-L172

[N‑15] Consider bounding input array length

The functions below take in an unbounded array, and make function calls for entries in the array. While the function will revert if it eventually runs out of gas, it may be a nicer user experience to require() that the length of the array is below some reasonable maximum, so that the user doesn't have to use up a full transaction's gas only to see that the transaction reverts.

There are 29 instances of this issue:

see instances
File: contracts/Penrose.sol

437          for (uint256 i = 0; i < len; ) {
438              require(
439                  isSingularityMasterContractRegistered[
440                      masterContractOf[mc[i]]
441                  ] || isBigBangMasterContractRegistered[masterContractOf[mc[i]]],
442                  "Penrose: MC not registered"
443              );
444              (success[i], result[i]) = mc[i].call(data[i]);
445              if (forceSuccess) {
446                  require(success[i], _getRevertMsg(result[i]));
447              }
448              ++i;
449:         }

492              for (uint256 i = 0; i < length; ) {
493                  _depositFeesToYieldBox(markets_[i], swappers_[i], swapData_[i]);
494                  ++i;
495:             }

550              for (uint256 i = 0; i < _masterContractLength; ) {
551                  marketsLength += clonesOfCount(array[i].location);
552  
553                  ++i;
554:             }

564              for (uint256 i = 0; i < _masterContractLength; ) {
565                  address mcLocation = array[i].location;
566                  clonesOfLength = clonesOfCount(mcLocation);
567  
568                  // Loop through clones of the current MC.
569                  for (uint256 j = 0; j < clonesOfLength; ) {
570                      markets[marketIndex] = clonesOf[mcLocation][j];
571                      ++marketIndex;
572                      ++j;
573                  }
574                  ++i;
575:             }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L437-L449

File: contracts/markets/bigBang/BigBang.sol

215          for (uint256 i = 0; i < calls.length; i++) {
216              (bool success, bytes memory result) = address(this).delegatecall(
217                  calls[i]
218              );
219              require(success || !revertOnFail, _getRevertMsg(result));
220              successes[i] = success;
221              results[i] = _getRevertMsg(result);
222:         }

666          for (uint256 i = 0; i < users.length; i++) {
667              address user = users[i];
668              if (!_isSolvent(user, _exchangeRate)) {
669                  liquidatedCount++;
670                  _liquidateUser(
671                      user,
672                      maxBorrowParts[i],
673                      swapper,
674                      _exchangeRate,
675                      swapData
676                  );
677              }
678:         }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L215-L222

File: contracts/markets/singularity/SGLLiquidation.sol

107          for (uint256 i = 0; i < users.length; i++) {
108              address user = users[i];
109              if (!_isSolvent(user, _exchangeRate)) {
110                  uint256 borrowAmount = _computeAssetAmountToSolvency(
111                      user,
112                      _exchangeRate
113                  );
114  
115                  if (borrowAmount == 0) {
116                      continue;
117                  }
118  
119                  uint256 borrowPart;
120                  {
121                      uint256 availableBorrowPart = userBorrowPart[user];
122                      borrowPart = _totalBorrow.toBase(borrowAmount, false);
123                      userBorrowPart[user] = availableBorrowPart - borrowPart;
124                  }
125                  uint256 amountWithBonus = borrowAmount +
126                      (borrowAmount * liquidationMultiplier) /
127                      FEE_PRECISION;
128                  uint256 collateralShare = yieldBox.toShare(
129                      collateralId,
130                      (amountWithBonus * _exchangeRate) / EXCHANGE_RATE_PRECISION,
131                      false
132                  );
133                  userCollateralShare[user] -= collateralShare;
134                  emit LogRemoveCollateral(
135                      user,
136                      address(liquidationQueue),
137                      collateralShare
138                  );
139                  emit LogRepay(
140                      address(liquidationQueue),
141                      user,
142                      borrowAmount,
143                      borrowPart
144                  );
145  
146                  // Keep totals
147                  allCollateralShare += collateralShare;
148                  allBorrowAmount += borrowAmount;
149                  allBorrowPart += borrowPart;
150              }
151:         }

384          for (uint256 i = 0; i < users.length; i++) {
385              address user = users[i];
386              if (!_isSolvent(user, _exchangeRate)) {
387                  liquidatedCount++;
388                  _liquidateUser(
389                      user,
390                      maxBorrowParts[i],
391                      swapper,
392                      _exchangeRate,
393                      swapData
394                  );
395              }
396:         }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L107-L151

File: contracts/markets/singularity/Singularity.sol

187          for (uint256 i = 0; i < calls.length; i++) {
188              (bool success, bytes memory result) = address(this).delegatecall(
189                  calls[i]
190              );
191              require(success || !revertOnFail, _getRevertMsg(result));
192              successes[i] = success;
193              results[i] = _getRevertMsg(result);
194:         }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L187-L194

File: contracts/usd0/modules/USDOLeverageModule.sol

255          for (uint256 i = 0; i < approvals.length; ) {
256              if (approvals[i].permitBorrow) {
257                  try
258                      IPermitBorrow(approvals[i].target).permitBorrow(
259                          approvals[i].owner,
260                          approvals[i].spender,
261                          approvals[i].value,
262                          approvals[i].deadline,
263                          approvals[i].v,
264                          approvals[i].r,
265                          approvals[i].s
266                      )
267                  {} catch Error(string memory reason) {
268                      if (!approvals[i].allowFailure) {
269                          revert(reason);
270                      }
271                  }
272              } else if (approvals[i].permitAll) {
273                  try
274                      IPermitAll(approvals[i].target).permitAll(
275                          approvals[i].owner,
276                          approvals[i].spender,
277                          approvals[i].deadline,
278                          approvals[i].v,
279                          approvals[i].r,
280                          approvals[i].s
281                      )
282                  {} catch Error(string memory reason) {
283                      if (!approvals[i].allowFailure) {
284                          revert(reason);
285                      }
286                  }
287              } else {
288                  try
289                      IERC20Permit(approvals[i].target).permit(
290                          approvals[i].owner,
291                          approvals[i].spender,
292                          approvals[i].value,
293                          approvals[i].deadline,
294                          approvals[i].v,
295                          approvals[i].r,
296                          approvals[i].s
297                      )
298                  {} catch Error(string memory reason) {
299                      if (!approvals[i].allowFailure) {
300                          revert(reason);
301                      }
302                  }
303              }
304  
305              unchecked {
306                  ++i;
307              }
308:         }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L255-L308

File: contracts/usd0/modules/USDOMarketModule.sol

244          for (uint256 i = 0; i < approvals.length; ) {
245              if (approvals[i].permitBorrow) {
246                  try
247                      IPermitBorrow(approvals[i].target).permitBorrow(
248                          approvals[i].owner,
249                          approvals[i].spender,
250                          approvals[i].value,
251                          approvals[i].deadline,
252                          approvals[i].v,
253                          approvals[i].r,
254                          approvals[i].s
255                      )
256                  {} catch Error(string memory reason) {
257                      if (!approvals[i].allowFailure) {
258                          revert(reason);
259                      }
260                  }
261              } else if (approvals[i].permitAll) {
262                  try
263                      IPermitAll(approvals[i].target).permitAll(
264                          approvals[i].owner,
265                          approvals[i].spender,
266                          approvals[i].deadline,
267                          approvals[i].v,
268                          approvals[i].r,
269                          approvals[i].s
270                      )
271                  {} catch Error(string memory reason) {
272                      if (!approvals[i].allowFailure) {
273                          revert(reason);
274                      }
275                  }
276              } else {
277                  try
278                      IERC20Permit(approvals[i].target).permit(
279                          approvals[i].owner,
280                          approvals[i].spender,
281                          approvals[i].value,
282                          approvals[i].deadline,
283                          approvals[i].v,
284                          approvals[i].r,
285                          approvals[i].s
286                      )
287                  {} catch Error(string memory reason) {
288                      if (!approvals[i].allowFailure) {
289                          revert(reason);
290                      }
291                  }
292              }
293  
294              unchecked {
295                  ++i;
296              }
297:         }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol#L244-L297

File: contracts/usd0/modules/USDOOptionsModule.sol

245          for (uint256 i = 0; i < approvals.length; ) {
246              if (approvals[i].permitBorrow) {
247                  try
248                      IPermitBorrow(approvals[i].target).permitBorrow(
249                          approvals[i].owner,
250                          approvals[i].spender,
251                          approvals[i].value,
252                          approvals[i].deadline,
253                          approvals[i].v,
254                          approvals[i].r,
255                          approvals[i].s
256                      )
257                  {} catch Error(string memory reason) {
258                      if (!approvals[i].allowFailure) {
259                          revert(reason);
260                      }
261                  }
262              } else if (approvals[i].permitAll) {
263                  try
264                      IPermitAll(approvals[i].target).permitAll(
265                          approvals[i].owner,
266                          approvals[i].spender,
267                          approvals[i].deadline,
268                          approvals[i].v,
269                          approvals[i].r,
270                          approvals[i].s
271                      )
272                  {} catch Error(string memory reason) {
273                      if (!approvals[i].allowFailure) {
274                          revert(reason);
275                      }
276                  }
277              } else {
278                  try
279                      IERC20Permit(approvals[i].target).permit(
280                          approvals[i].owner,
281                          approvals[i].spender,
282                          approvals[i].value,
283                          approvals[i].deadline,
284                          approvals[i].v,
285                          approvals[i].r,
286                          approvals[i].s
287                      )
288                  {} catch Error(string memory reason) {
289                      if (!approvals[i].allowFailure) {
290                          revert(reason);
291                      }
292                  }
293              }
294  
295              unchecked {
296                  ++i;
297              }
298:         }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol#L245-L298

File: contracts/TapiocaWrapper.sol

140          for (uint256 i = 0; i < _call.length; i++) {
141              (success, results[i]) = payable(_call[i].toft).call{
142                  value: msg.value
143              }(_call[i].bytecode);
144              if (_call[i].revertOnFailure && !success) {
145                  revert TapiocaWrapper__TOFTExecutionFailed(results[i]);
146              }
147:         }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L140-L147

File: contracts/tOFT/modules/BaseTOFTLeverageModule.sol

285          for (uint256 i = 0; i < approvals.length; ) {
286              if (approvals[i].permitBorrow) {
287                  try
288                      IPermitBorrow(approvals[i].target).permitBorrow(
289                          approvals[i].owner,
290                          approvals[i].spender,
291                          approvals[i].value,
292                          approvals[i].deadline,
293                          approvals[i].v,
294                          approvals[i].r,
295                          approvals[i].s
296                      )
297                  {} catch Error(string memory reason) {
298                      if (!approvals[i].allowFailure) {
299                          revert(reason);
300                      }
301                  }
302              } else if (approvals[i].permitAll) {
303                  try
304                      IPermitAll(approvals[i].target).permitAll(
305                          approvals[i].owner,
306                          approvals[i].spender,
307                          approvals[i].deadline,
308                          approvals[i].v,
309                          approvals[i].r,
310                          approvals[i].s
311                      )
312                  {} catch Error(string memory reason) {
313                      if (!approvals[i].allowFailure) {
314                          revert(reason);
315                      }
316                  }
317              } else {
318                  try
319                      IERC20Permit(approvals[i].target).permit(
320                          approvals[i].owner,
321                          approvals[i].spender,
322                          approvals[i].value,
323                          approvals[i].deadline,
324                          approvals[i].v,
325                          approvals[i].r,
326                          approvals[i].s
327                      )
328                  {} catch Error(string memory reason) {
329                      if (!approvals[i].allowFailure) {
330                          revert(reason);
331                      }
332                  }
333              }
334  
335              unchecked {
336                  ++i;
337              }
338:         }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L285-L338

File: contracts/tOFT/modules/BaseTOFTMarketModule.sol

261          for (uint256 i = 0; i < approvals.length; ) {
262              if (approvals[i].permitBorrow) {
263                  try
264                      IPermitBorrow(approvals[i].target).permitBorrow(
265                          approvals[i].owner,
266                          approvals[i].spender,
267                          approvals[i].value,
268                          approvals[i].deadline,
269                          approvals[i].v,
270                          approvals[i].r,
271                          approvals[i].s
272                      )
273                  {} catch Error(string memory reason) {
274                      if (!approvals[i].allowFailure) {
275                          revert(reason);
276                      }
277                  }
278              } else if (approvals[i].permitAll) {
279                  try
280                      IPermitAll(approvals[i].target).permitAll(
281                          approvals[i].owner,
282                          approvals[i].spender,
283                          approvals[i].deadline,
284                          approvals[i].v,
285                          approvals[i].r,
286                          approvals[i].s
287                      )
288                  {} catch Error(string memory reason) {
289                      if (!approvals[i].allowFailure) {
290                          revert(reason);
291                      }
292                  }
293              } else {
294                  try
295                      IERC20Permit(approvals[i].target).permit(
296                          approvals[i].owner,
297                          approvals[i].spender,
298                          approvals[i].value,
299                          approvals[i].deadline,
300                          approvals[i].v,
301                          approvals[i].r,
302                          approvals[i].s
303                      )
304                  {} catch Error(string memory reason) {
305                      if (!approvals[i].allowFailure) {
306                          revert(reason);
307                      }
308                  }
309              }
310  
311              unchecked {
312                  ++i;
313              }
314:         }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L261-L314

File: contracts/tOFT/modules/BaseTOFTOptionsModule.sol

260          for (uint256 i = 0; i < approvals.length; ) {
261              if (approvals[i].permitBorrow) {
262                  try
263                      IPermitBorrow(approvals[i].target).permitBorrow(
264                          approvals[i].owner,
265                          approvals[i].spender,
266                          approvals[i].value,
267                          approvals[i].deadline,
268                          approvals[i].v,
269                          approvals[i].r,
270                          approvals[i].s
271                      )
272                  {} catch Error(string memory reason) {
273                      if (!approvals[i].allowFailure) {
274                          revert(reason);
275                      }
276                  }
277              } else if (approvals[i].permitAll) {
278                  try
279                      IPermitAll(approvals[i].target).permitAll(
280                          approvals[i].owner,
281                          approvals[i].spender,
282                          approvals[i].deadline,
283                          approvals[i].v,
284                          approvals[i].r,
285                          approvals[i].s
286                      )
287                  {} catch Error(string memory reason) {
288                      if (!approvals[i].allowFailure) {
289                          revert(reason);
290                      }
291                  }
292              } else {
293                  try
294                      IERC20Permit(approvals[i].target).permit(
295                          approvals[i].owner,
296                          approvals[i].spender,
297                          approvals[i].value,
298                          approvals[i].deadline,
299                          approvals[i].v,
300                          approvals[i].r,
301                          approvals[i].s
302                      )
303                  {} catch Error(string memory reason) {
304                      if (!approvals[i].allowFailure) {
305                          revert(reason);
306                      }
307                  }
308              }
309  
310              unchecked {
311                  ++i;
312              }
313:         }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol#L260-L313

File: contracts/governance/twTAP.sol

507              for (uint256 i = 0; i < len; ) {
508                  uint256 claimableIndex = rewardTokenIndex[_rewardTokens[i]];
509                  uint256 amount = amounts[i];
510  
511                  if (amount > 0) {
512                      // Math is safe: `amount` calculated safely in `claimable()`
513                      claimed[_tokenId][claimableIndex] += amount;
514                      rewardTokens[claimableIndex].safeTransfer(_to, amount);
515                  }
516                  ++i;
517:             }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L507-L517

File: contracts/option-airdrop/AirdropBroker.sol

375              for (uint256 i = 0; i < len; ++i) {
376                  ERC20 paymentToken = ERC20(_paymentTokens[i]);
377                  paymentToken.transfer(
378                      paymentTokenBeneficiary,
379                      paymentToken.balanceOf(address(this))
380                  );
381:             }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L375-L381

File: contracts/options/TapiocaOptionBroker.sol

489              for (uint256 i = 0; i < len; ++i) {
490                  ERC20 paymentToken = ERC20(_paymentTokens[i]);
491                  paymentToken.transfer(
492                      paymentTokenBeneficiary,
493                      paymentToken.balanceOf(address(this))
494                  );
495:             }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L489-L495

File: contracts/tokens/BaseTapOFT.sol

333          for (uint256 i = 0; i < approvals.length; ) {
334              try
335                  IERC20Permit(approvals[i].target).permit(
336                      approvals[i].owner,
337                      approvals[i].spender,
338                      approvals[i].value,
339                      approvals[i].deadline,
340                      approvals[i].v,
341                      approvals[i].r,
342                      approvals[i].s
343                  )
344              {} catch Error(string memory reason) {
345                  if (!approvals[i].allowFailure) {
346                      revert(reason);
347                  }
348              }
349  
350              unchecked {
351                  ++i;
352              }
353:         }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L333-L353

File: contracts/Magnetar/MagnetarV2.sol

202          for (uint256 i = 0; i < length; i++) {
203              Call calldata _action = calls[i];
204              if (!_action.allowFailure) {
205                  require(
206                      _action.call.length > 0,
207                      string.concat(
208                          "MagnetarV2: Missing call for action with index",
209                          string(abi.encode(i))
210                      )
211                  );
212              }
213  
214              unchecked {
215                  valAccumulator += _action.value;
216              }
217  
218              if (_action.id == PERMIT_ALL) {
219                  _permit(
220                      _action.target,
221                      _action.call,
222                      true,
223                      _action.allowFailure
224                  );
225              } else if (_action.id == PERMIT) {
226                  _permit(
227                      _action.target,
228                      _action.call,
229                      false,
230                      _action.allowFailure
231                  );
232              } else if (_action.id == TOFT_WRAP) {
233                  WrapData memory data = abi.decode(_action.call[4:], (WrapData));
234                  _checkSender(data.from);
235                  if (_action.value > 0) {
236                      unchecked {
237                          valAccumulator += _action.value;
238                      }
239                      ITapiocaOFT(_action.target).wrapNative{
240                          value: _action.value
241                      }(data.to);
242                  } else {
243                      ITapiocaOFT(_action.target).wrap(
244                          msg.sender,
245                          data.to,
246                          data.amount
247                      );
248                  }
249              } else if (_action.id == TOFT_SEND_FROM) {
250                  (
251                      address from,
252                      uint16 dstChainId,
253                      bytes32 to,
254                      uint256 amount,
255                      ISendFrom.LzCallParams memory lzCallParams
256                  ) = abi.decode(
257                          _action.call[4:],
258                          (
259                              address,
260                              uint16,
261                              bytes32,
262                              uint256,
263                              (ISendFrom.LzCallParams)
264                          )
265                      );
266                  _checkSender(from);
267  
268                  ISendFrom(_action.target).sendFrom{value: _action.value}(
269                      msg.sender,
270                      dstChainId,
271                      to,
272                      amount,
273                      lzCallParams
274                  );
275              } else if (_action.id == YB_DEPOSIT_ASSET) {
276                  YieldBoxDepositData memory data = abi.decode(
277                      _action.call[4:],
278                      (YieldBoxDepositData)
279                  );
280                  _checkSender(data.from);
281  
282                  (uint256 amountOut, uint256 shareOut) = IYieldBoxBase(
283                      _action.target
284                  ).depositAsset(
285                          data.assetId,
286                          msg.sender,
287                          data.to,
288                          data.amount,
289                          data.share
290                      );
291                  returnData[i] = Result({
292                      success: true,
293                      returnData: abi.encode(amountOut, shareOut)
294                  });
295              } else if (_action.id == MARKET_ADD_COLLATERAL) {
296                  SGLAddCollateralData memory data = abi.decode(
297                      _action.call[4:],
298                      (SGLAddCollateralData)
299                  );
300                  _checkSender(data.from);
301  
302                  IMarket(_action.target).addCollateral(
303                      msg.sender,
304                      data.to,
305                      data.skim,
306                      data.amount,
307                      data.share
308                  );
309              } else if (_action.id == MARKET_BORROW) {
310                  SGLBorrowData memory data = abi.decode(
311                      _action.call[4:],
312                      (SGLBorrowData)
313                  );
314                  _checkSender(data.from);
315  
316                  (uint256 part, uint256 share) = IMarket(_action.target).borrow(
317                      msg.sender,
318                      data.to,
319                      data.amount
320                  );
321                  returnData[i] = Result({
322                      success: true,
323                      returnData: abi.encode(part, share)
324                  });
325              } else if (_action.id == YB_WITHDRAW_TO) {
326                  (
327                      address yieldBox,
328                      address from,
329                      uint256 assetId,
330                      uint16 dstChainId,
331                      bytes32 receiver,
332                      uint256 amount,
333                      uint256 share,
334                      bytes memory adapterParams,
335                      address payable refundAddress
336                  ) = abi.decode(
337                          _action.call[4:],
338                          (
339                              address,
340                              address,
341                              uint256,
342                              uint16,
343                              bytes32,
344                              uint256,
345                              uint256,
346                              bytes,
347                              address
348                          )
349                      );
350  
351                  _executeModule(
352                      Module.Market,
353                      abi.encodeWithSelector(
354                          MagnetarMarketModule.withdrawToChain.selector,
355                          yieldBox,
356                          from,
357                          assetId,
358                          dstChainId,
359                          receiver,
360                          amount,
361                          share,
362                          adapterParams,
363                          refundAddress,
364                          _action.value
365                      )
366                  );
367              } else if (_action.id == MARKET_LEND) {
368                  SGLLendData memory data = abi.decode(
369                      _action.call[4:],
370                      (SGLLendData)
371                  );
372                  _checkSender(data.from);
373  
374                  uint256 fraction = IMarket(_action.target).addAsset(
375                      msg.sender,
376                      data.to,
377                      data.skim,
378                      data.share
379                  );
380                  returnData[i] = Result({
381                      success: true,
382                      returnData: abi.encode(fraction)
383                  });
384              } else if (_action.id == MARKET_REPAY) {
385                  SGLRepayData memory data = abi.decode(
386                      _action.call[4:],
387                      (SGLRepayData)
388                  );
389                  _checkSender(data.from);
390  
391                  uint256 amount = IMarket(_action.target).repay(
392                      msg.sender,
393                      data.to,
394                      data.skim,
395                      data.part
396                  );
397                  returnData[i] = Result({
398                      success: true,
399                      returnData: abi.encode(amount)
400                  });
401              } else if (_action.id == TOFT_SEND_AND_BORROW) {
402                  (
403                      address from,
404                      address to,
405                      uint16 lzDstChainId,
406                      bytes memory airdropAdapterParams,
407                      ITapiocaOFT.IBorrowParams memory borrowParams,
408                      ICommonData.IWithdrawParams memory withdrawParams,
409                      ICommonData.ISendOptions memory options,
410                      ICommonData.IApproval[] memory approvals
411                  ) = abi.decode(
412                          _action.call[4:],
413                          (
414                              address,
415                              address,
416                              uint16,
417                              bytes,
418                              ITapiocaOFT.IBorrowParams,
419                              ICommonData.IWithdrawParams,
420                              ICommonData.ISendOptions,
421                              ICommonData.IApproval[]
422                          )
423                      );
424                  _checkSender(from);
425  
426                  ITapiocaOFT(_action.target).sendToYBAndBorrow{
427                      value: _action.value
428                  }(
429                      msg.sender,
430                      to,
431                      lzDstChainId,
432                      airdropAdapterParams,
433                      borrowParams,
434                      withdrawParams,
435                      options,
436                      approvals
437                  );
438              } else if (_action.id == TOFT_SEND_AND_LEND) {
439                  (
440                      address from,
441                      address to,
442                      uint16 dstChainId,
443                      address zroPaymentAddress,
444                      IUSDOBase.ILendOrRepayParams memory lendParams,
445                      ICommonData.IApproval[] memory approvals,
446                      ICommonData.IWithdrawParams memory withdrawParams,
447                      bytes memory adapterParams
448                  ) = abi.decode(
449                          _action.call[4:],
450                          (
451                              address,
452                              address,
453                              uint16,
454                              address,
455                              (IUSDOBase.ILendOrRepayParams),
456                              (ICommonData.IApproval[]),
457                              (ICommonData.IWithdrawParams),
458                              bytes
459                          )
460                      );
461                  _checkSender(from);
462  
463                  IUSDOBase(_action.target).sendAndLendOrRepay{
464                      value: _action.value
465                  }(
466                      msg.sender,
467                      to,
468                      dstChainId,
469                      zroPaymentAddress,
470                      lendParams,
471                      approvals,
472                      withdrawParams,
473                      adapterParams
474                  );
475              } else if (_action.id == TOFT_DEPOSIT_TO_STRATEGY) {
476                  TOFTSendToStrategyData memory data = abi.decode(
477                      _action.call[4:],
478                      (TOFTSendToStrategyData)
479                  );
480                  _checkSender(data.from);
481  
482                  ITapiocaOFT(_action.target).sendToStrategy{
483                      value: _action.value
484                  }(
485                      msg.sender,
486                      data.to,
487                      data.amount,
488                      data.share,
489                      data.assetId,
490                      data.lzDstChainId,
491                      data.options
492                  );
493              } else if (_action.id == TOFT_RETRIEVE_FROM_STRATEGY) {
494                  (
495                      address from,
496                      uint256 amount,
497                      uint256 share,
498                      uint256 assetId,
499                      uint16 lzDstChainId,
500                      address zroPaymentAddress,
501                      bytes memory airdropAdapterParam
502                  ) = abi.decode(
503                          _action.call[4:],
504                          (
505                              address,
506                              uint256,
507                              uint256,
508                              uint256,
509                              uint16,
510                              address,
511                              bytes
512                          )
513                      );
514  
515                  _checkSender(from);
516  
517                  ITapiocaOFT(_action.target).retrieveFromStrategy{
518                      value: _action.value
519                  }(
520                      msg.sender,
521                      amount,
522                      share,
523                      assetId,
524                      lzDstChainId,
525                      zroPaymentAddress,
526                      airdropAdapterParam
527                  );
528              } else if (_action.id == MARKET_YBDEPOSIT_AND_LEND) {
529                  HelperLendData memory data = abi.decode(
530                      _action.call[4:],
531                      (HelperLendData)
532                  );
533  
534                  _executeModule(
535                      Module.Market,
536                      abi.encodeWithSelector(
537                          MagnetarMarketModule.mintFromBBAndLendOnSGL.selector,
538                          data.user,
539                          data.lendAmount,
540                          data.mintData,
541                          data.depositData,
542                          data.lockData,
543                          data.participateData,
544                          data.externalContracts
545                      )
546                  );
547              } else if (_action.id == MARKET_YBDEPOSIT_COLLATERAL_AND_BORROW) {
548                  (
549                      address market,
550                      address user,
551                      uint256 collateralAmount,
552                      uint256 borrowAmount,
553                      ,
554                      bool deposit,
555                      ICommonData.IWithdrawParams memory withdrawParams
556                  ) = abi.decode(
557                          _action.call[4:],
558                          (
559                              address,
560                              address,
561                              uint256,
562                              uint256,
563                              bool,
564                              bool,
565                              ICommonData.IWithdrawParams
566                          )
567                      );
568  
569                  _executeModule(
570                      Module.Market,
571                      abi.encodeWithSelector(
572                          MagnetarMarketModule
573                              .depositAddCollateralAndBorrowFromMarket
574                              .selector,
575                          market,
576                          user,
577                          collateralAmount,
578                          borrowAmount,
579                          false,
580                          deposit,
581                          withdrawParams
582                      )
583                  );
584              } else if (_action.id == MARKET_REMOVE_ASSET) {
585                  HelperMarketRemoveAndRepayAsset memory data = abi.decode(
586                      _action.call[4:],
587                      (HelperMarketRemoveAndRepayAsset)
588                  );
589  
590                  _executeModule(
591                      Module.Market,
592                      abi.encodeWithSelector(
593                          MagnetarMarketModule
594                              .exitPositionAndRemoveCollateral
595                              .selector,
596                          data.user,
597                          data.externalData,
598                          data.removeAndRepayData
599                      )
600                  );
601              } else if (_action.id == MARKET_DEPOSIT_REPAY_REMOVE_COLLATERAL) {
602                  HelperDepositRepayRemoveCollateral memory data = abi.decode(
603                      _action.call[4:],
604                      (HelperDepositRepayRemoveCollateral)
605                  );
606  
607                  _executeModule(
608                      Module.Market,
609                      abi.encodeWithSelector(
610                          MagnetarMarketModule
611                              .depositRepayAndRemoveCollateralFromMarket
612                              .selector,
613                          data.market,
614                          data.user,
615                          data.depositAmount,
616                          data.repayAmount,
617                          data.collateralAmount,
618                          data.extractFromSender,
619                          data.withdrawCollateralParams
620                      )
621                  );
622              } else if (_action.id == MARKET_BUY_COLLATERAL) {
623                  HelperBuyCollateral memory data = abi.decode(
624                      _action.call[4:],
625                      (HelperBuyCollateral)
626                  );
627  
628                  IMarket(data.market).buyCollateral(
629                      data.from,
630                      data.borrowAmount,
631                      data.supplyAmount,
632                      data.minAmountOut,
633                      address(data.swapper),
634                      data.dexData
635                  );
636              } else if (_action.id == MARKET_SELL_COLLATERAL) {
637                  HelperSellCollateral memory data = abi.decode(
638                      _action.call[4:],
639                      (HelperSellCollateral)
640                  );
641  
642                  IMarket(data.market).sellCollateral(
643                      data.from,
644                      data.share,
645                      data.minAmountOut,
646                      address(data.swapper),
647                      data.dexData
648                  );
649              } else if (_action.id == TAP_EXERCISE_OPTION) {
650                  HelperExerciseOption memory data = abi.decode(
651                      _action.call[4:],
652                      (HelperExerciseOption)
653                  );
654  
655                  ITapiocaOptionsBrokerCrossChain(_action.target).exerciseOption(
656                      data.optionsData,
657                      data.lzData,
658                      data.tapSendData,
659                      data.approvals
660                  );
661              } else if (_action.id == MARKET_MULTIHOP_BUY) {
662                  HelperMultiHopBuy memory data = abi.decode(
663                      _action.call[4:],
664                      (HelperMultiHopBuy)
665                  );
666  
667                  IUSDOBase(_action.target).initMultiHopBuy(
668                      data.from,
669                      data.collateralAmount,
670                      data.borrowAmount,
671                      data.swapData,
672                      data.lzData,
673                      data.externalData,
674                      data.airdropAdapterParams,
675                      data.approvals
676                  );
677              } else if (_action.id == MARKET_MULTIHOP_BUY) {
678                  HelperMultiHopBuy memory data = abi.decode(
679                      _action.call[4:],
680                      (HelperMultiHopBuy)
681                  );
682  
683                  IUSDOBase(_action.target).initMultiHopBuy(
684                      data.from,
685                      data.collateralAmount,
686                      data.borrowAmount,
687                      data.swapData,
688                      data.lzData,
689                      data.externalData,
690                      data.airdropAdapterParams,
691                      data.approvals
692                  );
693              } else if (_action.id == TOFT_REMOVE_AND_REPAY) {
694                  HelperTOFTRemoveAndRepayAsset memory data = abi.decode(
695                      _action.call[4:],
696                      (HelperTOFTRemoveAndRepayAsset)
697                  );
698  
699                  IUSDOBase(_action.target).removeAsset(
700                      data.from,
701                      data.to,
702                      data.lzDstChainId,
703                      data.zroPaymentAddress,
704                      data.adapterParams,
705                      data.externalData,
706                      data.removeAndRepayData,
707                      data.approvals
708                  );
709              } else {
710                  revert("MagnetarV2: action not valid");
711              }
712:         }

973          for (uint256 i = 0; i < len; i++) {
974              ISingularity sgl = markets[i];
975  
976              result[i].market = _commonInfo(who, IMarket(address(sgl)));
977  
978              (uint128 totalAssetElastic, uint128 totalAssetBase) = sgl //
979                  .totalAsset(); //
980              _totalAsset = Rebase(totalAssetElastic, totalAssetBase); //
981              result[i].totalAsset = _totalAsset; //
982              result[i].userAssetFraction = sgl.balanceOf(who); //
983  
984              (
985                  ISingularity.AccrueInfo memory _accrueInfo,
986                  uint256 _utilization
987              ) = sgl.getInterestDetails();
988  
989              result[i].accrueInfo = _accrueInfo;
990              result[i].utilization = _utilization;
991:         }

1004         for (uint256 i = 0; i < len; i++) {
1005             IBigBang bigBang = markets[i];
1006             result[i].market = _commonInfo(who, IMarket(address(bigBang)));
1007 
1008             (uint64 debtRate, uint64 lastAccrued) = bigBang.accrueInfo();
1009             _accrueInfo = IBigBang.AccrueInfo(debtRate, lastAccrued);
1010             result[i].accrueInfo = _accrueInfo;
1011             result[i].minDebtRate = bigBang.minDebtRate();
1012             result[i].maxDebtRate = bigBang.maxDebtRate();
1013             result[i].debtRateAgainstEthMarket = bigBang
1014                 .debtRateAgainstEthMarket();
1015             result[i].currentDebtRate = bigBang.getDebtRate();
1016 
1017             IPenrose penrose = IPenrose(bigBang.penrose());
1018             result[i].mainBBMarket = penrose.bigBangEthMarket();
1019             result[i].mainBBDebtRate = penrose.bigBangEthDebtRate();
1020:        }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L202-L712

File: contracts/NativeTokenFactory.sol

129          for (uint256 i = 0; i < len; i++) {
130              _mint(tos[i], tokenId, amounts[i]);
131:         }

141          for (uint256 i = 0; i < len; i++) {
142              _requireTransferAllowed(froms[i], isApprovedForAsset[froms[i]][msg.sender][tokenId]);
143              _burn(froms[i], tokenId, amounts[i]);
144:         }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L129-L131

File: contracts/YieldBox.sol

309          for (uint256 i = 0; i < len; i++) {
310              _requireTransferAllowed(from, isApprovedForAsset[from][msg.sender][assetIds_[i]]);
311:         }

320          for (uint256 i = 0; i < len; i++) {
321              uint256 id = ids[i];
322              _requireTransferAllowed(from, isApprovedForAsset[from][msg.sender][id]);
323              uint256 value = values[i];
324              balanceOf[from][id] -= value;
325              balanceOf[to][id] += value;
326:         }

339          for (uint256 i = 0; i < len; i++) {
340              require(tos[i] != address(0), "YieldBox: to not set"); // To avoid a bad UI from burning funds
341:         }

345          for (uint256 i = 0; i < len; i++) {
346              address to = tos[i];
347              uint256 share_ = shares[i];
348              balanceOf[to][assetId] += share_;
349              _totalShares += share_;
350              emit TransferSingle(msg.sender, from, to, assetId, share_);
351:         }

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L309-L311

[N‑16] Consider moving msg.sender checks to a common authorization modifier

There are 10 instances of this issue:

see instances
File: contracts/Penrose.sol

272:         require(msg.sender == conservator, "Penrose: unauthorized");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L272-L272

File: contracts/markets/Market.sol

246:         require(msg.sender == conservator, "Market: unauthorized");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L246-L246

File: contracts/usd0/BaseUSDO.sol

115:         require(msg.sender == conservator, "USDO: unauthorized");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDO.sol#L115-L115

File: contracts/governance/twTAP.sol

365:         require(msg.sender == address(tapOFT), "twTAP: only tapOFT");

390:         require(msg.sender == address(tapOFT), "twTAP: only tapOFT");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L365-L365

File: contracts/option-airdrop/AirdropBroker.sol

447:         require(PCNFT.ownerOf(_tokenID) == msg.sender, "adb: Not eligible");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L447-L447

File: contracts/tokens/TapOFT.sol

221:         require(msg.sender == minter, "unauthorized");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L221-L221

File: contracts/Magnetar/MagnetarV2Storage.sol

337:         require(_from == msg.sender, "MagnetarV2: operator not approved");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2Storage.sol#L337-L337

File: contracts/glp/GlpStrategy.sol

91:          require(msg.sender == address(gmxWethPool), "Not the pool");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L91-L91

File: contracts/NativeTokenFactory.sol

77:          require(msg.sender == _pendingOwner, "NTF: caller != pending owner");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L77-L77

[N‑17] Imports could be organized more systematically

The contract's interface should be imported first, followed by each of the interfaces it uses, followed by all other files. The examples below do not follow this layout.

There are 27 instances of this issue:

see instances
File: contracts/Penrose.sol

8:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/interfaces/IYieldBox.sol";

10:  import "tapioca-periph/contracts/interfaces/ISingularity.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L8-L8

File: contracts/markets/Market.sol

8:   import "tapioca-periph/contracts/interfaces/IOracle.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L8-L8

File: contracts/usd0/modules/USDOLeverageModule.sol

8:   import {IUSDOBase} from "tapioca-periph/contracts/interfaces/IUSDO.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L8-L8

File: contracts/usd0/modules/USDOOptionsModule.sol

8:   import "tapioca-periph/contracts/interfaces/IPermitBorrow.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol#L8-L8

File: contracts/tOFT/modules/BaseTOFTLeverageModule.sol

8:   import {IUSDOBase} from "tapioca-periph/contracts/interfaces/IUSDO.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L8-L8

File: contracts/tOFT/modules/BaseTOFTMarketModule.sol

8:   import {IUSDOBase} from "tapioca-periph/contracts/interfaces/IUSDO.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L8-L8

File: contracts/tOFT/modules/BaseTOFTOptionsModule.sol

8:   import "tapioca-periph/contracts/interfaces/IPermitBorrow.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol#L8-L8

File: contracts/tOFT/modules/BaseTOFTStrategyModule.sol

8:   import {IUSDOBase} from "tapioca-periph/contracts/interfaces/IUSDO.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol#L8-L8

File: contracts/option-airdrop/AirdropBroker.sol

7:   import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L7-L7

File: contracts/option-airdrop/aoTAP.sol

7:   import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L7-L7

File: contracts/options/TapiocaOptionLiquidityProvision.sol

9:   import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

12:  import "tapioca-sdk/dist/contracts/YieldBox/contracts/interfaces/IYieldBox.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L9-L9

File: contracts/options/oTAP.sol

6:   import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/oTAP.sol#L6-L6

File: contracts/tokens/BaseTapOFT.sol

7:   import "tapioca-periph/contracts/interfaces/ITapiocaOFT.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L7-L7

File: contracts/Magnetar/modules/MagnetarMarketModule.sol

10:  import "@openzeppelin/contracts/token/ERC721/IERC721.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L10-L10

File: contracts/Swapper/UniswapV3Swapper.sol

8:   import "@uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L8-L8

File: contracts/aave/AaveStrategy.sol

7:   import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L7-L7

File: contracts/balancer/BalancerStrategy.sol

7:   import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L7-L7

File: contracts/compound/CompoundStrategy.sol

7:   import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L7-L7

File: contracts/convex/ConvexTricryptoStrategy.sol

7:   import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L7-L7

File: contracts/curve/TricryptoLPStrategy.sol

7:   import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L7-L7

File: contracts/curve/TricryptoNativeStrategy.sol

7:   import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L7-L7

File: contracts/lido/LidoEthStrategy.sol

7:   import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L7-L7

File: contracts/stargate/StargateStrategy.sol

7:   import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L7-L7

File: contracts/yearn/YearnStrategy.sol

7:   import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L7-L7

File: contracts/YieldBox.sol

29:  import "@boringcrypto/boring-solidity/contracts/interfaces/IERC1155.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L29-L29

[N‑18] Overridden function has no body

Consider adding a NatSpec comment describing why the function doesn't need a body and or the purpose it serves

There are 4 instances of this issue:

File: contracts/markets/MarketERC20.sol

114:     function totalSupply() public view virtual override returns (uint256) {}

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L114-L114

File: contracts/markets/bigBang/BigBang.sol

426      function transfer(
427          address to,
428          uint256 amount
429:     ) public override returns (bool) {}

431      function transferFrom(
432          address from,
433          address to,
434          uint256 amount
435:     ) public override returns (bool) {}

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L426-L429

File: contracts/markets/singularity/SGLStorage.sol

195:     function _accrue() internal virtual override {}

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L195-L195

[N‑19] Use OpenZeppelin's or Solady's Ownable, rather than re-inventing the wheel

Both implementations have been optimized and are usage-hardened, so writing your own is unnecessary

There are 20 instances of this issue:

see instances
File: contracts/Penrose.sol

4:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L4-L4

File: contracts/markets/Market.sol

4:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L4-L4

File: contracts/markets/bigBang/BigBang.sol

4:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L4-L4

File: contracts/markets/singularity/SGLStorage.sol

4:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L4-L4

File: contracts/Vesting.sol

6:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L6-L6

File: contracts/option-airdrop/AirdropBroker.sol

5:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L5-L5

File: contracts/option-airdrop/aoTAP.sol

5:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L5-L5

File: contracts/options/TapiocaOptionBroker.sol

4:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L4-L4

File: contracts/options/TapiocaOptionLiquidityProvision.sol

6:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L6-L6

File: contracts/tokens/LTap.sol

4:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L4-L4

File: contracts/aave/AaveStrategy.sol

6:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L6-L6

File: contracts/balancer/BalancerStrategy.sol

6:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L6-L6

File: contracts/compound/CompoundStrategy.sol

6:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L6-L6

File: contracts/convex/ConvexTricryptoStrategy.sol

6:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L6-L6

File: contracts/curve/TricryptoLPStrategy.sol

6:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L6-L6

File: contracts/curve/TricryptoNativeStrategy.sol

6:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L6-L6

File: contracts/glp/GlpStrategy.sol

7:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L7-L7

File: contracts/lido/LidoEthStrategy.sol

6:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L6-L6

File: contracts/stargate/StargateStrategy.sol

6:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L6-L6

File: contracts/yearn/YearnStrategy.sol

6:   import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L6-L6

[N‑20] Array is push()ed but not pop()ed

Array entries are added but are never removed. Consider whether this should be the case, or whether there should be a maximum, or whether old entries should be removed. Cases where there are specific potential problems will be flagged separately under a different issue.

There are 5 instances of this issue:

File: contracts/Penrose.sol

329:         singularityMasterContracts.push(mc);

351:         bigbangMasterContracts.push(mc);

386:         clonesOf[mc].push(_contract);

419:         clonesOf[mc].push(_contract);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L329-L329

File: contracts/options/TapiocaOptionLiquidityProvision.sol

290:         singularities.push(assetID);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L290-L290

[N‑21] Long functions should be refactored into multiple, smaller, functions

There are 7 instances of this issue:

File: contracts/markets/Market.sol

158      function setMarketConfig(
159          uint256 _borrowOpeningFee,
160          IOracle _oracle,
161          bytes calldata _oracleData,
162          address _conservator,
163          uint256 _callerFee,
164          uint256 _protocolFee,
165          uint256 _liquidationBonusAmount,
166          uint256 _minLiquidatorReward,
167          uint256 _maxLiquidatorReward,
168          uint256 _totalBorrowCap,
169          uint256 _collateralizationRate
170:     ) external onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L158-L170

File: contracts/markets/singularity/SGLCommon.sol

35       function _getInterestRate()
36           internal
37           view
38           returns (
39               ISingularity.AccrueInfo memory _accrueInfo,
40               Rebase memory _totalBorrow,
41               Rebase memory _totalAsset,
42               uint256 extraAmount,
43               uint256 feeFraction,
44               uint256 utilization,
45               bool logStartingInterest
46           )
47:      {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol#L35-L47

File: contracts/markets/singularity/SGLLiquidation.sol

97       function _orderBookLiquidation(
98           address[] calldata users,
99           uint256 _exchangeRate,
100          bytes memory swapData
101:     ) private {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L97-L101

File: contracts/markets/singularity/Singularity.sol

62:      function init(bytes calldata data) external onlyOnce {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L62-L62

File: contracts/Magnetar/MagnetarV2.sol

194      function burst(
195          Call[] calldata calls
196:     ) external payable returns (Result[] memory returnData) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L194-L196

File: contracts/Magnetar/modules/MagnetarMarketModule.sol

292      function _mintFromBBAndLendOnSGL(
293          address user,
294          uint256 lendAmount,
295          IUSDOBase.IMintData calldata mintData,
296          ICommonData.IDepositData calldata depositData,
297          ITapiocaOptionLiquidityProvision.IOptionsLockData calldata lockData,
298          ITapiocaOptionsBroker.IOptionsParticipateData calldata participateData,
299          ICommonData.ICommonExternalContracts calldata externalContracts
300:     ) private {

495      function _exitPositionAndRemoveCollateral(
496          address user,
497          ICommonData.ICommonExternalContracts calldata externalData,
498          IUSDOBase.IRemoveAndRepay calldata removeAndRepayData
499:     ) private {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L292-L300

[N‑22] Mixed usage of int/uint with int256/uint256

int256/uint256 are the preferred type names (they're what are used for function signatures), so they should be used consistently

There are 7 instances of this issue:

File: contracts/markets/MarketERC20.sol

75:      function _allowedLend(address from, uint share) internal {

84:      function _allowedBorrow(address from, uint share) internal {

94:      modifier allowedLend(address from, uint share) virtual {

99:      modifier allowedBorrow(address from, uint share) virtual {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L75-L75

File: contracts/governance/twTAP.sol

156:         uint _tokenId

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L156-L156

File: contracts/tokens/BaseTapOFT.sol

129:         (, , address to, uint256 amount, uint duration) = abi.decode(

228:             for (uint i = 0; i < len; ) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L129-L129

[N‑23] Unsafe conversion from unsigned to signed values

Solidity follows two's complement rules for its integers, meaning that the most significant bit for signed integers is used to denote the sign, and converting between the two requires inverting all of the bits and adding one. Because of this, casting an unsigned integer to a signed one may result in a change of the sign and or magnitude of the value. For example, int8(type(uint8).max) is not equal to type(int8).max, but is equal to -1. type(uint8).max in binary is 11111111, which if cast to a signed value, means the first binary 1 indicates a negative value, and the binary 1s, invert to all zeroes, and when one is added, it becomes one, but negative, and therefore the decimal value of binary 11111111 is -1.

There are 10 instances of this issue:

File: tapioca-bar-audit/contracts/markets/Market.sol

/// @audit uint256 minLiquidatorReward -> int256
/// @audit uint256 maxLiquidatorReward -> int256
456:          int256 diff = int256(minLiquidatorReward) - int256(maxLiquidatorReward);

/// @audit uint256 rewardPercentage -> int256
457:          int256 reward = (diff * int256(rewardPercentage)) /

/// @audit uint256 FEE_PRECISION -> int256
458:              int256(FEE_PRECISION) +

/// @audit uint256 maxLiquidatorReward -> int256
459:              int256(maxLiquidatorReward);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L456

File: tap-token-audit/contracts/governance/twTAP.sol

/// @audit uint256 votes -> int256
343:          weekTotals[w0 + 1].netActiveVotes += int256(votes);

/// @audit uint256 votes -> int256
344:          weekTotals[w1 + 1].netActiveVotes -= int256(votes);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L343

File: tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol

/// @audit uint256 i -> int256
159:                  index = int256(i);

/// @audit uint256 i -> int256
228:                  index = int256(i);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L159

File: tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol

/// @audit uint256 gmxAmount -> int256
327:              int256(gmxAmount),

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L327

[N‑24] public functions not called by the contract should be declared external instead

Contracts are allowed to override their parents' functions and change the visibility from external to public.

There are 74 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

242       function borrow(
243           address from,
244           address to,
245           uint256 amount
246:      ) public notPaused solvent(from) returns (uint256 part, uint256 share) {

263       function repay(
264           address from,
265           address to,
266           bool,
267           uint256 part
268:      ) public notPaused allowedBorrow(from, part) returns (uint256 amount) {

282       function addCollateral(
283           address from,
284           address to,
285           bool skim,
286           uint256 amount,
287           uint256 share
288:      ) public allowedBorrow(from, share) notPaused {

296       function removeCollateral(
297           address from,
298           address to,
299           uint256 share
300:      ) public notPaused solvent(from) allowedBorrow(from, share) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L242-L246

File: tapioca-bar-audit/contracts/markets/MarketERC20.sol

116:      function nonces(address owner) public view returns (uint256) {

201       function approveBorrow(
202           address spender,
203           uint256 amount
204:      ) public returns (bool) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L116

File: tapioca-bar-audit/contracts/markets/singularity/SGLBorrow.sol

21        function borrow(
22            address from,
23            address to,
24            uint256 amount
25:       ) public notPaused solvent(from) returns (uint256 part, uint256 share) {

45        function repay(
46            address from,
47            address to,
48            bool skim,
49            uint256 part
50:       ) public notPaused allowedBorrow(from, part) returns (uint256 amount) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLBorrow.sol#L21-L25

File: tapioca-bar-audit/contracts/markets/singularity/SGLCollateral.sol

21        function addCollateral(
22            address from,
23            address to,
24            bool skim,
25            uint256 amount,
26            uint256 share
27:       ) public notPaused allowedBorrow(from, share) {

35        function removeCollateral(
36            address from,
37            address to,
38            uint256 share
39:       ) public notPaused solvent(from) allowedBorrow(from, share) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCollateral.sol#L21-L27

File: tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol

17        function accrue() public {
18:           _accrue();

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol#L17-L18

File: tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol

154:      function symbol() public view returns (string memory) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L154

File: tapioca-bar-audit/contracts/markets/singularity/Singularity.sol

204       function addAsset(
205           address from,
206           address to,
207           bool skim,
208           uint256 share
209:      ) public notPaused allowedLend(from, share) returns (uint256 fraction) {

219       function removeAsset(
220           address from,
221           address to,
222           uint256 fraction
223:      ) public notPaused returns (uint256 share) {

235       function addCollateral(
236           address from,
237           address to,
238           bool skim,
239           uint256 amount,
240:          uint256 share

259:      function removeCollateral(address from, address to, uint256 share) public {

277       function borrow(
278           address from,
279           address to,
280           uint256 amount
281:      ) public returns (uint256 part, uint256 share) {

296       function repay(
297           address from,
298           address to,
299           bool skim,
300           uint256 part
301:      ) public returns (uint256 amount) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L204-L209

File: tapioca-bar-audit/contracts/Penrose.sol

199       function singularityMarkets()
200           public
201           view
202:          returns (address[] memory markets)

209:      function bigBangMarkets() public view returns (address[] memory markets) {

214:      function singularityMasterContractLength() public view returns (uint256) {

219:      function bigBangMasterContractLength() public view returns (uint256) {

232       function withdrawAllMarketFees(
233           IMarket[] calldata markets_,
234           ISwapper[] calldata swappers_,
235           IPenrose.SwapData[] calldata swapData_
236:      ) public notPaused {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L199-L202

File: tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol

93:       function multiHop(bytes memory _payload) public {

133       function leverageUp(
134           address module,
135           uint16 _srcChainId,
136           bytes memory _srcAddress,
137           uint64 _nonce,
138:          bytes memory _payload

190       function leverageUpInternal(
191           uint256 amount,
192           IUSDOBase.ILeverageSwapData memory swapData,
193           IUSDOBase.ILeverageExternalContractsData memory externalData,
194           IUSDOBase.ILeverageLZData memory lzData,
195:          address leverageFor

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L93

File: tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol

104:      function remove(bytes memory _payload) public {

134       function lend(
135           address module,
136           uint16 _srcChainId,
137           bytes memory _srcAddress,
138           uint64 _nonce,
139:          bytes memory _payload

191       function lendInternal(
192           address to,
193           IUSDOBase.ILendOrRepayParams memory lendParams,
194           ICommonData.IApproval[] memory approvals,
195:          ICommonData.IWithdrawParams memory withdrawParams

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol#L104

File: tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol

103:      function sendFromDestination(bytes memory _payload) public {

138       function exercise(
139           address module,
140           uint16 _srcChainId,
141           bytes memory _srcAddress,
142           uint64 _nonce,
143:          bytes memory _payload

206       function exerciseInternal(
207           address from,
208           uint256 oTAPTokenID,
209           address paymentToken,
210           uint256 tapAmount,
211           address target,
212           ITapiocaOptionsBrokerCrossChain.IExerciseLZSendTapData
213               memory tapSendData,
214:          ICommonData.IApproval[] memory approvals

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol#L103

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol

111:      function multiHop(bytes memory _payload) public {

148       function leverageDown(
149           address module,
150           uint16 _srcChainId,
151           bytes memory _srcAddress,
152           uint64 _nonce,
153:          bytes memory _payload

205       function leverageDownInternal(
206           uint256 amount,
207           IUSDOBase.ILeverageSwapData memory swapData,
208           IUSDOBase.ILeverageExternalContractsData memory externalData,
209           IUSDOBase.ILeverageLZData memory lzData,
210:          address leverageFor

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L111

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol

126       function borrow(
127           address module,
128           uint16 _srcChainId,
129           bytes memory _srcAddress,
130           uint64 _nonce,
131:          bytes memory _payload

180       function borrowInternal(
181           bytes32 _to,
182           ITapiocaOFT.IBorrowParams memory borrowParams,
183           ICommonData.IWithdrawParams memory withdrawParams,
184:          ICommonData.IApproval[] memory approvals

204:      function remove(bytes memory _payload) public {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L126-L131

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol

118:      function sendFromDestination(bytes memory _payload) public {

153       function exercise(
154           address module,
155           uint16 _srcChainId,
156           bytes memory _srcAddress,
157           uint64 _nonce,
158:          bytes memory _payload

221       function exerciseInternal(
222           address from,
223           uint256 oTAPTokenID,
224           address paymentToken,
225           uint256 tapAmount,
226           address target,
227           ITapiocaOptionsBrokerCrossChain.IExerciseLZSendTapData
228               memory tapSendData,
229:          ICommonData.IApproval[] memory approvals

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol#L118

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol

122       function strategyDeposit(
123           address module,
124           uint16 _srcChainId,
125           bytes memory _srcAddress,
126           uint64 _nonce,
127           bytes memory _payload,
128:          IERC20 _erc20

173       function depositToYieldbox(
174           uint256 _assetId,
175           uint256 _amount,
176           uint256 _share,
177           IERC20 _erc20,
178           address _from,
179:          address _to

188       function strategyWithdraw(
189           uint16 _srcChainId,
190:          bytes memory _payload

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol#L122-L128

File: tap-token-audit/contracts/governance/twTAP.sol

155       function getParticipation(
156           uint _tokenId
157:      ) public view returns (Participation memory participant) {

397:      function advanceWeek(uint256 _limit) public {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L155-L157

File: tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol

76        function getCollateralAmountForShare(
77            IMarket market,
78            uint256 share
79:       ) public view returns (uint256 amount) {

89        function getCollateralSharesForBorrowPart(
90            IMarket market,
91            uint256 borrowPart,
92            uint256 liquidationMultiplierPrecision,
93            uint256 exchangeRatePrecision
94:       ) public view returns (uint256 collateralShares) {

117       function getAmountForBorrowPart(
118           IMarket market,
119           uint256 borrowPart
120:      ) public view returns (uint256 amount) {

133       function getBorrowPartForAmount(
134           IMarket market,
135           uint256 amount
136:      ) public view returns (uint256 part) {

150       function getAmountForAssetFraction(
151           ISingularity singularity,
152           uint256 fraction
153:      ) public view returns (uint256 amount) {

171       function getFractionForAmount(
172           ISingularity singularity,
173           uint256 amount
174:      ) public view returns (uint256 fraction) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L76-L79

File: tapioca-periph-audit/contracts/Multicall/Multicall3.sol

41        function multicall(
42            Call[] calldata calls
43:       ) public payable returns (Result[] memory returnData) {

63        function multicallValue(
64            CallValue[] calldata calls
65:       ) public payable returns (Result[] memory returnData) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Multicall/Multicall3.sol#L41-L43

File: tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol

117:      function compound(bytes memory) public {}

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L117

File: tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol

80:       function compoundAmount() public pure returns (uint256 result) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L80

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol

103:      function compoundAmount() public returns (uint256 result) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L103

File: tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol

104:      function harvestGmx(uint256 priceNum, uint256 priceDenom) public onlyOwner {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L104

File: tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol

84:       function compoundAmount() public pure returns (uint256 result) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L84

File: tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol

81:       function compoundAmount() public pure returns (uint256 result) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L81

File: YieldBox/contracts/NativeTokenFactory.sol

56:       function transferOwnership(uint256 tokenId, address newOwner, bool direct, bool renounce) public onlyOwner(tokenId) {

73:       function claimOwnership(uint256 tokenId) public {

90:       function createToken(string calldata name, string calldata symbol, uint8 decimals, string calldata uri) public returns (uint32 tokenId) {

109:      function mint(uint256 tokenId, address to, uint256 amount) public onlyOwner(tokenId) {

116:      function burn(uint256 tokenId, address from, uint256 amount) public allowed(from, tokenId) {

127:      function batchMint(uint256 tokenId, address[] calldata tos, uint256[] calldata amounts) public onlyOwner(tokenId) {

138:      function batchBurn(uint256 tokenId, address[] calldata froms, uint256[] calldata amounts) public {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L56

File: YieldBox/contracts/YieldBox.sol

168       function depositNFTAsset(
169           uint256 assetId,
170           address from,
171           address to
172:      ) public allowed(from, assetId) returns (uint256 amountOut, uint256 shareOut) {

223       function withdraw(
224           uint256 assetId,
225           address from,
226           address to,
227           uint256 amount,
228           uint256 share
229:      ) public allowed(from, assetId) returns (uint256 amountOut, uint256 shareOut) {

303:      function transfer(address from, address to, uint256 assetId, uint256 share) public allowed(from, assetId) {

307:      function batchTransfer(address from, address to, uint256[] calldata assetIds_, uint256[] calldata shares_) public {

336:      function transferMultiple(address from, address[] calldata tos, uint256 assetId, uint256[] calldata shares) public allowed(from, assetId) {

477       function deposit(
478           TokenType tokenType,
479           address contractAddress,
480           IStrategy strategy,
481           uint256 tokenId,
482           address from,
483           address to,
484           uint256 amount,
485           uint256 share
486:      ) public returns (uint256 amountOut, uint256 shareOut) {

500:      function depositETH(IStrategy strategy, address to, uint256 amount) public payable returns (uint256 amountOut, uint256 shareOut) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L168-L172

[N‑25] constants should be defined rather than using magic numbers

Even assembly can benefit from using readable constants instead of hex/numeric literals

There are 194 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

/// @audit 90000
148:          callerFee = 90000; // 90%

/// @audit 10000
149:          protocolFee = 10000; // 10%

/// @audit 75000
150:          collateralizationRate = 75000; // 75%

/// @audit 1e18
154:              : 1e18;

/// @audit 1e3
164:          minLiquidatorReward = 1e3;

/// @audit 1e4
165:          maxLiquidatorReward = 1e4;

/// @audit 1e4
166:          liquidationBonusAmount = 1e4;

/// @audit 50
167:          borrowOpeningFee = 50; // 0.05%

/// @audit 12000
168:          liquidationMultiplier = 12000; //12%

/// @audit 1e18
188:              debtRateAgainstEthMarket) / 1e18;

/// @audit 31536000
521:          _accrueInfo.debtRate = uint64(annumDebtRate / 31536000); //per second

/// @audit 1e18
534:              1e18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L148

File: tapioca-bar-audit/contracts/markets/Market.sol

/// @audit 18
264:          if (borrowPartDecimals > 18) {

/// @audit 18
265:              borrowPartScaled = borrowPart / (10 ** (borrowPartDecimals - 18));

/// @audit 18
267:          if (borrowPartDecimals < 18) {

/// @audit 18
268:              borrowPartScaled = borrowPart * (10 ** (18 - borrowPartDecimals));

/// @audit 18
272:          if (collateralPartDecimals > 18) {

/// @audit 18
275:                  (10 ** (collateralPartDecimals - 18));

/// @audit 18
277:          if (collateralPartDecimals < 18) {

/// @audit 18
280:                  (10 ** (18 - collateralPartDecimals));

/// @audit 18
293:              (10 ** ratesPrecision)) * (10 ** (18 - ratesPrecision));

/// @audit 1e18
295:          uint256 x = (numerator * 1e18) / denominator;

/// @audit 68
376:          if (_returnData.length < 68) return "Market: no return data";

/// @audit 0x04
380:              _returnData := add(_returnData, 0x04)

/// @audit 5
489:          uint256 _quotient = ((_numerator / denominator) + 5) / 10;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L264

File: tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol

/// @audit 1e18
103:              1e18;

/// @audit 1000
210:          if (_totalAsset.base + uint128(fraction) < 1000) {

/// @audit 1000
240:          require(_totalAsset.base >= 1000, "SGL: min limit");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol#L103

File: tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol

/// @audit 1000
75:           require(_totalAsset.base >= 1000, "SGL: min limit");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol#L75

File: tapioca-bar-audit/contracts/markets/singularity/Singularity.sol

/// @audit 951293760
112:          minimumInterestPerSecond = 951293760; // approx 3% APR

/// @audit 2536783360
113:          maximumInterestPerSecond = 2536783360; // approx 8% APR

/// @audit 7200e36
114:          interestElasticity = 7200e36; // Half or double in 28800 seconds (1 hours) if linear

/// @audit 1000
122:          callerFee = 1000; // 1%

/// @audit 10000
123:          protocolFee = 10000; // 10%

/// @audit 50
124:          borrowOpeningFee = 50; // 0.05%

/// @audit 12000
127:          liquidationMultiplier = 12000; //12%

/// @audit 75000
129:          collateralizationRate = 75000;

/// @audit 25000
130:          lqCollateralizationRate = 25000;

/// @audit 1e18
133:              : 1e18;

/// @audit 1e3
135:          minLiquidatorReward = 1e3;

/// @audit 1e4
136:          maxLiquidatorReward = 1e4;

/// @audit 1e4
137:          liquidationBonusAmount = 1e4;

/// @audit 3e17
139:          minimumTargetUtilization = 3e17;

/// @audit 5e17
140:          maximumTargetUtilization = 5e17;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L112

File: tapioca-bar-audit/contracts/Penrose.sol

/// @audit 5e15
131:          bigBangEthDebtRate = 5e15;

/// @audit 68
476:          if (_returnData.length < 68) return "SGL: no return data";

/// @audit 0x04
480:              _returnData := add(_returnData, 0x04)

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L131

File: tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol

/// @audit 100_000
/// @audit 1e18
78:           maxFlashMint = 100_000 * 1e18; // 100k USDO

/// @audit 8
73:       ) OFTV2("USDO", "USDO", 8, _lzEndpoint) {

/// @audit 68
91:           if (_returnData.length < 68) return "USDO: no return data";

/// @audit 0x04
95:               _returnData := add(_returnData, 0x04)

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol#L78

File: tapiocaz-audit/contracts/Balancer.sol

/// @audit 1e5
118:          if (_slippage >= 1e5) revert SlippageNotValid();

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L118

File: tapiocaz-audit/contracts/TapiocaWrapper.sol

/// @audit 0x0
160:          if (address(tapiocaOFTsByErc20[_erc20]) != address(0x0)) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L160

File: tapiocaz-audit/contracts/tOFT/BaseTOFT.sol

/// @audit 18
85:           if (_decimalCache == 0) return 18; //temporary fix for LZ _sharedDecimals check

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFT.sol#L85

File: tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol

/// @audit 68
71:           if (_returnData.length < 68) return "TOFT_data";

/// @audit 0x04
75:               _returnData := add(_returnData, 0x04)

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol#L71

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

/// @audit 4
33:       uint8[4] amountsPerUsers;

/// @audit 4
34:       uint8[4] discountsPerUsers;

/// @audit 1e18
177:          require(tapAmount >= 1e18, "adb: Too low");

/// @audit 4
204:          require(cachedEpoch <= 4, "adb: Airdrop ended");

/// @audit 3
211:          } else if (cachedEpoch == 3) {

/// @audit 4
213:          } else if (cachedEpoch == 4) {

/// @audit 1e18
258:          require(chosenAmount >= 1e18, "adb: Too low");

/// @audit 4
319:          bytes32[4] calldata _merkleRoots

/// @audit 4
335:          } else if (_phase == 4) {

/// @audit 20
424:          uint256 subPhase = 20 + _role;

/// @audit 1e18
434:          uint256 eligibleAmount = uint256(PHASE_2_AMOUNT_PER_USER[_role]) * 1e18;

/// @audit 1e4
435:          uint128 discount = uint128(PHASE_2_DISCOUNT_PER_USER[_role]) * 1e4;

/// @audit 3
450:              userParticipation[tokenIDToAddress][3] == false,

/// @audit 3
456:          userParticipation[tokenIDToAddress][3] = true;

/// @audit 100e4
533:              muldiv(rawPaymentAmount, _discount, 100e4); // 1e4 is discount decimals, 100 is discount percentage

/// @audit 18
535:          paymentAmount = paymentAmount / (10 ** (18 - _paymentTokenDecimals));

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L33

File: tap-token-audit/contracts/options/TapiocaOptionBroker.sol

/// @audit 1e18
190:          require(tapAmount >= 1e18, "tOB: Too low");

/// @audit 1e18
391:          require(chosenAmount >= 1e18, "tOB: Too low");

/// @audit 100e4
554:              muldiv(rawPaymentAmount, _discount, 100e4); // 1e4 is discount decimals, 100 is discount percentage

/// @audit 18
555:          paymentAmount = paymentAmount / (10 ** (18 - _paymentTokenDecimals));

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L190

File: tap-token-audit/contracts/tokens/TapOFT.sol

/// @audit 1e18
/// @audit 15_000_000
121:              _mint(_contributors, 1e18 * 15_000_000);

/// @audit 1e18
/// @audit 3_686_595
122:              _mint(_earlySupporters, 1e18 * 3_686_595);

/// @audit 1e18
/// @audit 12_500_000
123:              _mint(_supporters, 1e18 * 12_500_000);

/// @audit 1e18
/// @audit 5_000_000
124:              _mint(_lbp, 1e18 * 5_000_000);

/// @audit 1e18
/// @audit 8_000_000
125:              _mint(_dao, 1e18 * 8_000_000);

/// @audit 1e18
/// @audit 2_500_000
126:              _mint(_airdrop, 1e18 * 2_500_000);

/// @audit 8
117:      ) BaseTapOFT("TapOFT", "TAP", 8, _lzEndpoint) ERC20Permit("TapOFT") {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L121

File: tap-token-audit/contracts/twAML.sol

/// @audit 1
76:               twos := add(div(sub(0, twos), twos), 1)

/// @audit 3
86:           uint256 inv = (3 * denominator) ^ 2;

/// @audit 1e4
120:          return mul >= 1e4 ? mul / 1e4 : _totalWeight;

/// @audit 3
148:          if (y > 3) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/twAML.sol#L76

File: tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol

/// @audit 4
233:                  WrapData memory data = abi.decode(_action.call[4:], (WrapData));

/// @audit 4
257:                          _action.call[4:],

/// @audit 4
277:                      _action.call[4:],

/// @audit 4
297:                      _action.call[4:],

/// @audit 4
311:                      _action.call[4:],

/// @audit 4
337:                          _action.call[4:],

/// @audit 4
369:                      _action.call[4:],

/// @audit 4
386:                      _action.call[4:],

/// @audit 4
412:                          _action.call[4:],

/// @audit 4
449:                          _action.call[4:],

/// @audit 4
477:                      _action.call[4:],

/// @audit 4
503:                          _action.call[4:],

/// @audit 4
530:                      _action.call[4:],

/// @audit 4
557:                          _action.call[4:],

/// @audit 4
586:                      _action.call[4:],

/// @audit 4
603:                      _action.call[4:],

/// @audit 4
624:                      _action.call[4:],

/// @audit 4
638:                      _action.call[4:],

/// @audit 4
651:                      _action.call[4:],

/// @audit 4
663:                      _action.call[4:],

/// @audit 4
679:                      _action.call[4:],

/// @audit 4
695:                      _action.call[4:],

/// @audit 4
1033:                 actionCalldata[4:],

/// @audit 4
1039:                 actionCalldata[4:],

/// @audit 68
1080:         if (_returnData.length < 68) revert("MagnetarV2: Reason unknown");

/// @audit 0x04
1084:             _returnData := add(_returnData, 0x04)

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L233

File: tapioca-periph-audit/contracts/Multicall/Multicall3.sol

/// @audit 68
96:           if (_returnData.length < 68) revert("Reason unknown");

/// @audit 0x04
100:              _returnData := add(_returnData, 0x04)

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Multicall/Multicall3.sol#L96

File: tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol

/// @audit 1e10
121:          uint256 _btcPrice = uint256(BTC_FEED.latestAnswer()) * 1e10;

/// @audit 1e10
122:          uint256 _wbtcPrice = uint256(WBTC_FEED.latestAnswer()) * 1e10;

/// @audit 1e10
123:          uint256 _ethPrice = uint256(ETH_FEED.latestAnswer()) * 1e10;

/// @audit 1e10
124:          uint256 _usdtPrice = uint256(USDT_FEED.latestAnswer()) * 1e10;

/// @audit 1e18
126:          uint256 _minWbtcPrice = (_wbtcPrice < 1e18)

/// @audit 1e18
127:              ? (_wbtcPrice * _btcPrice) / 1e18

/// @audit 3
132:          _maxPrice = (3 * _vp * FixedPointMathLib.cbrt(_basePrices)) / 1 ether;

/// @audit 1e34
137:          uint256 _discount = Math.max((_g ** 2 / 1 ether) * _a, 1e34); // handle qbrt nonconvergence

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol#L121

File: tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol

/// @audit 0x095ea7b3
100:              abi.encodeWithSelector(0x095ea7b3, to, value)

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol#L100

File: tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol

/// @audit 60
97:           (int24 tick, ) = OracleLibrary.consult(pool, 60);

/// @audit 60
126:          (int24 tick, ) = OracleLibrary.consult(pool, 60);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L97

File: tapioca-periph-audit/contracts/TapiocaDeployer/TapiocaDeployer.sol

/// @audit 0x20
41:               addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)

/// @audit 0x40
74:               let ptr := mload(0x40) // Get free memory pointer

/// @audit 0x40
86:               mstore(add(ptr, 0x40), bytecodeHash)

/// @audit 0x20
87:               mstore(add(ptr, 0x20), salt)

/// @audit 0x0b
89:               let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff

/// @audit 0xff
90:               mstore8(start, 0xff)

/// @audit 85
91:               addr := keccak256(start, 85)

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/TapiocaDeployer/TapiocaDeployer.sol#L41

File: tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol

/// @audit 50
/// @audit 10_000
113:              result = result - (result * 50) / 10_000; //0.5%

/// @audit 12
170:              bool daysPassed = (currentCooldown + 12 days) < block.timestamp;

/// @audit 50
/// @audit 10_000
193:              uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L113

File: tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol

/// @audit 50
/// @audit 10_000
122:          toWithdraw = toWithdraw - (toWithdraw * 50) / 10_000; //0.5%

/// @audit 50
/// @audit 10_000
177:          bptOut = bptOut - (bptOut * 50) / 10_000; //0.5%

/// @audit 250
/// @audit 10_000
250:          bptIn = bptIn + (bptIn * 250) / 10_000; //2.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L122

File: tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol

/// @audit 18
116:          uint256 invested = (shares * pricePerShare) / (10 ** 18);

/// @audit 18
146:              uint256 toWithdraw = (((amount - queued) * (10 ** 18)) /

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L116

File: tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol

/// @audit 50
/// @audit 10_000
143:              result = result - (result * 50) / 10_000; //0.5%

/// @audit 50
/// @audit 10_000
154:          uint256 minAmount = (calcWithdraw * 50) / 10_000; //0.5%

/// @audit 50
/// @audit 10_000
207:                  uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

/// @audit 1e18
312:          if (calcAmount >= 1e18) {

/// @audit 50
/// @audit 10_000
313:              uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

/// @audit 50
/// @audit 10_000
336:              uint256 minAmount = calcWithdraw - (calcWithdraw * 50) / 10_000; //0.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L143

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol

/// @audit 50
/// @audit 10_000
179:                  uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

/// @audit 50
/// @audit 10_000
186:                  minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L179

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol

/// @audit 50
/// @audit 10_000
116:              result = result - (result * 50) / 10_000; //0.5%

/// @audit 50
/// @audit 10_000
170:                  uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

/// @audit 50
/// @audit 10_000
188:          uint256 minAmount = calcWithdraw - (calcWithdraw * 50) / 10_000; //0.5%

/// @audit 50
/// @audit 10_000
232:              uint256 minAmount = calcWithdraw - (calcWithdraw * 50) / 10_000; //0.5%

/// @audit 50
/// @audit 10_000
249:          uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L116

File: tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol

/// @audit 10_000
171:              uint256 fee = (wethAmount * FEE_BPS) / 10_000;

/// @audit 20
310:          uint256 buffer = (freeEsGmx + stakedEsGmx) / 20;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L171

File: tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol

/// @audit 50
/// @audit 10_000
108:          uint256 minAmount = (toWithdraw * 50) / 10_000; //0.5%

/// @audit 250
/// @audit 10_000
151:              uint256 minAmount = toWithdraw - (toWithdraw * 250) / 10_000; //2.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L108

File: tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol

/// @audit 50
/// @audit 10_000
133:              result = result - (result * 50) / 10_000; //0.5%

/// @audit 50
/// @audit 10_000
182:                  uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L133

File: YieldBox/contracts/YieldBoxRebase.sol

/// @audit 1e8
29:           totalShares_ += 1e8;

/// @audit 1e8
52:           totalShares_ += 1e8;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxRebase.sol#L29

File: YieldBox/contracts/YieldBoxURIBuilder.sol

/// @audit 20
37:                                       uint256(uint160(asset.contractAddress)).toHexString(20),

/// @audit 20
90:                   abi.encodePacked("ERC1155:", uint256(uint160(asset.contractAddress)).toHexString(20), "/", asset.tokenId.toString())

/// @audit 20
106:                  ? abi.encodePacked(',"tokenAddress":"', uint256(uint160(asset.contractAddress)).toHexString(20), '"')

/// @audit 20
124:                              uint256(uint160(address(asset.strategy))).toHexString(20),

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxURIBuilder.sol#L37

[N‑26] Event is not properly indexed

Index event fields make the field more quickly accessible to off-chain tools that parse events. This is especially useful when it comes to filtering based on an address. However, note that each index field costs extra gas during emission, so it's not necessarily best to index the maximum allowed per event (three fields). Where applicable, each event should use three indexed fields if there are three or more fields, and gas usage is not particularly of concern for the events in question. If there are fewer than three applicable fields, all of the applicable fields should be indexed.

There are 22 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/Market.sol

102       event Liquidated(
103           address liquidator,
104           address[] users,
105           uint256 liquidatorReward,
106           uint256 protocolReward,
107           uint256 repayedAmount,
108           uint256 collateralShareRemoved
109:      );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L102-L109

File: tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol

136:      event BidExecutionSwapperUpdated(address newAddress);

138:      event UsdoSwapperUpdated(address newAddress);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L136

File: tapioca-bar-audit/contracts/Penrose.sol

140       event RegisterSingularityMasterContract(
141           address location,
142           IPenrose.ContractType risk
143:      );

145       event RegisterBigBangMasterContract(
146           address location,
147           IPenrose.ContractType risk
148:      );

150:      event RegisterSingularity(address location, address masterContract);

152:      event RegisterBigBang(address location, address masterContract);

154:      event FeeToUpdate(address newFeeTo);

156:      event SwapperUpdate(address swapper, bool isRegistered);

158:      event UsdoTokenUpdated(address indexed usdoToken, uint256 assetId);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L140-L143

File: tapiocaz-audit/contracts/Balancer.sol

69        event ConnectedChainUpdated(
70            address indexed _srcOft,
71            uint16 _dstChainId,
72            address indexed _dstOft
73:       );

76        event Rebalanced(
77            address indexed _srcOft,
78            uint16 _dstChainId,
79            uint256 _slippage,
80            uint256 _amount,
81            bool _isNative
82:       );

84        event RebalanceAmountUpdated(
85            address _srcOft,
86            uint16 _dstChainId,
87            uint256 _amount,
88            uint256 _totalAmount
89:       );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L69-L73

File: tap-token-audit/contracts/governance/twTAP.sol

144:      event ExitPosition(uint256 tokenId, uint256 amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L144

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

115:      event Participate(uint256 indexed epoch, uint256 aoTAPTokenID);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L115

File: tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol

94:       event SetSGLPoolWeight(address sgl, uint256 poolWeight);

95:       event RegisterSingularity(address sgl, uint256 assetID);

96:       event UnregisterSingularity(address sgl, uint256 assetID);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L94

File: tap-token-audit/contracts/tokens/BaseTapOFT.sol

41:       event CallFailedStr(uint16 _srcChainId, bytes _payload, string _reason);

42:       event CallFailedBytes(uint16 _srcChainId, bytes _payload, bytes _reason);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L41

File: tapioca-periph-audit/contracts/Magnetar/MagnetarV2Storage.sol

331:      event ApprovalForAll(address owner, address operator, bool approved);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2Storage.sol#L331

File: YieldBox/contracts/NativeTokenFactory.sol

28:       event TokenCreated(address indexed creator, string name, string symbol, uint8 decimals, uint256 tokenId);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L28

[N‑27] Duplicated require()/revert() checks should be refactored to a modifier or function

The compiler will inline the function, which will avoid JUMP instructions usually associated with functions

There are 33 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

391:          require(penrose.swappers(swapper), "SGL: Invalid swapper");

413:          require(amountOut >= minAmountOut, "SGL: not enough");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L391

File: tapioca-bar-audit/contracts/markets/MarketERC20.sol

167:              require(srcBalance >= amount, "ERC20: balance too low");

179:                  require(to != address(0), "ERC20: no zero address"); // Moved down so other failed calls safe some gas

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L167

File: tapioca-bar-audit/contracts/markets/singularity/SGLLeverage.sol

65            require(
66                penrose.swappers(ISwapper(externalData.swapper)),
67                "SGL: Invalid swapper"
68:           );

155:          require(penrose.swappers(swapper), "SGL: Invalid swapper");

182:          require(amountOut >= minAmountOut, "SGL: not enough");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLeverage.sol#L65-L68

File: tapioca-bar-audit/contracts/markets/singularity/Singularity.sol

640:              revert(_getRevertMsg(returnData));

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L640

File: tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol

284:                          revert(reason);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L284

File: tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol

273:                          revert(reason);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol#L273

File: tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol

274:                          revert(reason);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol#L274

File: tapioca-bar-audit/contracts/usd0/USDO.sol

87:           require(token == address(this), "USDO: token not valid");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/USDO.sol#L87

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol

314:                          revert(reason);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L314

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol

290:                          revert(reason);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L290

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol

289:                          revert(reason);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol#L289

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol

98:           require(amount > 0, "TOFT_0");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol#L98

File: tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol

106:          require(!balancers[msg.sender], "TOFT_auth");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol#L106

File: tap-token-audit/contracts/governance/twTAP.sol

390:          require(msg.sender == address(tapOFT), "twTAP: only tapOFT");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L390

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

233:          require(aoTapOption.expiry > block.timestamp, "adb: Option expired");

242           require(
243               paymentTokenOracle.oracle != IOracle(address(0)),
244               "adb: Payment token not supported"
245:          );

255:          require(eligibleTapAmount >= _tapAmount, "adb: Too high");

467:          require(_eligibleAmount > 0, "adb: Not eligible");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L233

File: tap-token-audit/contracts/option-airdrop/aoTAP.sol

129           require(
130               _isApprovedOrOwner(msg.sender, _tokenId),
131               "AOTAP: only approved or owner"
132:          );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L129-L132

File: tap-token-audit/contracts/options/oTAP.sol

116           require(
117               _isApprovedOrOwner(msg.sender, _tokenId),
118               "OTAP: only approved or owner"
119:          );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/oTAP.sol#L116-L119

File: tap-token-audit/contracts/options/TapiocaOptionBroker.sol

368           require(
369               paymentTokenOracle.oracle != IOracle(address(0)),
370               "tOB: Payment token not supported"
371:          );

376:          require(isPositionActive, "tOB: Option expired");

388:          require(eligibleTapAmount >= _tapAmount, "tOB: Too high");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L368-L371

File: tap-token-audit/contracts/tokens/BaseTapOFT.sol

307:          require(twTap.ownerOf(tokenID) == to, "TapOFT: Not owner");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L307

File: YieldBox/contracts/NativeTokenFactory.sol

139:          require(assets[tokenId].tokenType == TokenType.Native, "NTF: Not native");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L139

File: YieldBox/contracts/YieldBoxPermit.sol

80:           require(block.timestamp <= deadline, "YieldBoxPermit: expired deadline");

87:           require(signer == owner, "YieldBoxPermit: invalid signature");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxPermit.sol#L80

File: YieldBox/contracts/YieldBox.sol

382:          require(operator != address(0), "YieldBox: operator not set"); // Important for security

383:          require(operator != address(this), "YieldBox: can't approve yieldBox");

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L382

[N‑28] Vulnerable versions of packages are being used

This project's specific package versions are vulnerable to the specific CVEs listed below. Consider switching to more recent versions of these packages that don't have these vulnerabilities

There are 6 instances of this issue:

File: Various Files

/// @audit Vulnerabilities:
///          
  • CVE-2022-34338 - MEDIUM - (@types/node >=21.0.0 <21.0.3) - IBM Robotic Process Automation 21.0.0, 21.0.1, and 21.0.2 could disclose sensitive information due to improper privilege management for storage provider types. IBM X-Force ID: 229962.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

File: Various Files

/// @audit Vulnerabilities:
///          
  • CVE-2022-34338 - MEDIUM - (@types/node >=21.0.0 <21.0.3) - IBM Robotic Process Automation 21.0.0, 21.0.1, and 21.0.2 could disclose sensitive information due to improper privilege management for storage provider types. IBM X-Force ID: 229962.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol

File: Various Files

/// @audit Vulnerabilities:
///          
  • CVE-2022-34338 - MEDIUM - (@types/node >=21.0.0 <21.0.3) - IBM Robotic Process Automation 21.0.0, 21.0.1, and 21.0.2 could disclose sensitive information due to improper privilege management for storage provider types. IBM X-Force ID: 229962.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol

File: Various Files

/// @audit Vulnerabilities:
///          
  • CVE-2022-34338 - MEDIUM - (@types/node >=21.0.0 <21.0.3) - IBM Robotic Process Automation 21.0.0, 21.0.1, and 21.0.2 could disclose sensitive information due to improper privilege management for storage provider types. IBM X-Force ID: 229962.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol

File: Various Files

/// @audit Vulnerabilities:
///          
  • CVE-2022-34338 - MEDIUM - (@types/node >=21.0.0 <21.0.3) - IBM Robotic Process Automation 21.0.0, 21.0.1, and 21.0.2 could disclose sensitive information due to improper privilege management for storage provider types. IBM X-Force ID: 229962.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol

File: Various Files

/// @audit Vulnerabilities:
///          
  • CVE-2022-34338 - MEDIUM - (@types/node >=21.0.0 <21.0.3) - IBM Robotic Process Automation 21.0.0, 21.0.1, and 21.0.2 could disclose sensitive information due to improper privilege management for storage provider types. IBM X-Force ID: 229962.

[N‑29] Import declarations should import specific identifiers, rather than the whole file

Using import declarations of the form import {<identifier_name>} from "some/file.sol" avoids polluting the symbol namespace making flattened files smaller, and speeds up compilation (but does not save any gas)

There are 345 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

4:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

5:    import "@boringcrypto/boring-solidity/contracts/ERC20.sol";

7:    import "tapioca-periph/contracts/interfaces/IBigBang.sol";

8:    import "tapioca-periph/contracts/interfaces/ISendFrom.sol";

9:    import "tapioca-periph/contracts/interfaces/ISwapper.sol";

12:   import "../Market.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L4

File: tapioca-bar-audit/contracts/markets/MarketERC20.sol

6:    import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L6

File: tapioca-bar-audit/contracts/markets/Market.sol

4:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

5:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringRebase.sol";

7:    import "tapioca-sdk/dist/contracts/YieldBox/contracts/YieldBox.sol";

8:    import "tapioca-periph/contracts/interfaces/IOracle.sol";

9:    import "tapioca-periph/contracts/interfaces/IPenrose.sol";

10:   import "./MarketERC20.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L4

File: tapioca-bar-audit/contracts/markets/singularity/SGLBorrow.sol

4:    import "./SGLLendingCommon.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLBorrow.sol#L4

File: tapioca-bar-audit/contracts/markets/singularity/SGLCollateral.sol

4:    import "./SGLLendingCommon.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCollateral.sol#L4

File: tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol

4:    import "./SGLStorage.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol#L4

File: tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol

4:    import "./SGLCommon.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol#L4

File: tapioca-bar-audit/contracts/markets/singularity/SGLLeverage.sol

4:    import "./SGLLendingCommon.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLeverage.sol#L4

File: tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol

4:    import "./SGLCommon.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L4

File: tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol

4:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

5:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol";

6:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringRebase.sol";

8:    import "tapioca-periph/contracts/interfaces/ISwapper.sol";

9:    import "tapioca-periph/contracts/interfaces/IPenrose.sol";

10:   import "tapioca-periph/contracts/interfaces/ISingularity.sol";

11:   import "tapioca-periph/contracts/interfaces/ILiquidationQueue.sol";

12:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/YieldBox.sol";

14:   import "../Market.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L4

File: tapioca-bar-audit/contracts/markets/singularity/Singularity.sol

4:    import "./SGLCommon.sol";

5:    import "./SGLLiquidation.sol";

6:    import "./SGLCollateral.sol";

7:    import "./SGLBorrow.sol";

8:    import "./SGLLeverage.sol";

10:   import "tapioca-periph/contracts/interfaces/ISendFrom.sol";

11:   import "tapioca-sdk/dist/contracts/libraries/LzLib.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L4

File: tapioca-bar-audit/contracts/Penrose.sol

4:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

5:    import "@boringcrypto/boring-solidity/contracts/BoringFactory.sol";

7:    import "tapioca-sdk/dist/contracts/YieldBox/contracts/YieldBox.sol";

8:    import "tapioca-sdk/dist/contracts/YieldBox/contracts/interfaces/IYieldBox.sol";

9:    import "tapioca-sdk/dist/contracts/YieldBox/contracts/strategies/ERC20WithoutStrategy.sol";

10:   import "tapioca-periph/contracts/interfaces/ISingularity.sol";

11:   import "tapioca-periph/contracts/interfaces/IPenrose.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L4

File: tapioca-bar-audit/contracts/usd0/BaseUSDO.sol

5:    import "tapioca-sdk/dist/contracts/token/oft/v2/OFTV2.sol";

8:    import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

9:    import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";

12:   import "tapioca-periph/contracts/interfaces/IYieldBoxBase.sol";

14:   import "tapioca-periph/contracts/interfaces/ICommonData.sol";

16:   import "./BaseUSDOStorage.sol";

17:   import "./modules/USDOLeverageModule.sol";

18:   import "./modules/USDOMarketModule.sol";

19:   import "./modules/USDOOptionsModule.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDO.sol#L5

File: tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol

5:    import "tapioca-sdk/dist/contracts/token/oft/v2/OFTV2.sol";

8:    import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

9:    import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";

12:   import "tapioca-periph/contracts/interfaces/IYieldBoxBase.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol#L5

File: tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol

5:    import "tapioca-sdk/dist/contracts/libraries/LzLib.sol";

9:    import "tapioca-periph/contracts/interfaces/ISwapper.sol";

10:   import "tapioca-periph/contracts/interfaces/ITapiocaOFT.sol";

11:   import "tapioca-periph/contracts/interfaces/ISingularity.sol";

12:   import "tapioca-periph/contracts/interfaces/IPermitBorrow.sol";

13:   import "tapioca-periph/contracts/interfaces/IPermitAll.sol";

15:   import "../BaseUSDOStorage.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L5

File: tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol

5:    import "tapioca-sdk/dist/contracts/libraries/LzLib.sol";

8:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringRebase.sol";

10:   import "tapioca-periph/contracts/interfaces/ITapiocaOFT.sol";

11:   import "tapioca-periph/contracts/interfaces/IMagnetar.sol";

12:   import "tapioca-periph/contracts/interfaces/IMarket.sol";

13:   import "tapioca-periph/contracts/interfaces/ISingularity.sol";

14:   import "tapioca-periph/contracts/interfaces/IPermitBorrow.sol";

15:   import "tapioca-periph/contracts/interfaces/IPermitAll.sol";

17:   import "../BaseUSDOStorage.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol#L5

File: tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol

5:    import "tapioca-sdk/dist/contracts/libraries/LzLib.sol";

8:    import "tapioca-periph/contracts/interfaces/IPermitBorrow.sol";

9:    import "tapioca-periph/contracts/interfaces/IPermitAll.sol";

10:   import "tapioca-periph/contracts/interfaces/ITapiocaOptionsBroker.sol";

11:   import "tapioca-periph/contracts/interfaces/ISendFrom.sol";

12:   import "../BaseUSDOStorage.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol#L5

File: tapioca-bar-audit/contracts/usd0/USDO.sol

4:    import "tapioca-sdk/dist/contracts/interfaces/ILayerZeroEndpoint.sol";

5:    import "tapioca-periph/contracts/interfaces/IERC3156FlashLender.sol";

6:    import "./BaseUSDO.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/USDO.sol#L4

File: tapiocaz-audit/contracts/Balancer.sol

4:    import "tapioca-periph/contracts/interfaces/ITapiocaOFT.sol";

5:    import "tapioca-periph/contracts/interfaces/IStargateRouter.sol";

6:    import "@rari-capital/solmate/src/auth/Owned.sol";

7:    import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L4

File: tapiocaz-audit/contracts/TapiocaWrapper.sol

4:    import "./tOFT/TapiocaOFT.sol";

5:    import "./tOFT/mTapiocaOFT.sol";

6:    import "tapioca-periph/contracts/interfaces/ITapiocaOFT.sol";

8:    import "@openzeppelin/contracts/utils/Create2.sol";

9:    import "@openzeppelin/contracts/access/Ownable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L4

File: tapiocaz-audit/contracts/tOFT/BaseTOFT.sol

4:    import "./BaseTOFTStorage.sol";

7:    import "./modules/BaseTOFTLeverageModule.sol";

8:    import "./modules/BaseTOFTStrategyModule.sol";

9:    import "./modules/BaseTOFTMarketModule.sol";

10:   import "./modules/BaseTOFTOptionsModule.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFT.sol#L4

File: tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol

5:    import "tapioca-sdk/dist/contracts/token/oft/v2/OFTV2.sol";

6:    import "tapioca-sdk/dist/contracts/libraries/LzLib.sol";

9:    import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";

10:   import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

11:   import "@openzeppelin/contracts/utils/introspection/ERC165.sol";

14:   import "tapioca-periph/contracts/interfaces/IYieldBoxBase.sol";

15:   import "tapioca-periph/contracts/interfaces/ITapiocaOFT.sol";

16:   import "tapioca-periph/contracts/interfaces/ICommonData.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol#L5

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol

5:    import "tapioca-sdk/dist/contracts/libraries/LzLib.sol";

9:    import "tapioca-periph/contracts/interfaces/ISwapper.sol";

10:   import "tapioca-periph/contracts/interfaces/IMagnetar.sol";

11:   import "tapioca-periph/contracts/interfaces/ISingularity.sol";

12:   import "tapioca-periph/contracts/interfaces/IPermitBorrow.sol";

13:   import "tapioca-periph/contracts/interfaces/IPermitAll.sol";

14:   import "tapioca-periph/contracts/interfaces/ITapiocaOptionsBroker.sol";

15:   import "tapioca-periph/contracts/interfaces/ITapiocaOptionLiquidityProvision.sol";

17:   import "../BaseTOFTStorage.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L5

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol

5:    import "tapioca-sdk/dist/contracts/libraries/LzLib.sol";

9:    import "tapioca-periph/contracts/interfaces/ISwapper.sol";

10:   import "tapioca-periph/contracts/interfaces/ITapiocaOFT.sol";

11:   import "tapioca-periph/contracts/interfaces/IMagnetar.sol";

12:   import "tapioca-periph/contracts/interfaces/IMarket.sol";

13:   import "tapioca-periph/contracts/interfaces/IPermitBorrow.sol";

14:   import "tapioca-periph/contracts/interfaces/IPermitAll.sol";

16:   import "../BaseTOFTStorage.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L5

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol

5:    import "tapioca-sdk/dist/contracts/libraries/LzLib.sol";

8:    import "tapioca-periph/contracts/interfaces/IPermitBorrow.sol";

9:    import "tapioca-periph/contracts/interfaces/IPermitAll.sol";

10:   import "tapioca-periph/contracts/interfaces/ITapiocaOptionsBroker.sol";

12:   import "../BaseTOFTStorage.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol#L5

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol

5:    import "tapioca-sdk/dist/contracts/libraries/LzLib.sol";

9:    import "tapioca-periph/contracts/interfaces/ISwapper.sol";

10:   import "tapioca-periph/contracts/interfaces/ITapiocaOFT.sol";

12:   import "../BaseTOFTStorage.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol#L5

File: tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol

3:    import "./BaseTOFT.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol#L3

File: tapiocaz-audit/contracts/tOFT/TapiocaOFT.sol

3:    import "./BaseTOFT.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/TapiocaOFT.sol#L3

File: tap-token-audit/contracts/governance/twTAP.sol

6:    import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

7:    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

8:    import "tapioca-sdk/dist/contracts/util/ERC4494.sol";

9:    import "../tokens/TapOFT.sol";

10:   import "../twAML.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L6

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

4:    import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";

5:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

6:    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

7:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

8:    import "@openzeppelin/contracts/security/Pausable.sol";

9:    import "tapioca-periph/contracts/interfaces/IOracle.sol";

10:   import "../tokens/TapOFT.sol";

11:   import "../twAML.sol";

12:   import "./aoTAP.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L4

File: tap-token-audit/contracts/option-airdrop/aoTAP.sol

5:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

6:    import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

7:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

9:    import "tapioca-sdk/dist/contracts/util/ERC4494.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L5

File: tap-token-audit/contracts/options/oTAP.sol

5:    import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

6:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

7:    import "tapioca-sdk/dist/contracts/util/ERC4494.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/oTAP.sol#L5

File: tap-token-audit/contracts/options/TapiocaOptionBroker.sol

4:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

5:    import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

6:    import "@openzeppelin/contracts/security/Pausable.sol";

7:    import "tapioca-periph/contracts/interfaces/IOracle.sol";

8:    import "./TapiocaOptionLiquidityProvision.sol";

9:    import "../tokens/TapOFT.sol";

10:   import "../twAML.sol";

11:   import "./oTAP.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L4

File: tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol

5:    import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";

6:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

7:    import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";

8:    import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

9:    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

10:   import "@openzeppelin/contracts/security/Pausable.sol";

11:   import "tapioca-sdk/dist/contracts/util/ERC4494.sol";

12:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/interfaces/IYieldBox.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L5

File: tap-token-audit/contracts/tokens/BaseTapOFT.sol

5:    import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";

7:    import "tapioca-periph/contracts/interfaces/ITapiocaOFT.sol";

8:    import "tapioca-sdk/dist/contracts/token/oft/v2/OFTV2.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L5

File: tap-token-audit/contracts/tokens/LTap.sol

4:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

5:    import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L4

File: tap-token-audit/contracts/tokens/TapOFT.sol

5:    import "./BaseTapOFT.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L5

File: tap-token-audit/contracts/Vesting.sol

4:    import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

5:    import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

6:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L4

File: tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol

5:    import "@openzeppelin/contracts/access/Ownable.sol";

6:    import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

9:    import "./MagnetarV2Storage.sol";

10:   import "./modules/MagnetarMarketModule.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L5

File: tapioca-periph-audit/contracts/Magnetar/MagnetarV2Storage.sol

5:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringRebase.sol";

8:    import "../interfaces/IOracle.sol";

9:    import "../interfaces/ISingularity.sol";

10:   import "../interfaces/IBigBang.sol";

11:   import "../interfaces/ITapiocaOFT.sol";

12:   import "../interfaces/ISwapper.sol";

13:   import "../interfaces/ITapiocaOptionsBroker.sol";

14:   import "../interfaces/ITapiocaOptionLiquidityProvision.sol";

15:   import "../interfaces/IPenrose.sol";

16:   import "../interfaces/ITapiocaOptionsBroker.sol";

21:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/enums/YieldBoxTokenType.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2Storage.sol#L5

File: tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol

5:    import "tapioca-sdk/dist/contracts/libraries/LzLib.sol";

8:    import "@openzeppelin/contracts/utils/introspection/IERC165.sol";

9:    import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

10:   import "@openzeppelin/contracts/token/ERC721/IERC721.sol";

13:   import "../../interfaces/IYieldBoxBase.sol";

14:   import "../../interfaces/ITapiocaOptions.sol";

16:   import "../MagnetarV2Storage.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L5

File: tapioca-periph-audit/contracts/Multicall/Multicall3.sol

4:    import "@openzeppelin/contracts/access/Ownable.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Multicall/Multicall3.sol#L4

File: tapioca-periph-audit/contracts/oracle/Seer.sol

4:    import "./OracleMulti.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/Seer.sol#L4

File: tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol

4:    import "@openzeppelin/contracts/access/Ownable.sol";

5:    import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

6:    import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

7:    import "tapioca-sdk/dist/contracts/YieldBox/contracts/interfaces/IYieldBox.sol";

9:    import "../interfaces/ISwapper.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/BaseSwapper.sol#L4

File: tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol

4:    import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

5:    import "./interfaces/ICurvePool.sol";

6:    import "./BaseSwapper.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol#L4

File: tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol

4:    import "./interfaces/IUniswapV2Factory.sol";

5:    import "./interfaces/IUniswapV2Router02.sol";

6:    import "./BaseSwapper.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol#L4

File: tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol

4:    import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";

5:    import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";

6:    import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol";

7:    import "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";

8:    import "@uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol";

9:    import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

11:   import "./libraries/OracleLibrary.sol";

12:   import "./BaseSwapper.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L4

File: tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol

4:    import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

6:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

7:    import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

8:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol";

10:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/strategies/BaseStrategy.sol";

11:   import "../../tapioca-periph/contracts/interfaces/ISwapper.sol";

12:   import "./interfaces/IStkAave.sol";

13:   import "./interfaces/ILendingPool.sol";

14:   import "./interfaces/IIncentivesController.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L4

File: tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol

4:    import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

6:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

7:    import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

8:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol";

10:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/strategies/BaseStrategy.sol";

11:   import "./interfaces/IBalancerVault.sol";

12:   import "./interfaces/IBalancerPool.sol";

13:   import "./interfaces/IBalancerHelpers.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L4

File: tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol

4:    import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

6:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

7:    import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

8:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol";

10:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/strategies/BaseStrategy.sol";

12:   import "../../tapioca-periph/contracts/interfaces/INative.sol";

13:   import "./interfaces/ICToken.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L4

File: tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol

4:    import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

6:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

7:    import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

8:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol";

10:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/strategies/BaseStrategy.sol";

11:   import "../../tapioca-periph/contracts/interfaces/ISwapper.sol";

12:   import "../curve/interfaces/ITricryptoLPGetter.sol";

14:   import "./interfaces/IConvexBooster.sol";

15:   import "./interfaces/IConvexRewardPool.sol";

16:   import "./interfaces/IConvexZap.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L4

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol

4:    import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

6:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

7:    import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

8:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol";

10:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/strategies/BaseStrategy.sol";

11:   import "../../tapioca-periph/contracts/interfaces/ISwapper.sol";

13:   import "./interfaces/ITricryptoLPGetter.sol";

14:   import "./interfaces/ITricryptoLPGauge.sol";

15:   import "./interfaces/ICurveMinter.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L4

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol

4:    import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

6:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

7:    import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

8:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol";

10:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/strategies/BaseStrategy.sol";

11:   import "../../tapioca-periph/contracts/interfaces/ISwapper.sol";

13:   import "./interfaces/ITricryptoLPGetter.sol";

14:   import "./interfaces/ITricryptoLPGauge.sol";

15:   import "./interfaces/ICurveMinter.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L4

File: tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol

5:    import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

6:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol";

7:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

9:    import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";

11:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/enums/YieldBoxTokenType.sol";

12:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/strategies/BaseStrategy.sol";

14:   import "../interfaces/IFeeCollector.sol";

15:   import "../interfaces/gmx/IGlpManager.sol";

16:   import "../interfaces/gmx/IGmxRewardDistributor.sol";

17:   import "../interfaces/gmx/IGmxRewardRouter.sol";

18:   import "../interfaces/gmx/IGmxRewardTracker.sol";

19:   import "../interfaces/gmx/IGmxVester.sol";

20:   import "../interfaces/gmx/IGmxVault.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L5

File: tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol

4:    import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

6:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

7:    import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

8:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol";

10:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/strategies/BaseStrategy.sol";

12:   import "./interfaces/IStEth.sol";

13:   import "./interfaces/ICurveEthStEthPool.sol";

14:   import "../../tapioca-periph/contracts/interfaces/INative.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L4

File: tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol

4:    import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

6:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

7:    import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

8:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol";

10:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/strategies/BaseStrategy.sol";

11:   import "../../tapioca-periph/contracts/interfaces/ISwapper.sol";

13:   import "./interfaces/IRouter.sol";

14:   import "./interfaces/IRouterETH.sol";

15:   import "./interfaces/ILPStaking.sol";

16:   import "../../tapioca-periph/contracts/interfaces/INative.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L4

File: tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol

4:    import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

6:    import "@boringcrypto/boring-solidity/contracts/BoringOwnable.sol";

7:    import "@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol";

8:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol";

10:   import "tapioca-sdk/dist/contracts/YieldBox/contracts/strategies/BaseStrategy.sol";

12:   import "./interfaces/IYearnVault.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L4

File: YieldBox/contracts/NativeTokenFactory.sol

3:    import "./AssetRegister.sol";

4:    import "./BoringMath.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L3

File: YieldBox/contracts/YieldBoxPermit.sol

5:    import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";

6:    import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

7:    import "@openzeppelin/contracts/utils/Counters.sol";

8:    import "./interfaces/IYieldBox.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxPermit.sol#L5

File: YieldBox/contracts/YieldBoxRebase.sol

5:    import "./interfaces/IStrategy.sol";

6:    import "@boringcrypto/boring-solidity/contracts/interfaces/IERC1155.sol";

7:    import "@boringcrypto/boring-solidity/contracts/libraries/Base64.sol";

8:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringAddress.sol";

9:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol";

10:   import "@boringcrypto/boring-solidity/contracts/Domain.sol";

11:   import "./ERC1155TokenReceiver.sol";

12:   import "./ERC1155.sol";

13:   import "@boringcrypto/boring-solidity/contracts/BoringBatchable.sol";

14:   import "@boringcrypto/boring-solidity/contracts/BoringFactory.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxRebase.sol#L5

File: YieldBox/contracts/YieldBox.sol

26:   import "./interfaces/IWrappedNative.sol";

27:   import "./interfaces/IStrategy.sol";

28:   import "@boringcrypto/boring-solidity/contracts/interfaces/IERC721.sol";

29:   import "@boringcrypto/boring-solidity/contracts/interfaces/IERC1155.sol";

30:   import "@boringcrypto/boring-solidity/contracts/libraries/Base64.sol";

31:   import "@boringcrypto/boring-solidity/contracts/Domain.sol";

32:   import "./ERC721TokenReceiver.sol";

33:   import "./ERC1155TokenReceiver.sol";

34:   import "./ERC1155.sol";

35:   import "@boringcrypto/boring-solidity/contracts/BoringBatchable.sol";

36:   import "@openzeppelin/contracts/utils/Strings.sol";

37:   import "./AssetRegister.sol";

38:   import "./NativeTokenFactory.sol";

39:   import "./YieldBoxRebase.sol";

40:   import "./YieldBoxURIBuilder.sol";

41:   import "./YieldBoxPermit.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L26

File: YieldBox/contracts/YieldBoxURIBuilder.sol

3:    import "@openzeppelin/contracts/utils/Strings.sol";

4:    import "@boringcrypto/boring-solidity/contracts/libraries/Base64.sol";

5:    import "@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol";

6:    import "./interfaces/IYieldBox.sol";

7:    import "./NativeTokenFactory.sol";

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxURIBuilder.sol#L3

[N‑30] Return values of approve() not checked

Not all IERC20 implementations revert() when there's a failure in approve(). The function signature has a boolean return value and they indicate errors that way instead. By not checking the return value, operations that should have marked as failed, may potentially go through without actually approving anything

There are 45 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol

217:          IERC20(swapData.tokenOut).approve(externalData.tOft, amountOut);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L217

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol

215:          IERC20(erc20).approve(externalData.swapper, amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L215

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol

184:          _erc20.approve(address(yieldBox), _amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol#L184

File: tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol

157               IERC20(collateralAddress).approve(
158                   address(yieldBox),
159                   collateralAmount
160:              );

234:              IERC20(assetAddress).approve(address(yieldBox), depositAmount);

339                   IERC20(bbCollateralAddress).approve(
340                       address(yieldBox),
341                       mintData.collateralDepositData.amount
342:                  );

386               IERC20(sglAssetAddress).approve(
387                   address(yieldBox),
388                   depositData.amount
389:              );

428:              IERC20(address(singularity)).approve(address(yieldBox), fraction);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L157-L160

File: tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol

75:           wrappedNative.approve(_lendingPool, type(uint256).max);

76:           rewardToken.approve(_multiSwapper, type(uint256).max);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L75

File: tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol

77:           wrappedNative.approve(_vault, type(uint256).max);

78:           IERC20(address(pool)).approve(_vault, type(uint256).max);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L77

File: tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol

58:           wrappedNative.approve(_cToken, type(uint256).max);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L58

File: tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol

105:          wrappedNative.approve(_lpGetter, type(uint256).max);

106:          lpToken.approve(_lpGetter, type(uint256).max);

107:          lpToken.approve(_booster, type(uint256).max);

108:          rewardToken.approve(_multiSwapper, type(uint256).max);

172:          rewardToken.approve(address(swapper), 0);

174:          rewardToken.approve(_swapper, type(uint256).max);

181:          wrappedNative.approve(address(lpGetter), 0);

183:          wrappedNative.approve(_lpGetter, type(uint256).max);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L105

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol

79:           lpToken.approve(_lpGauge, type(uint256).max);

80:           lpToken.approve(_lpGetter, type(uint256).max);

81:           rewardToken.approve(_multiSwapper, type(uint256).max);

82:           wrappedNative.approve(_lpGetter, type(uint256).max);

143:          rewardToken.approve(address(swapper), 0);

144:          rewardToken.approve(_swapper, type(uint256).max);

152:          wrappedNative.approve(address(lpGetter), 0);

154:          wrappedNative.approve(_lpGetter, type(uint256).max);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L79

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol

78:           IERC20(lpGetter.lpToken()).approve(_lpGauge, type(uint256).max);

79:           IERC20(lpGetter.lpToken()).approve(_lpGetter, type(uint256).max);

80:           rewardToken.approve(_multiSwapper, type(uint256).max);

81:           wrappedNative.approve(_lpGetter, type(uint256).max);

134:          rewardToken.approve(address(swapper), 0);

135:          rewardToken.approve(_swapper, type(uint256).max);

143:          wrappedNative.approve(address(lpGetter), 0);

145:          wrappedNative.approve(_lpGetter, type(uint256).max);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L78

File: tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol

175:              weth.approve(address(glpManager), wethAmount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L175

File: tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol

62:           IERC20(_stEth).approve(_curvePool, type(uint256).max);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L62

File: tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol

89:           stgNative.approve(_lpStaking, type(uint256).max);

90:           stgNative.approve(address(router), type(uint256).max);

94:           stgTokenReward.approve(_swapper, type(uint256).max);

151:          stgTokenReward.approve(address(swapper), 0);

153:          stgTokenReward.approve(_swapper, type(uint256).max);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L89

File: tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol

59:           wrappedNative.approve(address(vault), type(uint256).max);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L59

[N‑31] Contract implements interface without extending the interface

Not extending the interface may lead to the wrong function signature being used, leading to unexpected behavior. If the interface is in fact being implemented, use the override keyword to indicate that fact

There are 9 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/MarketERC20.sol

/// @audit IAPWineIBT.transfer(), IAPWineIBT.transferFrom()
24:   contract MarketERC20 is IERC20, IERC20Permit, EIP712 {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L24

File: tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol

/// @audit IAPWineIBT.symbol(), IAPWineIBT.name(), IAPWineIBT.decimals()
34:   contract SGLStorage is BoringOwnable, Market {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L34

File: tapioca-bar-audit/contracts/usd0/USDO.sol

/// @audit IAPWineIBT.mint()
24:   contract USDO is BaseUSDO, IERC3156FlashLender {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/USDO.sol#L24

File: tap-token-audit/contracts/option-airdrop/aoTAP.sol

/// @audit IAPWineIBT.burn()
32:   contract AOTAP is ERC721, ERC721Permit, BaseBoringBatchable, BoringOwnable {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L32

File: tap-token-audit/contracts/options/oTAP.sol

/// @audit IAPWineIBT.burn()
30:   contract OTAP is ERC721, ERC721Permit, BaseBoringBatchable {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/oTAP.sol#L30

File: tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol

/// @audit IERC1155Receiver.onERC1155Received()
48:   contract TapiocaOptionLiquidityProvision is

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L48

File: tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol

/// @audit IAPWineIBT.decimals()
30:   contract ARBTriCryptoOracle is ITOracle {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol#L30

File: tapioca-periph-audit/contracts/oracle/implementations/GLPOracle.sol

/// @audit IAPWineIBT.decimals()
7:    contract GLPOracle is IOracle {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/GLPOracle.sol#L7

File: tapioca-periph-audit/contracts/oracle/implementations/SGOracle.sol

/// @audit IAPWineIBT.decimals()
23:   contract SGOracle is IOracle {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/SGOracle.sol#L23

[N‑32] override function arguments that are unused should have the variable name removed or commented out to avoid compiler warnings

There are 5 instances of this issue:

File: tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

427:          address to,

428:          uint256 amount

432:          address from,

433:          address to,

434:          uint256 amount

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L427

[N‑33] Cast is more restrictive than the type of the variable being assigned

If address foo is being used in an expression such as IERC20 token = FooToken(foo), then the more specific cast to FooToken is a waste because the only thing the compiler will check for is that FooToken extends IERC20 - it won't check any of the function signatures. Therefore, it makes more sense to do IERC20 token = IERC20(token) or better yet FooToken token = FooToken(foo). The former may allow the file in which it's used to remove the import for FooToken

There are 8 instances of this issue:

File: tapioca-bar-audit/contracts/Penrose.sol

/// @audit uint96 vs uint256
104           tapAssetId = uint96(
105               _yieldBox.registerAsset(
106                   TokenType.ERC20,
107                   address(tapToken_),
108                   emptyStrategies[address(tapToken_)],
109                   0
110               )
111:          );

/// @audit uint96 vs uint256
122           wethAssetId = uint96(
123               _yieldBox.registerAsset(
124                   TokenType.ERC20,
125                   address(wethToken_),
126                   emptyStrategies[address(wethToken_)],
127                   0
128               )
129:          );

/// @audit IERC20 vs address
292:          usdoToken = IERC20(_usdoToken);

/// @audit uint96 vs uint256
302           usdoAssetId = uint96(
303               yieldBox.registerAsset(
304                   TokenType.ERC20,
305                   _usdoToken,
306                   emptyStrategies[_usdoToken],
307                   0
308               )
309:          );

/// @audit deploy vs address
373:          _contract = deploy(mc, data, useCreate2);

/// @audit deploy vs address
406:          _contract = deploy(mc, data, useCreate2);

/// @audit clonesOfCount vs uint256
566:                  clonesOfLength = clonesOfCount(mcLocation);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L104-L111

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

/// @audit uint128 vs uint256
292:          epochTAPValuation = uint128(_epochTAPValuation);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L292

[N‑34] Events that mark critical parameter changes should contain both the old and the new value

This should especially be done if the new value is not required to be different from the old value

There are 59 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

/// @audit setBigBangConfig()
477:                  emit MinDebtRateUpdated(minDebtRate, _minDebtRate);

/// @audit setBigBangConfig()
483:                  emit MaxDebtRateUpdated(maxDebtRate, _maxDebtRate);

/// @audit setBigBangConfig()
488                   emit DebtRateAgainstEthUpdated(
489                       debtRateAgainstEthMarket,
490                       _debtRateAgainstEthMarket
491:                  );

/// @audit setBigBangConfig()
500                   emit LiquidationMultiplierUpdated(
501                       liquidationMultiplier,
502                       _liquidationMultiplier
503:                  );

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L477

File: tapioca-bar-audit/contracts/markets/Market.sol

/// @audit setBorrowOpeningFee()
144:          emit LogBorrowingFee(borrowOpeningFee, _val);

/// @audit setBorrowCap()
152:          emit LogBorrowCapUpdated(totalBorrowCap, _cap);

/// @audit setMarketConfig()
173:              emit LogBorrowingFee(borrowOpeningFee, _borrowOpeningFee);

/// @audit setMarketConfig()
179:              emit OracleUpdated();

/// @audit setMarketConfig()
184:              emit OracleDataUpdated();

/// @audit setMarketConfig()
188:              emit ConservatorUpdated(conservator, _conservator);

/// @audit setMarketConfig()
229:              emit LogBorrowCapUpdated(totalBorrowCap, _totalBorrowCap);

/// @audit updatePause()
248:          emit PausedUpdated(paused, val);

/// @audit updateExchangeRate()
346:              emit LogExchangeRate(rate);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L144

File: tapioca-bar-audit/contracts/markets/singularity/Singularity.sol

/// @audit setSingularityConfig()
499               emit MinimumTargetUtilizationUpdated(
500                   minimumTargetUtilization,
501                   _minimumTargetUtilization
502:              );

/// @audit setSingularityConfig()
511               emit MaximumTargetUtilizationUpdated(
512                   maximumTargetUtilization,
513                   _maximumTargetUtilization
514:              );

/// @audit setSingularityConfig()
526               emit MinimumInterestPerSecondUpdated(
527                   minimumInterestPerSecond,
528                   _minimumInterestPerSecond
529:              );

/// @audit setSingularityConfig()
538               emit MaximumInterestPerSecondUpdated(
539                   maximumInterestPerSecond,
540                   _maximumInterestPerSecond
541:              );

/// @audit setSingularityConfig()
558               emit LqCollateralizationRateUpdated(
559                   lqCollateralizationRate,
560                   _lqCollateralizationRate
561:              );

/// @audit setSingularityConfig()
567               emit LiquidationMultiplierUpdated(
568                   liquidationMultiplier,
569                   _liquidationMultiplier
570:              );

/// @audit setLiquidationQueueConfig()
587:              emit BidExecutionSwapperUpdated(_bidExecutionSwapper);

/// @audit setLiquidationQueueConfig()
592:              emit UsdoSwapperUpdated(_usdoSwapper);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L499-L502

File: tapioca-bar-audit/contracts/Penrose.sol

/// @audit setBigBangEthMarketDebtRate()
258:          emit BigBangEthMarketDebtRate(_rate);

/// @audit setBigBangEthMarket()
265:          emit BigBangEthMarketSet(_market);

/// @audit updatePause()
274:          emit PausedUpdated(paused, val);

/// @audit setConservator()
283:          emit ConservatorUpdated(conservator, _conservator);

/// @audit setUsdoToken()
310:          emit UsdoTokenUpdated(_usdoToken, usdoAssetId);

/// @audit registerSingularityMasterContract()
332:          emit RegisterSingularityMasterContract(mcAddress, contractType_);

/// @audit registerBigBangMasterContract()
354:          emit RegisterBigBangMasterContract(mcAddress, contractType_);

/// @audit registerSingularity()
375:          emit RegisterSingularity(_contract, mc);

/// @audit registerBigBang()
408:          emit RegisterBigBang(_contract, mc);

/// @audit setFeeTo()
457:          emit FeeToUpdate(feeTo_);

/// @audit setSwapper()
466:          emit SwapperUpdate(address(swapper), enable);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L258

File: tapioca-bar-audit/contracts/usd0/BaseUSDO.sol

/// @audit setMaxFlashMintable()
89:           emit MaxFlashMintUpdated(maxFlashMint, _val);

/// @audit setFlashMintFee()
98:           emit FlashMintFeeUpdated(flashMintFee, _val);

/// @audit setConservator()
107:          emit ConservatorUpdated(conservator, _conservator);

/// @audit updatePause()
117:          emit PausedUpdated(paused, val);

/// @audit setMinterStatus()
127:          emit SetMinterStatus(_for, _status);

/// @audit setBurnerStatus()
136:          emit SetBurnerStatus(_for, _status);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDO.sol#L89

File: tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol

/// @audit updateConnectedChain()
120           emit ConnectedChainStatusUpdated(
121               _chain,
122               connectedChains[_chain],
123               _status
124:          );

/// @audit updateBalancerState()
135:          emit BalancerStatusUpdated(_balancer, balancers[_balancer], _status);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol#L120-L124

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

/// @audit setTapOracle()
315:          emit SetTapOracle(_tapOracle, _tapOracleData);

/// @audit setPaymentToken()
352:          emit SetPaymentToken(_paymentToken, _oracle, _oracleData);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L315

File: tap-token-audit/contracts/options/TapiocaOptionBroker.sol

/// @audit setTapOracle()
453:          emit SetTapOracle(_tapOracle, _tapOracleData);

/// @audit setPaymentToken()
466:          emit SetPaymentToken(_paymentToken, _oracle, _oracleData);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L453

File: tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol

/// @audit setSGLPoolWEight()
269:          emit SetSGLPoolWeight(address(singularity), weight);

/// @audit registerSingularity()
292:          emit RegisterSingularity(address(singularity), assetID);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L269

File: tap-token-audit/contracts/tokens/TapOFT.sol

/// @audit setGovernanceChainIdentifier()
143           emit GovernanceChainIdentifierUpdated(
144               governanceChainIdentifier,
145               _identifier
146:          );

/// @audit updatePause()
154:          emit PausedUpdated(paused, val);

/// @audit setMinter()
162:          emit MinterUpdated(minter, _minter);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L143-L146

File: tap-token-audit/contracts/Vesting.sol

/// @audit registerUser()
145:          emit UserRegistered(_user, _amount);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L145

File: tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol

/// @audit setPoolFee()
62:           emit PoolFee(poolFee, _newFee);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L62

File: tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol

/// @audit setMultiSwapper()
130:          emit MultiSwapper(address(swapper), _swapper);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L130

File: tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol

/// @audit setMultiSwapper()
171:          emit MultiSwapper(address(swapper), _swapper);

/// @audit setTricryptoLPGetter()
180:          emit LPGetterSet(address(lpGetter), _lpGetter);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L171

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol

/// @audit setMultiSwapper()
142:          emit MultiSwapper(address(swapper), _swapper);

/// @audit setTricryptoLPGetter()
151:          emit LPGetterSet(address(lpGetter), _lpGetter);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L142

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol

/// @audit setMultiSwapper()
133:          emit MultiSwapper(address(swapper), _swapper);

/// @audit setTricryptoLPGetter()
142:          emit LPGetterSet(address(lpGetter), _lpGetter);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L133

File: tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol

/// @audit setMultiSwapper()
150:          emit MultiSwapper(address(swapper), _swapper);

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L150

[N‑35] Constant redefined elsewhere

Consider defining in only one contract so that values cannot become out of sync when only one location is updated. A cheap way to store constants in a single location is to create an internal constant in a library. If the variable is a local cache of another contract's value, consider making the cache variable internal or private, which will require external users to query the contract with the source of truth, so that callers don't get out of sync.

There are 23 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol

/// @audit seen in tapioca-bar-audit/contracts/Penrose.sol 
19:       IYieldBoxBase public immutable yieldBox;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol#L19

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

/// @audit seen in tap-token-audit/contracts/governance/twTAP.sol 
45:       TapOFT public immutable tapOFT;

/// @audit seen in tap-token-audit/contracts/governance/twTAP.sol 
95:       uint256 public constant EPOCH_DURATION = 2 days;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L45

File: tap-token-audit/contracts/options/TapiocaOptionBroker.sol

/// @audit seen in tap-token-audit/contracts/option-airdrop/AirdropBroker.sol 
56:       TapOFT public immutable tapOFT;

/// @audit seen in tap-token-audit/contracts/option-airdrop/AirdropBroker.sol 
78:       uint256 public immutable EPOCH_DURATION; // 7 days = 604800

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L56

File: tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol

/// @audit seen in tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol 
28:       IYieldBox public immutable yieldBox;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol#L28

File: tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol

/// @audit seen in tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol 
35:       ISwapRouter public immutable swapRouter;

/// @audit seen in tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol 
36:       IUniswapV3Factory public immutable factory;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L35

File: tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol 
34:       IERC20 public immutable wrappedNative;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L34

File: tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol 
34:       IERC20 public immutable wrappedNative;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L34

File: tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol 
41:       IERC20 public immutable wrappedNative;

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol 
52:       IERC20 public immutable rewardToken;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L41

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol 
40:       IERC20 public immutable lpToken;

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol 
41:       IERC20 public immutable wrappedNative;

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol 
47:       IERC20 public immutable rewardToken; //CRV token

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L40

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol 
40:       IERC20 public immutable wrappedNative;

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol 
43:       ITricryptoLPGauge public immutable lpGauge;

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol 
44:       ICurveMinter public immutable minter;

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol 
46:       IERC20 public immutable rewardToken; //CRV token

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L40

File: tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol 
36:       IERC20 public immutable wrappedNative;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L36

File: tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol 
41:       IERC20 public immutable wrappedNative;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L41

File: tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol 
36:       IERC20 public immutable wrappedNative;

/// @audit seen in tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol 
37:       IYearnVault public immutable vault;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L36

[N‑36] Use @inheritdoc rather than using a non-standard annotation

There are 5 instances of this issue:

File: tapioca-bar-audit/contracts/markets/MarketERC20.sol

120       /**
121        * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
122        */
123       // solhint-disable-next-line func-name-mixedcase
124:      function DOMAIN_SEPARATOR() external view override returns (bytes32) {

209       /**
210        * @dev See {IERC20Permit-permit}.
211        */
212       function permit(
213           address owner,
214           address spender,
215           uint256 value,
216           uint256 deadline,
217           uint8 v,
218           bytes32 r,
219:          bytes32 s

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L120-L124

File: tap-token-audit/contracts/governance/twTAP.sol

579       /**
580        * @dev See {IERC165-supportsInterface}.
581        */
582       function supportsInterface(
583           bytes4 interfaceId
584:      ) public view virtual override(ONFT721, ERC721) returns (bool) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L579-L584

File: YieldBox/contracts/YieldBoxPermit.sol

98        /**
99         * @dev See {IERC20Permit-nonces}.
100        */
101:      function nonces(address owner) public view virtual returns (uint256) {

105       /**
106        * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.
107        */
108       // solhint-disable-next-line func-name-mixedcase
109:      function DOMAIN_SEPARATOR() external view returns (bytes32) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxPermit.sol#L98-L101

[N‑37] Inconsistent spacing in comments

Some lines use // x and some use //x. The instances below point out the usages that don't follow the majority, within each file

There are 315 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

18:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

19:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

20:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

21:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

22:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

23:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

24:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

25:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

168:          liquidationMultiplier = 12000; //12%

420:              //repay as much as we can

519:          //update debt rate

521:          _accrueInfo.debtRate = uint64(annumDebtRate / 31536000); //per second

730:          uint256 toWithdraw = (amount - part); //acrrued

733:          //burn USDO

757:          //mint USDO

760:          //deposit borrowed amount to user

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L18

File: tapioca-bar-audit/contracts/markets/MarketERC20.sol

11:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

12:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

13:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

14:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

15:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

16:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

17:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

18:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L11

File: tapioca-bar-audit/contracts/markets/Market.sol

66:       uint256 public minLiquidatorReward = 1e3; //1%

68:       uint256 public maxLiquidatorReward = 1e4; //10%

71:       uint256 public liquidationBonusAmount = 1e4; //10%

75:       uint256 public borrowOpeningFee = 50; //0.05%

77:       uint256 public liquidationMultiplier = 12000; //12%

82:       uint256 internal EXCHANGE_RATE_PRECISION; //not costant, but can only be set in the 'init' method

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L66

File: tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol

246:                  _yieldBoxShares[from][ASSET_SIG] = 0; //some assets accrue in time

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol#L246

File: tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol

51:               _yieldBoxShares[from][COLLATERAL_SIG] = 0; //accrues in time

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol#L51

File: tapioca-bar-audit/contracts/markets/singularity/SGLLeverage.sol

34:           //add collateral

43:           //borrow

46:           //withdraw

80:           //send for unwrap

133:              //repay as much as we can

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLeverage.sol#L34

File: tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol

21:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

22:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

23:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

24:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

25:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

26:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

27:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

28:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L21

File: tapioca-bar-audit/contracts/markets/singularity/Singularity.sol

18:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

19:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

20:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

21:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

22:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

23:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

24:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

25:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

121:          //default fees

126:          //liquidation

127:          liquidationMultiplier = 12000; //12%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L18

File: tapioca-bar-audit/contracts/Penrose.sol

16:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

17:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

18:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

19:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

20:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

21:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

22:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

23:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L16

File: tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol

201:          // Use market helper to deposit and add asset to market

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol#L201

File: tapioca-bar-audit/contracts/usd0/USDO.sol

11:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

12:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

13:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

14:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

15:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

16:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

17:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

18:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/USDO.sol#L11

File: tapiocaz-audit/contracts/Balancer.sol

155:                  1e3, //1% slippage

188:          //check if OFT is still valid

197:          //extract

200:          //send

290:              _oft, //refund

326:              _oft, //refund,

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L155

File: tapiocaz-audit/contracts/TapiocaWrapper.sol

13:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

14:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

15:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

16:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

17:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

18:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

19:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L13

File: tapiocaz-audit/contracts/tOFT/BaseTOFT.sol

85:           if (_decimalCache == 0) return 18; //temporary fix for LZ _sharedDecimals check

347:      //---internal-

378:      //---private---

441:      //---LZ---

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFT.sol#L85

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol

135:              address _from, //from

174:              revert(_getRevertMsg(reason)); //forward revert because it's handled by the main executor

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L135

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol

167:              revert(_getRevertMsg(reason)); //forward revert because it's handled by the main executor

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol#L167

File: tapiocaz-audit/contracts/tOFT/TapiocaOFT.sol

7:     _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

8:      _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

9:       _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

10:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

11:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

12:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

13:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/TapiocaOFT.sol#L7

File: tap-token-audit/contracts/governance/twTAP.sol

14:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

15:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

16:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

17:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

18:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

19:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

20:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L14

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

17:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

18:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

19:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

20:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

21:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

22:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

23:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

24:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L17

File: tap-token-audit/contracts/option-airdrop/aoTAP.sol

14:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

15:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

16:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

17:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

18:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

19:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

20:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

21:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L14

File: tap-token-audit/contracts/options/oTAP.sol

12:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

13:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

14:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

15:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

16:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

17:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

18:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

19:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/oTAP.sol#L12

File: tap-token-audit/contracts/options/TapiocaOptionBroker.sol

16:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

17:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

18:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

19:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

20:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

21:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

22:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

23:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L16

File: tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol

17:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

18:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

19:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

20:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

21:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

22:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

23:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

24:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L17

File: tap-token-audit/contracts/tokens/BaseTapOFT.sol

13:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

14:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

15:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

16:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

17:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

18:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

19:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

20:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

51:       //---LZ---

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L13

File: tap-token-audit/contracts/tokens/LTap.sol

28:       /// @notice Creates a new LTAP token

29:       /// @dev LTAP tokens are minted by depositing TAP

30:       /// @param _tapToken Address of the TAP token

31:       /// @param _maxLockedUntil Latest possible end of locking period

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L28

File: tap-token-audit/contracts/tokens/TapOFT.sol

10:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

11:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

12:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

13:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

14:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

15:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

16:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

17:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

137:      ///-- Owner methods --

166:      //-- View methods --

194:      ///-- Write methods --

238:      ///-- Internal methods --

245:      ///-- Private methods --

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L10

File: tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol

15:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

16:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

17:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

18:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

19:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

20:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

21:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

22:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L15

File: tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol

144:          //deposit to YieldBox

274:              //withdraw

354:                  //add collateral to BingBang

590:              //withdraw

651:              //withdraw

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L144

File: tapioca-periph-audit/contracts/Multicall/Multicall3.sol

74:               // Humanity will be a Type V Kardashev Civilization before this overflows - andreas

75:               // ~ 10^25 Wei in existence << ~ 10^76 size uint fits in a uint256

89:           // Finally, make sure the msg.value = SUM(call[0...i].value)

94:           // If the _res length is less than 68, then

95:           // the transaction failed with custom error or silently (without a revert message)

99:               // Slice the sighash.

102:          revert(abi.decode(_returnData, (string))); // All that remains is the revert string

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Multicall/Multicall3.sol#L74

File: tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol

11:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

12:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

13:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

14:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

15:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

16:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

17:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

18:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol#L11

File: tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol

11:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

12:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

13:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

14:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

15:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

16:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

17:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol#L11

File: tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol

17:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

18:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

19:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

20:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

21:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

22:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

23:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L17

File: tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol

18:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

19:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

20:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

21:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

22:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

23:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

24:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

38:       //AAVE

113:              result = result - (result * 50) / 10_000; //0.5%

140:          //first claim stkAave

154:          //try to claim AAVE

162:          //try to cooldown

169:              //we have an active cooldown; check if we need to cooldown again

178:          //try to stake

183:              //swap AAVE to wrappedNative

193:              uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

196:              //stake if > depositThreshold

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L18

File: tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol

18:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

19:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

20:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

21:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

22:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

23:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

24:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

39:       IBalancerPool public immutable pool; //lp token

122:          toWithdraw = toWithdraw - (toWithdraw * 50) / 10_000; //0.5%

177:          bptOut = bptOut - (bptOut * 50) / 10_000; //0.5%

250:          bptIn = bptIn + (bptIn * 250) / 10_000; //2.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L18

File: tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol

18:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

19:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

20:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

21:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

22:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

23:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

24:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L18

File: tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol

21:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

22:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

23:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

24:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

25:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

26:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

27:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

143:              result = result - (result * 50) / 10_000; //0.5%

154:          uint256 minAmount = (calcWithdraw * 50) / 10_000; //0.5%

207:                  uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

313:              uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

336:              uint256 minAmount = calcWithdraw - (calcWithdraw * 50) / 10_000; //0.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L21

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol

20:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

21:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

22:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

23:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

24:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

25:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

26:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

47:       IERC20 public immutable rewardToken; //CRV token

179:                  uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

186:                  minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L20

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol

20:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

21:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

22:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

23:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

24:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

25:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

26:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

46:       IERC20 public immutable rewardToken; //CRV token

116:              result = result - (result * 50) / 10_000; //0.5%

170:                  uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

188:          uint256 minAmount = calcWithdraw - (calcWithdraw * 50) / 10_000; //0.5%

201:          return assetAmount + queued; //+ compoundAmount;

232:              uint256 minAmount = calcWithdraw - (calcWithdraw * 50) / 10_000; //0.5%

249:          uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L20

File: tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol

19:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

20:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

21:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

22:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

23:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

24:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

25:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

108:          uint256 minAmount = (toWithdraw * 50) / 10_000; //0.5%

133:              stEth.submit{value: queued}(address(0)); //1:1 between eth<>stEth

150:              uint256 toWithdraw = amount - queued; //1:1 between eth<>stEth

151:              uint256 minAmount = toWithdraw - (toWithdraw * 250) / 10_000; //2.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L19

File: tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol

21:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

22:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

23:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

24:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

25:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

26:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

27:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

51:       IERC20 public stgNative; //ex: stEth

133:              result = result - (result * 50) / 10_000; //0.5%

182:                  uint256 minAmount = calcAmount - (calcAmount * 50) / 10_000; //0.5%

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L21

File: tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol

16:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

17:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

18:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

19:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

20:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

21:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

22:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

147:          wrappedNative.safeTransfer(to, amount - 1); //rounding error

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L16

[N‑38] Lines are too long

Usually lines in source code are limited to 80 characters. Today's screens are much larger so it's reasonable to stretch this in some cases. The solidity style guide recommends a maximumum line length of 120 characters, so the lines below should be split when they reach that length.

There are 361 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

17:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

18:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

19:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

20:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

21:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

22:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

23:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

24:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

25:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

34:   ///     - interest rate is not fixed, but dynamic based on the main BigBang market, minDebtRate, maxDebtRate and debtRateAgainstEthMarket

35:   ///         - BigBang markets can either be main or secondary markets; the main market is set on Penrose and has a fixed rate

37:   ///             - if current debt is over _maxDebtPoint = (_ethMarketTotalDebt * debtRateAgainstEthMarket) / 1e18, the interest rate is automatically `maxDebtRate`

258:      /// @dev The bool param is not used but we added it to respect the ISingularity interface for MarketsHelper compatibility

306:      /// @param maxBorrowParts A one-to-one mapping to `users`, contains maximum (partial) borrow amounts (to liquidate) of the respective user.

655:      /// @param maxBorrowParts A one-to-one mapping to `users`, contains maximum (partial) borrow amounts (to liquidate) of the respective user.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L17

File: tapioca-bar-audit/contracts/markets/MarketERC20.sol

10:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

11:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

12:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

13:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

14:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

15:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

16:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

17:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

18:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L10

File: tapioca-bar-audit/contracts/markets/Market.sol

299:      /// @notice return the amount of collateral for a `user` to be solvent, min TVL and max TVL. Returns 0 if user already solvent.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L299

File: tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol

21:       /// @param maxBorrowParts A one-to-one mapping to `users`, contains maximum (partial) borrow amounts (to liquidate) of the respective user.

373:      /// @param maxBorrowParts A one-to-one mapping to `users`, contains maximum (partial) borrow amounts (to liquidate) of the respective user.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L21

File: tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol

20:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

21:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

22:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

23:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

24:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

25:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

26:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

27:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

28:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

44:       Rebase public totalAsset; // elastic = yieldBox shares held by the Singularity, base = Total fractions held by asset suppliers

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L20

File: tapioca-bar-audit/contracts/markets/singularity/Singularity.sol

17:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

18:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

19:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

20:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

21:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

22:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

23:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

24:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

25:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

35:   ///     - adding assets to the contract, mints shares to the `to` address which can later be used in the oTap & twTap system

36:   ///     - interest rate is automatically updated based on the interest elasticity time and it's bounded by `minimumInterestPerSecond` and `maximumInterestPerSecond`

432:      /// @param maxBorrowParts A one-to-one mapping to `users`, contains maximum (partial) borrow amounts (to liquidate) of the respective user.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L17

File: tapioca-bar-audit/contracts/Penrose.sol

15:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

16:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

17:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

18:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

19:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

20:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

21:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

22:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

23:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L15

File: tapioca-bar-audit/contracts/usd0/USDO.sol

10:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

11:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

12:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

13:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

14:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

15:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

16:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

17:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

18:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/USDO.sol#L10

File: tapiocaz-audit/contracts/TapiocaWrapper.sol

12:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

13:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

14:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

15:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

16:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

17:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

18:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

19:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

20:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L12

File: tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol

8:    ///      - wrapping & unwrapping of the ERC20/the gas token can happen on multiple chains defined by the `connectedChains` mapping

85:       /// @dev Since it can be executed only on the main chain, if an address exists on the OP chain it will not allowed to wrap.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol#L8

File: tapiocaz-audit/contracts/tOFT/TapiocaOFT.sol

6:    __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

7:     _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

8:      _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

9:       _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

10:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

11:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

12:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

13:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

14:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

65:       /// @dev Since it can be executed only on the main chain, if an address exists on the OP chain it will not allowed to wrap.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/TapiocaOFT.sol#L6

File: tap-token-audit/contracts/governance/twTAP.sol

13:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

14:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

15:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

16:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

17:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

18:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

19:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

20:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

21:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

64:   /// @dev This contract allow the locking of TAP to twTAP. The amount of twTAP received is based on the amount of locked TAP, and the duration of the lock.

65:   ///      It uses twAML to compute the amount of twTAP received, details about the model can be found here https://docs.tapioca.xyz/tapioca/core-technologies/twaml.

66:   ///      The contract distributes a set of rewards tokens each week to the twTAP holders. The amount of rewards received is based on the amount of twTAP held.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/governance/twTAP.sol#L13

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

16:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

17:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

18:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

19:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

20:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

21:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

22:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

23:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

24:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

38:   /// @notice Forked version of TapiocaOptionBroker. More details found here https://docs.tapioca.xyz/tapioca/launch/option-airdrop#eligibility-and-details

39:   /// @dev This contract is used to manage the Tapioca Option Airdrop. It allows for users to participate in the airdrop and exercise their options.

136:      /// @param _tapAmount The amount of TAP to be exchanged. If 0 it will use the full amount of TAP eligible for the deal

407:      /// @notice Participate in phase 2 of the Airdrop. Guild members will receive pre-defined discounts and TAP, based on role.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L16

File: tap-token-audit/contracts/option-airdrop/aoTAP.sol

13:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

14:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

15:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

16:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

17:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

18:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

19:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

20:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

21:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L13

File: tap-token-audit/contracts/options/oTAP.sol

11:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

12:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

13:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

14:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

15:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

16:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

17:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

18:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

19:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/oTAP.sol#L11

File: tap-token-audit/contracts/options/TapiocaOptionBroker.sol

15:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

16:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

17:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

18:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

19:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

20:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

21:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

22:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

23:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

45:   /// @notice This contract handles the creation of oTAP, the oTAP options creates an expiry dates to exercise the option, and an eligible amount of TAP that can be exercised.

46:   ///         The amount of TAP that can be exercised is calculated by the TWAML algorithm, which takes into account the size of the participant as well his lock time.

48:   ///         More info about the mechanic of how to receive oTAP can be found here https://docs.tapioca.xyz/tapioca/token-economy/dso-dao-share-options

141:      /// @param _tapAmount The amount of TAP to be exchanged. If 0 it will use the full amount of TAP eligible for the deal

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L15

File: tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol

16:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

17:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

18:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

19:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

20:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

21:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

22:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

23:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

24:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

42:   ///         tOLP tokens are minted when a user locks their Singularity position and can be burned only when the position is unlocked,

62:       mapping(uint256 => IERC20) public sglAssetIDToAddress; // Singularity market YieldBox asset ID => Singularity market address

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L16

File: tap-token-audit/contracts/tokens/BaseTapOFT.sol

12:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

13:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

14:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

15:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

16:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

17:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

18:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

19:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

20:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/BaseTapOFT.sol#L12

File: tap-token-audit/contracts/tokens/LTap.sol

9:    __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

10:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

11:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

12:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

13:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

14:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

15:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

16:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

17:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L9

File: tap-token-audit/contracts/tokens/TapOFT.sol

9:    __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

10:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

11:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

12:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

13:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

14:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

15:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

16:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

17:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L9

File: tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol

14:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

15:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

16:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

17:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

18:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

19:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

20:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

21:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

22:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

880:      /// @notice helper to exit from  tOB, unlock from tOLP, remove from SGL, repay on BB, remove collateral from BB and withdraw

885:      ///         - if `!removeAndRepayData.assetWithdrawData.withdraw && removeAndRepayData.repayAssetOnBB`, the repay operation is performed

887:      ///     - the helper can either stop at the remove asset from SGL step or it can continue until is removes & withdraws collateral from BB

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L14

File: tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol

257:          // if `withdrawCollateralParams.withdraw` it uses `withdrawTo` to withdraw collateral on the same chain or to another one

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L257

File: tapioca-periph-audit/contracts/Multicall/Multicall3.sol

8:    __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

9:     _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

10:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

11:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

12:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

13:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

14:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

15:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

16:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Multicall/Multicall3.sol#L8

File: tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol

68:       /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

79:       /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

88:       /// @notice Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek().

90:       /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

100:      /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

108:      /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol#L68

File: tapioca-periph-audit/contracts/oracle/implementations/SGOracle.sol

58:       /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

69:       /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

78:       /// @notice Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek().

80:       /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

90:       /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

98:       /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/SGOracle.sol#L58

File: tapioca-periph-audit/contracts/oracle/Seer.sol

49:       /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

61:       /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

71:       /// @notice Check the current spot exchange rate without any state changes. For oracles like TWAP this will be different from peek().

73:       /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

84:       /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

92:       /// (string memory collateralSymbol, string memory assetSymbol, uint256 division) = abi.decode(data, (string, string, uint256));

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/Seer.sol#L49

File: tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol

10:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

11:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

12:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

13:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

14:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

15:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

16:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

17:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

18:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol#L10

File: tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol

10:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

11:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

12:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

13:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

14:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

15:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

16:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

17:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

18:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol#L10

File: tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol

16:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

17:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

18:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

19:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

20:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

21:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

22:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

23:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

24:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L16

File: tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol

17:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

18:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

19:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

20:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

21:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

22:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

23:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

24:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

25:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L17

File: tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol

17:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

18:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

19:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

20:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

21:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

22:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

23:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

24:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

25:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L17

File: tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol

17:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

18:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

19:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

20:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

21:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

22:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

23:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

24:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

25:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L17

File: tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol

20:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

21:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

22:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

23:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

24:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

25:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

26:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

27:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

28:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L20

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol

19:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

20:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

21:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

22:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

23:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

24:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

25:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

26:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

27:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L19

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol

19:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

20:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

21:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

22:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

23:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

24:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

25:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

26:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

27:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L19

File: tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol

18:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

19:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

20:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

21:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

22:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

23:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

24:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

25:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

26:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L18

File: tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol

20:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

21:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

22:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

23:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

24:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

25:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

26:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

27:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

28:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

31:   //TODO: decide if we need to start with ETH and wrap it into WETH; stargate allows ETH. not WETH, while others allow WETH, not ETH

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L20

File: tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol

15:   __/\\\\\\\\\\\\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\\____/\\\\\\\\\\\_______/\\\\\_____________/\\\\\\\\\_____/\\\\\\\\\____        

16:    _\///////\\\/////____/\\\\\\\\\\\\\__\/\\\/////////\\\_\/////\\\///______/\\\///\\\________/\\\////////____/\\\\\\\\\\\\\__       

17:     _______\/\\\________/\\\/////////\\\_\/\\\_______\/\\\_____\/\\\_______/\\\/__\///\\\____/\\\/____________/\\\/////////\\\_      

18:      _______\/\\\_______\/\\\_______\/\\\_\/\\\\\\\\\\\\\/______\/\\\______/\\\______\//\\\__/\\\_____________\/\\\_______\/\\\_     

19:       _______\/\\\_______\/\\\\\\\\\\\\\\\_\/\\\/////////________\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\\\\\\\\\\\\\_    

20:        _______\/\\\_______\/\\\/////////\\\_\/\\\_________________\/\\\_____\//\\\______/\\\__\//\\\____________\/\\\/////////\\\_   

21:         _______\/\\\_______\/\\\_______\/\\\_\/\\\_________________\/\\\______\///\\\__/\\\_____\///\\\__________\/\\\_______\/\\\_  

22:          _______\/\\\_______\/\\\_______\/\\\_\/\\\______________/\\\\\\\\\\\____\///\\\\\/________\////\\\\\\\\\_\/\\\_______\/\\\_ 

23:           _______\///________\///________\///__\///______________\///////////_______\/////_____________\/////////__\///________\///__

26:   //TODO: decide if we need to start with ETH and wrap it into WETH; stargate allows ETH. not WETH, while others allow WETH, not ETH

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L15

File: YieldBox/contracts/NativeTokenFactory.sol

55:       /// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.

56:       function transferOwnership(uint256 tokenId, address newOwner, bool direct, bool renounce) public onlyOwner(tokenId) {

89:       /// @param decimals The number of decimals of the token (this is just for display purposes). Should be set to 18 in normal cases.

90:       function createToken(string calldata name, string calldata symbol, uint8 decimals, string calldata uri) public returns (uint32 tokenId) {

91:           // To keep each Token unique in the AssetRegister, we use the assetId as the tokenId. So for native assets, the tokenId is always equal to the assetId.

104:      /// @notice The `owner` can mint tokens. If a fixed supply is needed, the `owner` should mint the totalSupply and renounce ownership.

108:      /// @dev For security reasons, operators are not allowed to mint. Only the actual owner can do this. Of course the owner can be a contract.

121:      /// @notice The `owner` can mint tokens. If a fixed supply is needed, the `owner` should mint the totalSupply and renounce ownership.

125:      /// @dev If the tos array is longer than the amounts array there will be an out of bounds error. If the amounts array is longer, the extra amounts are simply ignored.

126:      /// @dev For security reasons, operators are not allowed to mint. Only the actual owner can do this. Of course the owner can be a contract.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L55

File: YieldBox/contracts/YieldBoxPermit.sol

53:           bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, assetId, _useNonce(owner), deadline));

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxPermit.sol#L53

File: YieldBox/contracts/YieldBox.sol

4:    // The original BentoBox is owned by the Sushi team to set strategies for each token. Abracadabra wanted different strategies, which led to

5:    // them launching their own DegenBox. The YieldBox solves this by allowing an unlimited number of strategies for each token in a fully

127:          require(asset.tokenType != TokenType.Native && asset.tokenType != TokenType.ERC721, "YieldBox: can't deposit type");

135:              // amount may be lower than the value of share due to rounding, in that case, add 1 to amount (Always round up)

143:              // For ERC20 tokens, use the safe helper function to deal with broken ERC20 implementations. This actually calls transferFrom on the ERC20 contract.

151:                  IERC1155(asset.contractAddress).safeTransferFrom(from, address(asset.strategy), asset.tokenId, amount, "");

196:      function depositETHAsset(uint256 assetId, address to, uint256 amount) public payable returns (uint256 amountOut, uint256 shareOut) {

199:          require(asset.tokenType == TokenType.ERC20 && asset.contractAddress == address(wrappedNative), "YieldBox: not wrappedNative");

208:          // Strategies always receive wrappedNative (supporting both wrapped and raw native tokens adds too much complexity)

281:              // value of the share paid could be lower than the amount paid due to rounding, in that case, add a share (Always round up)

316:      function _transferBatch(address from, address to, uint256[] calldata ids, uint256[] calldata values) internal override {

336:      function transferMultiple(address from, address[] calldata tos, uint256 assetId, uint256[] calldata shares) public allowed(from, assetId) {

400:      // This functionality has been split off into a separate contract. This is only a view function, so gas usage isn't a huge issue.

489:              return depositAsset(registerAsset(TokenType.ERC1155, address(this), strategy, tokenId), from, to, amount, share);

500:      function depositETH(IStrategy strategy, address to, uint256 amount) public payable returns (uint256 amountOut, uint256 shareOut) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L4

File: YieldBox/contracts/YieldBoxURIBuilder.sol

90:                   abi.encodePacked("ERC1155:", uint256(uint160(asset.contractAddress)).toHexString(20), "/", asset.tokenId.toString())

107:                  : abi.encodePacked(',"totalSupply":', totalSupply.toString(), ',"fixedSupply":', owner == address(0) ? "true" : "false")

129:                              asset.tokenType == TokenType.ERC1155 ? string(abi.encodePacked(',"tokenId":', asset.tokenId.toString())) : "",

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxURIBuilder.sol#L90

[N‑39] Variable names that consist of all capital letters should be reserved for constant/immutable variables

If the variable needs to be different based on which class it comes from, a view/pure function should be used instead (e.g. like this).

There are 6 instances of this issue:

File: tapioca-bar-audit/contracts/markets/MarketERC20.sol

45:       bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L45

File: tapioca-bar-audit/contracts/markets/Market.sol

82:       uint256 internal EXCHANGE_RATE_PRECISION; //not costant, but can only be set in the 'init' method

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L82

File: tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol

50        bytes32 internal ASSET_SIG =
51:           0x0bd4060688a1800ae986e4840aebc924bb40b5bf44de4583df2257220b54b77c; // keccak256("asset")

52        bytes32 internal COLLATERAL_SIG =
53:           0x7d1dc38e60930664f8cbf495da6556ca091d2f92d6550877750c049864b18230; // keccak256("collateral")

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L50-L51

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

77:       uint8[4] public PHASE_2_AMOUNT_PER_USER = [200, 190, 200, 190];

78:       uint8[4] public PHASE_2_DISCOUNT_PER_USER = [50, 40, 40, 33];

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L77

[N‑40] Non-library/interface files should use fixed compiler versions, not floating ones

There are 59 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L2

File: tapioca-bar-audit/contracts/markets/MarketERC20.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L2

File: tapioca-bar-audit/contracts/markets/singularity/SGLBorrow.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLBorrow.sol#L2

File: tapioca-bar-audit/contracts/markets/singularity/SGLCollateral.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCollateral.sol#L2

File: tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol#L2

File: tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol#L2

File: tapioca-bar-audit/contracts/markets/singularity/SGLLeverage.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLeverage.sol#L2

File: tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L2

File: tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L2

File: tapioca-bar-audit/contracts/markets/singularity/Singularity.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L2

File: tapioca-bar-audit/contracts/Penrose.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L2

File: tapioca-bar-audit/contracts/usd0/BaseUSDO.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDO.sol#L2

File: tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDOStorage.sol#L2

File: tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOLeverageModule.sol#L2

File: tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOMarketModule.sol#L2

File: tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/modules/USDOOptionsModule.sol#L2

File: tapioca-bar-audit/contracts/usd0/USDO.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/USDO.sol#L2

File: tapiocaz-audit/contracts/Balancer.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L2

File: tapiocaz-audit/contracts/TapiocaWrapper.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/TapiocaWrapper.sol#L2

File: tapiocaz-audit/contracts/tOFT/BaseTOFT.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFT.sol#L2

File: tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFTStorage.sol#L2

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTLeverageModule.sol#L2

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTMarketModule.sol#L2

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTOptionsModule.sol#L2

File: tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/modules/BaseTOFTStrategyModule.sol#L2

File: tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol#L2

File: tapiocaz-audit/contracts/tOFT/TapiocaOFT.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/TapiocaOFT.sol#L2

File: tap-token-audit/contracts/option-airdrop/AirdropBroker.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/AirdropBroker.sol#L2

File: tap-token-audit/contracts/option-airdrop/aoTAP.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/option-airdrop/aoTAP.sol#L2

File: tap-token-audit/contracts/options/oTAP.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/oTAP.sol#L2

File: tap-token-audit/contracts/options/TapiocaOptionBroker.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionBroker.sol#L2

File: tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/options/TapiocaOptionLiquidityProvision.sol#L2

File: tap-token-audit/contracts/tokens/LTap.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/LTap.sol#L2

File: tap-token-audit/contracts/tokens/TapOFT.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/tokens/TapOFT.sol#L2

File: tap-token-audit/contracts/Vesting.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/Vesting.sol#L2

File: tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2.sol#L2

File: tapioca-periph-audit/contracts/Magnetar/MagnetarV2Storage.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/MagnetarV2Storage.sol#L2

File: tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Magnetar/modules/MagnetarMarketModule.sol#L2

File: tapioca-periph-audit/contracts/Multicall/Multicall3.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Multicall/Multicall3.sol#L2

File: tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol

2:    pragma solidity ^0.8.9;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/ARBTriCryptoOracle.sol#L2

File: tapioca-periph-audit/contracts/oracle/implementations/SGOracle.sol

2:    pragma solidity ^0.8.9;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/implementations/SGOracle.sol#L2

File: tapioca-periph-audit/contracts/oracle/Seer.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/oracle/Seer.sol#L2

File: tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/CurveSwapper.sol#L2

File: tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV2Swapper.sol#L2

File: tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/Swapper/UniswapV3Swapper.sol#L2

File: tapioca-periph-audit/contracts/TapiocaDeployer/TapiocaDeployer.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-periph-audit/contracts/TapiocaDeployer/TapiocaDeployer.sol#L2

File: tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/aave/AaveStrategy.sol#L2

File: tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/balancer/BalancerStrategy.sol#L2

File: tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/compound/CompoundStrategy.sol#L2

File: tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/convex/ConvexTricryptoStrategy.sol#L2

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoLPStrategy.sol#L2

File: tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/curve/TricryptoNativeStrategy.sol#L2

File: tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/glp/GlpStrategy.sol#L2

File: tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/lido/LidoEthStrategy.sol#L2

File: tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/stargate/StargateStrategy.sol#L2

File: tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol

2:    pragma solidity ^0.8.18;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-yieldbox-strategies-audit/contracts/yearn/YearnStrategy.sol#L2

File: YieldBox/contracts/NativeTokenFactory.sol

2:    pragma solidity ^0.8.9;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/NativeTokenFactory.sol#L2

File: YieldBox/contracts/YieldBox.sol

24:   pragma solidity ^0.8.9;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L24

File: YieldBox/contracts/YieldBoxURIBuilder.sol

2:    pragma solidity ^0.8.9;

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxURIBuilder.sol#L2

[N‑41] Typos

There are 31 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

/// @audit repayed
262:      /// @return amount The total amount repayed.

/// @audit Mininal
332:      /// @param minAmountOut Mininal collateral amount to receive

/// @audit Mininal
380:      /// @param minAmountOut Mininal proceeds required for the sale

/// @audit necessar
657:      /// @param swapData Swap necessar data

/// @audit acrrued
730:          uint256 toWithdraw = (amount - part); //acrrued

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L262

File: tapioca-bar-audit/contracts/markets/Market.sol

/// @audit repayed
50:       /// @dev elastic = Total token amount to be repayed by borrowers, base = Total parts of the debt held by borrowers

/// @audit costant
82:       uint256 internal EXCHANGE_RATE_PRECISION; //not costant, but can only be set in the 'init' method

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L50

File: tapioca-bar-audit/contracts/markets/singularity/SGLBorrow.sol

/// @audit repayed
44:       /// @return amount The total amount repayed.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLBorrow.sol#L44

File: tapioca-bar-audit/contracts/markets/singularity/SGLLeverage.sol

/// @audit Mininal
93:       /// @param minAmountOut Mininal proceeds required for the sale

/// @audit Mininal
143:      /// @param minAmountOut Mininal collateral amount to receive

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLeverage.sol#L93

File: tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol

/// @audit necessar
375:      /// @param swapData Swap necessar data

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L375

File: tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol

/// @audit repayed
110:      /// @notice event emitted when asset is repayed

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLStorage.sol#L110

File: tapioca-bar-audit/contracts/markets/singularity/Singularity.sol

/// @audit repayed
295:      /// @return amount The total amount repayed.

/// @audit Mininal
318:      /// @param minAmountOut Mininal proceeds required for the sale

/// @audit Mininal
347:      /// @param minAmountOut Mininal collateral amount to receive

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L295

File: tapioca-bar-audit/contracts/usd0/BaseUSDO.sol

/// @audit transer
183:      /// @param lzData data needed for the cross chain transer

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDO.sol#L183

File: tapiocaz-audit/contracts/Balancer.sol

/// @audit registeres
214:      /// @notice registeres mTapiocaOFT for rebalancing

/// @audit assings
246:      /// @notice assings more rebalanceable amount for TOFT

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/Balancer.sol#L214

File: tapiocaz-audit/contracts/tOFT/BaseTOFT.sol

/// @audit transer
124:      /// @param lzData data needed for the cross chain transer

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/BaseTOFT.sol#L124

File: tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol

/// @audit reigstered
26:       /// @notice event emitted when a connected chain is reigstered or unregistered

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapiocaz-audit/contracts/tOFT/mTapiocaOFT.sol#L26

File: tap-token-audit/contracts/twAML.sol

/// @audit precoditions
100:          // correct result modulo 2**256. Since the precoditions guarantee

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tap-token-audit/contracts/twAML.sol#L100

File: YieldBox/contracts/YieldBoxRebase.sol

/// @audit reseting
24:           // To prevent reseting the ratio due to withdrawal of all shares, we start with

/// @audit Calculte
31:           // Calculte the shares using te current amount to share ratio

/// @audit reseting
47:           // To prevent reseting the ratio due to withdrawal of all shares, we start with

/// @audit Calculte
54:           // Calculte the amount using te current amount to share ratio

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBoxRebase.sol#L24

File: YieldBox/contracts/YieldBox.sol

/// @audit repesented
117:      /// @return shareOut The deposited amount repesented in shares.

/// @audit repesented
167:      /// @return shareOut The deposited amount repesented in shares.

/// @audit repesented
195:      /// @return shareOut The deposited amount repesented in shares.

/// @audit regierestered
421:      /// @param assetId The regierestered asset id

/// @audit repesented
476:      /// @return shareOut The deposited amount repesented in shares.

/// @audit repesented
499:      /// @return shareOut The deposited amount repesented in shares.

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/YieldBox/contracts/YieldBox.sol#L117

[N‑42] NatSpec @param is missing

There are 329 instances of this issue:

see instances
File: tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol

/// @audit Missing: '@param data'
100       /// @notice The init function that acts as a constructor
101:      function init(bytes calldata data) external onlyOnce {

/// @audit Missing: '@param operator'
225       /// @notice allows 'operator' to act on behalf of the sender
226       /// @param status true/false
227:      function updateOperator(address operator, bool status) external {

/// @audit Missing: '@param bool'
257       /// @notice Repays a loan.
258       /// @dev The bool param is not used but we added it to respect the ISingularity interface for MarketsHelper compatibility
259       /// @param from Address to repay from.
260       /// @param to Address of the user this payment should go.
261       /// @param part The amount to repay. See `userBorrowPart`.
262       /// @return amount The total amount repayed.
263       function repay(
264           address from,
265           address to,
266           bool,
267           uint256 part
268:      ) public notPaused allowedBorrow(from, part) returns (uint256 amount) {

/// @audit Missing: '@param amount'
276       /// @notice Adds `collateral` from msg.sender to the account `to`.
277       /// @param from Account to transfer shares from.
278       /// @param to The receiver of the tokens.
279       /// @param skim True if the amount should be skimmed from the deposit balance of msg.sender.
280       /// False if tokens from msg.sender in `yieldBox` should be transferred.
281       /// @param share The amount of shares to add for `to`.
282       function addCollateral(
283           address from,
284           address to,
285           bool skim,
286           uint256 amount,
287           uint256 share
288:      ) public allowedBorrow(from, share) notPaused {

/// @audit Missing: '@param address'
441       /// @notice Transfers fees to penrose
442       function refreshPenroseFees(
443           address
444:      ) external onlyOwner notPaused returns (uint256 feeShares) {

/// @audit Missing: '@param _minDebtRate'
/// @audit Missing: '@param _maxDebtRate'
/// @audit Missing: '@param _debtRateAgainstEthMarket'
/// @audit Missing: '@param _liquidationMultiplier'
464       /// @notice sets BigBang specific configuration
465       /// @dev values are updated only if > 0 or not address(0)
466       function setBigBangConfig(
467           uint256 _minDebtRate,
468           uint256 _maxDebtRate,
469           uint256 _debtRateAgainstEthMarket,
470           uint256 _liquidationMultiplier
471:      ) external onlyOwner {

/// @audit Missing: '@param _exchangeRate'
652       /// @notice Handles the liquidation of users' balances, once the users' amount of collateral is too low.
653       /// @dev Closed liquidations Only, 90% of extra shares goes to caller and 10% to protocol
654       /// @param users An array of user addresses.
655       /// @param maxBorrowParts A one-to-one mapping to `users`, contains maximum (partial) borrow amounts (to liquidate) of the respective user.
656       /// @param swapper Contract address of the `MultiSwapper` implementation. See `setSwapper`.
657       /// @param swapData Swap necessar data
658       function _closedLiquidation(
659           address[] calldata users,
660           uint256[] calldata maxBorrowParts,
661           ISwapper swapper,
662           uint256 _exchangeRate,
663:          bytes calldata swapData

/// @audit Missing: '@param from'
/// @audit Missing: '@param to'
/// @audit Missing: '@param share'
708       /// @dev Concrete implementation of `removeCollateral`.
709       function _removeCollateral(
710           address from,
711           address to,
712:          uint256 share

/// @audit Missing: '@param from'
/// @audit Missing: '@param to'
/// @audit Missing: '@param part'
720       /// @dev Concrete implementation of `repay`.
721       function _repay(
722           address from,
723           address to,
724           uint256 part
725:      ) internal returns (uint256 amount) {

/// @audit Missing: '@param from'
/// @audit Missing: '@param to'
/// @audit Missing: '@param amount'
741       /// @dev Concrete implementation of `borrow`.
742       function _borrow(
743           address from,
744           address to,
745           uint256 amount
746:      ) internal returns (uint256 part, uint256 share) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/bigBang/BigBang.sol#L100-L101

File: tapioca-bar-audit/contracts/markets/MarketERC20.sol

/// @audit Missing: '@param from'
/// @audit Missing: '@param share'
72        // ***************** //
73        // *** MODIFIERS *** //
74        // ***************** //
75:       function _allowedLend(address from, uint share) internal {

/// @audit Missing: '@param name'
104       /**
105        * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`.
106        *
107        * It's a good idea to use the same `name` that is defined as the ERC20 token name.
108        */
109:      constructor(string memory name) EIP712(name, "1") {}

/// @audit Missing: '@param owner'
/// @audit Missing: '@param spender'
/// @audit Missing: '@param value'
/// @audit Missing: '@param deadline'
/// @audit Missing: '@param v'
/// @audit Missing: '@param r'
/// @audit Missing: '@param s'
209       /**
210        * @dev See {IERC20Permit-permit}.
211        */
212       function permit(
213           address owner,
214           address spender,
215           uint256 value,
216           uint256 deadline,
217           uint8 v,
218           bytes32 r,
219:          bytes32 s

/// @audit Missing: '@param owner'
240       /**
241        * @dev "Consume a nonce": return the current value and increment.
242        *
243        * _Available since v4.1._
244        */
245       function _useNonce(
246           address owner
247:      ) internal virtual returns (uint256 current) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/MarketERC20.sol#L72-L75

File: tapioca-bar-audit/contracts/markets/Market.sol

/// @audit Missing: '@param _borrowOpeningFee'
/// @audit Missing: '@param _oracle'
/// @audit Missing: '@param _oracleData'
/// @audit Missing: '@param _conservator'
/// @audit Missing: '@param _callerFee'
/// @audit Missing: '@param _protocolFee'
/// @audit Missing: '@param _liquidationBonusAmount'
/// @audit Missing: '@param _minLiquidatorReward'
/// @audit Missing: '@param _maxLiquidatorReward'
/// @audit Missing: '@param _totalBorrowCap'
/// @audit Missing: '@param _collateralizationRate'
156       /// @notice sets common market configuration
157       /// @dev values are updated only if > 0 or not address(0)
158       function setMarketConfig(
159           uint256 _borrowOpeningFee,
160           IOracle _oracle,
161           bytes calldata _oracleData,
162           address _conservator,
163           uint256 _callerFee,
164           uint256 _protocolFee,
165           uint256 _liquidationBonusAmount,
166           uint256 _minLiquidatorReward,
167           uint256 _maxLiquidatorReward,
168           uint256 _totalBorrowCap,
169           uint256 _collateralizationRate
170:      ) external onlyOwner {

/// @audit Missing: '@param borrowPart'
/// @audit Missing: '@param collateralPartInAsset'
/// @audit Missing: '@param borrowPartDecimals'
/// @audit Missing: '@param collateralPartDecimals'
/// @audit Missing: '@param ratesPrecision'
252       // ********************** //
253       // *** VIEW FUNCTIONS *** //
254       // ********************** //
255       /// @notice returns the maximum liquidatable amount for user
256       function computeClosingFactor(
257           uint256 borrowPart,
258           uint256 collateralPartInAsset,
259           uint256 borrowPartDecimals,
260           uint256 collateralPartDecimals,
261           uint256 ratesPrecision
262:      ) public view returns (uint256) {

/// @audit Missing: '@param user'
353       /// @notice computes the possible liquidator reward
354       /// @notice user the user for which a liquidation operation should be performed
355       /// @param _exchangeRate the exchange rate asset/collateral to use for internal computations
356       function computeLiquidatorReward(
357           address user,
358           uint256 _exchangeRate
359:      ) public view returns (uint256) {

/// @audit Missing: '@param user'
400       /// @notice Concrete implementation of `isSolvent`. Includes a parameter to allow caching `exchangeRate`.
401       /// @param _exchangeRate The exchange rate. Used to cache the `exchangeRate` between calls.
402       function _isSolvent(
403           address user,
404           uint256 _exchangeRate
405:      ) internal view returns (bool) {

/// @audit Missing: '@param collateralShare'
/// @audit Missing: '@param _exchangeRate'
427       /// @notice Returns the min and max LTV for user in asset price
428       function _computeMaxAndMinLTVInAsset(
429           uint256 collateralShare,
430           uint256 _exchangeRate
431:      ) internal view returns (uint256 min, uint256 max) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/Market.sol#L156-L170

File: tapioca-bar-audit/contracts/markets/singularity/SGLCollateral.sol

/// @audit Missing: '@param amount'
12        // ************************ //
13        // *** PUBLIC FUNCTIONS *** //
14        // ************************ //
15        /// @notice Adds `collateral` from msg.sender to the account `to`.
16        /// @param from Account to transfer shares from.
17        /// @param to The receiver of the tokens.
18        /// @param skim True if the amount should be skimmed from the deposit balance of msg.sender.
19        /// False if tokens from msg.sender in `yieldBox` should be transferred.
20        /// @param share The amount of shares to add for `to`.
21        function addCollateral(
22            address from,
23            address to,
24            bool skim,
25            uint256 amount,
26            uint256 share
27:       ) public notPaused allowedBorrow(from, share) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCollateral.sol#L12-L27

File: tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol

/// @audit Missing: '@param from'
/// @audit Missing: '@param to'
/// @audit Missing: '@param skim'
/// @audit Missing: '@param share'
196       /// @dev Concrete implementation of `addAsset`.
197       function _addAsset(
198           address from,
199           address to,
200           bool skim,
201           uint256 share
202:      ) internal returns (uint256 fraction) {

/// @audit Missing: '@param to'
/// @audit Missing: '@param fraction'
/// @audit Missing: '@param updateYieldBoxShares'
221       /// @dev Concrete implementation of `removeAsset`.
222       /// @param from The account to remove from. Should always be msg.sender except for `depositFeesToyieldBox()`.
223       function _removeAsset(
224           address from,
225           address to,
226           uint256 fraction,
227           bool updateYieldBoxShares
228:      ) internal returns (uint256 share) {

/// @audit Missing: '@param borrowPart'
253       /// @dev Return the equivalent of collateral borrow part in asset amount.
254       function _getAmountForBorrowPart(
255           uint256 borrowPart
256:      ) internal view returns (uint256) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLCommon.sol#L196-L202

File: tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol

/// @audit Missing: '@param from'
/// @audit Missing: '@param to'
/// @audit Missing: '@param skim'
/// @audit Missing: '@param amount'
/// @audit Missing: '@param share'
12        // ************************** //
13        // *** PRIVATE FUNCTIONS *** //
14        // ************************* //
15        /// @dev Concrete implementation of `addCollateral`.
16        function _addCollateral(
17            address from,
18            address to,
19            bool skim,
20            uint256 amount,
21:           uint256 share

/// @audit Missing: '@param from'
/// @audit Missing: '@param to'
/// @audit Missing: '@param share'
40        /// @dev Concrete implementation of `removeCollateral`.
41        function _removeCollateral(
42            address from,
43            address to,
44:           uint256 share

/// @audit Missing: '@param from'
/// @audit Missing: '@param to'
/// @audit Missing: '@param amount'
57        /// @dev Concrete implementation of `borrow`.
58        function _borrow(
59            address from,
60            address to,
61            uint256 amount
62:       ) internal returns (uint256 part, uint256 share) {

/// @audit Missing: '@param from'
/// @audit Missing: '@param to'
/// @audit Missing: '@param skim'
/// @audit Missing: '@param part'
82        /// @dev Concrete implementation of `repay`.
83        function _repay(
84            address from,
85            address to,
86            bool skim,
87            uint256 part
88:       ) internal returns (uint256 amount) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLendingCommon.sol#L12-L21

File: tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol

/// @audit Missing: '@param user'
/// @audit Missing: '@param _exchangeRate'
67        // ************************* //
68        // *** PRIVATE FUNCTIONS *** //
69        // ************************* //
70        function _computeAssetAmountToSolvency(
71            address user,
72            uint256 _exchangeRate
73:       ) private view returns (uint256) {

/// @audit Missing: '@param _exchangeRate'
370       /// @notice Handles the liquidation of users' balances, once the users' amount of collateral is too low.
371       /// @dev Closed liquidations Only, 90% of extra shares goes to caller and 10% to protocol
372       /// @param users An array of user addresses.
373       /// @param maxBorrowParts A one-to-one mapping to `users`, contains maximum (partial) borrow amounts (to liquidate) of the respective user.
374       /// @param swapper Contract address of the `MultiSwapper` implementation. See `setSwapper`.
375       /// @param swapData Swap necessar data
376       function _closedLiquidation(
377           address[] calldata users,
378           uint256[] calldata maxBorrowParts,
379           ISwapper swapper,
380           uint256 _exchangeRate,
381:          bytes calldata swapData

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/SGLLiquidation.sol#L67-L73

File: tapioca-bar-audit/contracts/markets/singularity/Singularity.sol

/// @audit Missing: '@param data'
61        /// @notice The init function that acts as a constructor
62:       function init(bytes calldata data) external onlyOnce {

/// @audit Missing: '@param amount'
229       /// @notice Adds `collateral` from msg.sender to the account `to`.
230       /// @param from Account to transfer shares from.
231       /// @param to The receiver of the tokens.
232       /// @param skim True if the amount should be skimmed from the deposit balance of msg.sender.
233       /// False if tokens from msg.sender in `yieldBox` should be transferred.
234       /// @param share The amount of shares to add for `to`.
235       function addCollateral(
236           address from,
237           address to,
238           bool skim,
239           uint256 amount,
240:          uint256 share

/// @audit Missing: '@param _lqCollateralizationRate'
/// @audit Missing: '@param _liquidationMultiplier'
/// @audit Missing: '@param _minimumTargetUtilization'
/// @audit Missing: '@param _maximumTargetUtilization'
/// @audit Missing: '@param _minimumInterestPerSecond'
/// @audit Missing: '@param _maximumInterestPerSecond'
/// @audit Missing: '@param _interestElasticity'
487       /// @notice sets Singularity specific configuration
488       /// @dev values are updated only if > 0 or not address(0)
489       function setSingularityConfig(
490           uint256 _lqCollateralizationRate,
491           uint256 _liquidationMultiplier,
492           uint256 _minimumTargetUtilization,
493           uint256 _maximumTargetUtilization,
494           uint64 _minimumInterestPerSecond,
495           uint64 _maximumInterestPerSecond,
496           uint256 _interestElasticity
497:      ) external onlyOwner {

/// @audit Missing: '@param _liquidationQueue'
/// @audit Missing: '@param _bidExecutionSwapper'
/// @audit Missing: '@param _usdoSwapper'
575       /// @notice sets LQ specific confinguration
576       function setLiquidationQueueConfig(
577           ILiquidationQueue _liquidationQueue,
578           address _bidExecutionSwapper,
579           address _usdoSwapper
580:      ) external onlyOwner {

/// @audit Missing: '@param _module'
597       // ************************* //
598       // *** PRIVATE FUNCTIONS *** //
599       // ************************* //
600:      function _extractModule(Module _module) private view returns (address) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/markets/singularity/Singularity.sol#L61-L62

File: tapioca-bar-audit/contracts/Penrose.sol

/// @audit Missing: '@param _market'
261       /// @notice sets the main BigBang market
262       /// @dev needed for the variable debt computation
263:      function setBigBangEthMarket(address _market) external onlyOwner {

/// @audit Missing: '@param _contract'
378       /// @notice Registers an existing Singularity market (without deployment)
379       /// @dev can only be called by the owner
380       /// @param mc The address of the master contract which must be already registered
381       function addSingularity(
382           address mc,
383           address _contract
384:      ) external onlyOwner registeredSingularityMasterContract(mc) {

/// @audit Missing: '@param _contract'
411       /// @notice Registers an existing BigBang market (without deployment)
412       /// @dev can only be called by the owner
413       /// @param mc The address of the master contract which must be already registered
414       function addBigBang(
415           address mc,
416           address _contract
417:      ) external onlyOwner registeredBigBangMasterContract(mc) {

/// @audit Missing: '@param mc'
/// @audit Missing: '@param data'
/// @audit Missing: '@param forceSuccess'
423       /// @notice Execute an only owner function inside of a Singularity or a BigBang market
424       function executeMarketFn(
425           address[] calldata mc,
426           bytes[] memory data,
427           bool forceSuccess
428       )
429           external
430           onlyOwner
431           notPaused
432:          returns (bool[] memory success, bytes[] memory result)

/// @audit Missing: '@param _returnData'
469       // ************************* //
470       // *** PRIVATE FUNCTIONS *** //
471       // ************************* //
472       function _getRevertMsg(
473           bytes memory _returnData
474:      ) private pure returns (string memory) {

/// @audit Missing: '@param market'
/// @audit Missing: '@param swapper'
/// @audit Missing: '@param dexData'
499       /// @notice Withdraw the balance of `feeTo`, swap asset into TAP and deposit it to yieldBox of `feeTo`
500       function _depositFeesToYieldBox(
501           IMarket market,
502           ISwapper swapper,
503:          IPenrose.SwapData calldata dexData

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/Penrose.sol#L261-L263

File: tapioca-bar-audit/contracts/usd0/BaseUSDO.sol

/// @audit Missing: '@param airdropAdapterParams'
207       /// @notice inits multiHopBuyCollateral
208       /// @param from The user who sells
209       /// @param collateralAmount Extra collateral to be added
210       /// @param borrowAmount Borrowed amount that will be swapped into collateral
211       /// @param swapData Swap data used on destination chain for swapping USDO to the underlying TOFT token
212       /// @param lzData LayerZero specific data
213       /// @param externalData External contracts used for the cross chain operation
214       /// @param approvals array
215       function initMultiHopBuy(
216           address from,
217           uint256 collateralAmount,
218           uint256 borrowAmount,
219           IUSDOBase.ILeverageSwapData calldata swapData,
220           IUSDOBase.ILeverageLZData calldata lzData,
221           IUSDOBase.ILeverageExternalContractsData calldata externalData,
222           bytes calldata airdropAdapterParams,
223:          ICommonData.IApproval[] memory approvals

/// @audit Missing: '@param zroPaymentAddress'
305       /// @notice sends to YieldBox over layer and lends asset to market
306       /// @param _from sending address
307       /// @param _to receiver address
308       /// @param lzDstChainId LayerZero destination chain id
309       /// @param lendParams lend specific params
310       /// @param approvals approvals specific params
311       /// @param withdrawParams parameter to withdraw the SGL collateral
312       /// @param adapterParams adapter params of the withdrawn collateral
313       function sendAndLendOrRepay(
314           address _from,
315           address _to,
316           uint16 lzDstChainId,
317           address zroPaymentAddress,
318           IUSDOBase.ILendOrRepayParams calldata lendParams,
319           ICommonData.IApproval[] calldata approvals,
320           ICommonData.IWithdrawParams calldata withdrawParams,
321:          bytes calldata adapterParams

/// @audit Missing: '@param _module'
340       // ************************* //
341       // *** PRIVATE FUNCTIONS *** //
342       // ************************* //
343   
344:      function _extractModule(Module _module) private view returns (address) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/BaseUSDO.sol#L207-L223

File: tapioca-bar-audit/contracts/usd0/USDO.sol

/// @audit Missing: '@param _marketModule'
/// @audit Missing: '@param _optionsModule'
30        /// @notice creates a new USDO0 OFT contract
31        /// @param _lzEndpoint LayerZero endpoint
32        /// @param _yieldBox the YieldBox address
33        /// @param _owner owner address
34        /// @param _leverageModule USDOLeverageModule address
35        constructor(
36            address _lzEndpoint,
37            IYieldBoxBase _yieldBox,
38            address _owner,
39            address payable _leverageModule,
40            address payable _marketModule,
41            address payable _optionsModule
42        )
43            BaseUSDO(
44                _lzEndpoint,
45                _yieldBox,
46                _owner,
47                _leverageModule,
48                _marketModule,
49                _optionsModule
50:           )

/// @audit Missing: '@param address'
53        // ********************** //
54        // *** VIEW FUNCTIONS *** //
55        // ********************** //
56        /// @notice returns the maximum amount of tokens available for a flash mint
57:       function maxFlashLoan(address) public view override returns (uint256) {

https://github.com/code-423n4/2023-07-tapioca/blob/e6eef060495b31173578570215e80f9e95330b9a/tapioca-bar-audit/contracts/usd0/USDO.sol#L30-L50

File: tapiocaz-audit/contracts/Balancer.sol

/// @audit Missing: '@param _srcOft'
/// @audit Missing: '@param _dstChainId'
133       // ************************ //
134       // *** PUBLIC FUNCTIONS *** //
135       // ************************ //
136   
137       function checker(
138           address payable _srcOft,
139           uint16 _dstChainId
140:      ) external view returns (bool canExec, bytes memory execPayload) {

/// @audit Missing: '@param _srcOft'
/// @audit Missing: '@param _dstOft'
/// @audit Missing: '@param _dstChainId'
264       // ************************* //
265       // *** PRIVATE FUNCTIONS *** //
266       // ***********************