Skip to content

Latest commit

 

History

History
4452 lines (2741 loc) · 240 KB

bot-report.md

File metadata and controls

4452 lines (2741 loc) · 240 KB

Winning bot race submission

This is the top-ranked automated findings report, from henry bot. All findings in this report will be considered known issues for the purposes of your C4 audit.

Summary

Issue Instances Gas Savings
[M‑01] Centralization risk for privileged functions 5 0
Issue Instances Gas Savings
- :- :-: :-:
[L‑01] Use increaseAllowance()/decreaseAllowance() instead of approve()/safeApprove() 1 0
[L‑02] Use of tx.origin is unsafe in almost every context 2 0
[L‑03] Variables shadowing other definitions 4 0
[L‑04] Missing zero address check in constructor 3 0
[L‑05] Solidity version 0.8.20 or above may not work on other chains due to PUSH0 2 0
[L‑06] Using >/>= without specifying an upper bound in version pragma is unsafe 2 0
[L‑07] Tokens may be minted to the zero address 1 0
[L‑08] Consider implementing two-step procedure for updating protocol addresses 2 0
[L‑09] Vulnerable versions of packages are being used 1 0
[L‑10] Missing checks for address(0) when setting address state variables 3 0
[L‑11] Owner can renounce Ownership 3 0
[L‑12] Constructor / initialization function lacks parameter validation 1 0
[L‑13] Contracts are vulnerable to fee-on-transfer accounting-related issues 13 0
[L‑14] Functions calling contracts/addresses with transfer hooks should be protected by reentrancy guard 13 0
[L‑15] Critical functions should be controlled by time locks 2 0
[L‑16] The safeApprove() function is deprecated 1 0
[L‑17] Some tokens may revert when zero value transfers are made 9 0
[L‑18] Loss of precision in divisions 1 0
[L‑19] Code does not follow the best practice of check-effects-interaction 10 0
[L‑20] Some tokens may revert when large transfers are made 13 0
[L‑21] Contracts are vulnerable to rebasing accounting-related issues 9 0
Issue Instances Gas Savings
- :- :-: :-:
[G‑01] Using private for constants saves gas 3 10218
[G‑02] Constructors can be marked as payable to save deployment gas 4 84
[G‑03] Using ++X/--X instead of X++/X-- can save gas 1 5
[G‑04] Use custom errors rather than revert()/require() strings to save gas 12 600
[G‑05] Do not cache state variables that are used only once 4 12
[G‑06] Inline modifiers that are only used once to save gas 1 0
[G‑07] Functions that revert when called by normal users can be marked payable 6 126
[G‑08] Use x = x + y instead of x += y for state variables 1 10
[G‑09] Operator >=/<= costs less gas than operator >/< 6 18
[G‑10] Unused non-constant state variables waste gas 1 0
[G‑11] Usage of ints/uints smaller than 32 bytes incurs overhead 1 55
[G‑12] Divisions can be unchecked to save gas 8 160
[G‑13] Increments can be unchecked to save gas 1 60
[G‑14] Use assembly to validate msg.sender 3 36
[G‑15] Using assembly to check for zero can save gas 5 30
[G‑16] Avoid contract existence checks by using low level calls 8 800
[G‑17] Use uint256(1)/uint256(2) instead of true/false to save gas for changes 4 68400
[G‑18] Avoid zero transfer to save gas 9 900
[G‑19] Optimize names to save gas 4 88
[G‑20] Reduce gas usage by moving to Solidity 0.8.19 or later 2 0
[G‑21] Newer versions of solidity are more gas efficient 4 0
[G‑22] Avoid updating storage when the value hasn't changed 5 4000
[G‑23] State variables that are used multiple times in a function should be cached in stack variables 4 1164
[G‑24] Contracts can use fewer storage slots by truncating state variables 1 20000
[G‑25] Refactor duplicated require()/revert() checks to save gas 1 0
[G‑26] Use assembly to emit events 9 342
[G‑27] Use calldata instead of memory for immutable arguments 2 1200
[G‑28] Using bools for storage incurs overhead 4 400
[G‑29] Multiple accesses of the same mapping/array key/index should be cached 13 924
[G‑30] Multiple mappings can be replaced with a single struct mapping 4 168
Issue Instances Gas Savings
- :- :-: :-:
[N‑01] NatSpec documentation for contract is missing 4 0
[N‑02] Names of private/internal functions should be prefixed with an underscore 1 0
[N‑03] Order of functions does not follow the Solidity Style Guide 13 0
[N‑04] Use of override is unnecessary 2 0
[N‑05] Custom errors should be used rather than revert()/require() 12 0
[N‑06] Large numeric literals should use underscores for readability 6 0
[N‑07] Assembly blocks should have extensive comments 1 0
[N‑08] Simplify complex require statements 1 0
[N‑09] Consider moving msg.sender checks to modifiers 2 0
[N‑10] Consider adding a block/deny-list 2 0
[N‑11] Constants/Immutables redefined elsewhere 2 0
[N‑12] Convert simple if-statements to ternary expressions 1 0
[N‑13] Events should be emitted before external calls 8 0
[N‑14] Events are emitted without the sender information 3 0
[N‑15] Event is missing indexed fields 3 0
[N‑16] Imports could be organized more systematically 4 0
[N‑17] @openzeppelin/contracts should be upgraded to a newer version 6 0
[N‑18] Lines are too long 11 0
[N‑19] Magic numbers should be replaced with constants 14 0
[N‑20] Memory-safe annotation preferred over comment variant 1 0
[N‑21] Use @inheritdoc for overridden functions 2 0
[N‑22] Contracts should have NatSpec @author tags 4 0
[N‑23] Contracts should have @notice tags 4 0
[N‑24] Contracts should have NatSpec @title tags 4 0
[N‑25] Events missing NatSpec @param tag 12 0
[N‑26] Event declarations should have NatSpec descriptions 12 0
[N‑27] Functions missing NatSpec @param tag 7 0
[N‑28] NatSpec documentation for function is missing 5 0
[N‑29] Functions missing NatSpec @return tag 9 0
[N‑30] State variables should have NatSpec descriptions 6 0
[N‑31] Contract name does not follow the Solidity Style Guide 2 0
[N‑32] Functions should be named in mixedCase style 3 0
[N‑33] Variable names for immutables should use UPPER_CASE_WITH_UNDERSCORES 4 0
[N‑34] Missing zero address check in functions with address parameters 3 0
[N‑35] Constants should be put on the left side of comparisons 11 0
[N‑36] Large multiples of ten should use scientific notation 4 0
[N‑37] Non-interface files should use fixed compiler versions 2 0
[N‑38] Unused contract variables 1 0
[N‑39] Unused import 1 0
[N‑40] Consider using delete rather than assigning zero to clear values 2 0
[N‑41] Use the latest Solidity version 4 0
[N‑42] Named mappings are recommended 10 0
[N‑43] Whitespace in Expressions 1 0
[N‑44] Modifier declarations should have NatSpec descriptions 1 0
[N‑45] Contract functions should use an interface 18 0
[N‑46] Addresses shouldn't be hard-coded 3 0
[N‑47] Multiple mappings with same keys can be combined into a single struct mapping for readability 4 0
[N‑48] Control structures do not follow the Solidity Style Guide 1 0
[N‑49] Do not cache immutable variables 2 0
[N‑50] Missing event for critical changes 1 0
[N‑51] Duplicated require()/revert() checks should be refactored 1 0
[N‑52] Consider adding emergency-stop functionality 3 0
[N‑53] Avoid the use of sensitive terms 23 0
[N‑54] Contracts should have NatSpec @dev tags 4 0
[N‑55] Missing NatSpec @dev from event declaration 12 0
[N‑56] Missing NatSpec @notice from event declaration 12 0
[N‑57] Missing NatSpec @dev from function declaration 23 0
[N‑58] Missing NatSpec @notice from function declaration 5 0
[N‑59] Missing NatSpec @dev from modifier declaration 1 0
[N‑60] Missing NatSpec @notice from modifier declaration 1 0
[N‑61] Contracts should have full test coverage 1 0
[N‑62] Large or complicated code bases should implement invariant tests 1 0
[N‑63] Top-level declarations should be separated by at least two lines 12 0
[N‑64] Consider adding formal verification proofs 4 1000
[N‑65] Error messages should be descriptive, not cryptic 6 18
Issue Instances Gas Savings
- :- :-: :-:
[D‑01] Using private rather than public for constants, saves gas 4 0
[D‑02] Event names should use CamelCase 12 0
[D‑03] Avoid double casting 1 0
[D‑04] Event is missing indexed fields 1 0
[D‑05] internal functions only called once can be inlined to save gas 1 30
[D‑06] Variables should be named in mixedCase style 1 0
[D‑07] safeMint should be used in place of mint 3 0
[D‑08] x += y is more expensive than x = x + y for state variables 12 0
[D‑09] Revert on transfer to the zero address 13 0
[D‑10] SafeTransferLib does not ensure that the token contract exists 14 0
[D‑11] Solidity version 0.8.20 or above may not work on other chains due to PUSH0 2 0
[D‑12] SPDX identifier should be the in the first line of a solidity file 4 0
[D‑13] Numbers downcast to addresses may result in collisions 8 0
[D‑14] Unused named return 1 0
[D‑15] Unused named return variables without optimizer waste gas 1 9
[D‑16] Using bitmap to store bool states can save gas 3 0
[D‑17] Using delete statement can save gas 2 16
[D‑18] Use != 0 or == 0 for unsigned integer comparison 4 0
[D‑19] Avoid contract existence checks by using low level calls 6 0
[D‑20] Use Ownable2Step instead of Ownable 3 0
[D‑21] Events that mark critical parameter changes should contain both the old and the new value 1 0
[D‑22] safeTransfer function does not check for contract existence 4 0
[D‑23] Assembly block creates dirty bits 1 0
[D‑24] require() or revert() statements that check input arguments should be at the top of the function 4 0
[D‑25] Division by zero not prevented 1 0
[D‑26] Inconsistent spacing in comments 4 0
[D‑27] Consider activating via-ir for deploying 1 0
[D‑28] Enable IR-based code generation 1 0
[D‑29] Large approvals may not work with some ERC20 tokens 1 0
[D‑30] Contracts are vulnerable to rebasing accounting-related issues 1 0
Audit report generated by Bot-Henry. ### Medium Risk Issues

[M‑01] Centralization risk for privileged functions

Contracts with privileged functions need owner/admin to be trusted not to perform malicious updates or drain funds. This may also cause a single point failure.

There are 5 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}104:     function changeBondingCurveAllowed(address _bondingCurve, bool _newState) external onlyOwner {

244:     function claimPlatformFee() external onlyOwner {

300:     function restrictShareCreation(bool _isRestricted) external onlyOwner {

309:     function changeShareCreatorWhitelist(address _address, bool _isWhitelisted) external onlyOwner {

GitHub : 104,244,300,309

File: asD/src/asD.sol

}72:     function withdrawCarry(uint256 _amount) external onlyOwner {

GitHub : 72### Low Risk Issues

[L‑01] Use increaseAllowance()/decreaseAllowance() instead of approve()/safeApprove()

Changing an allowance with approve() brings the risk that someone may use both the old and the new allowance by unfortunate transaction ordering. Refer to ERC20 API: An Attack Vector on the Approve/TransferFrom Methods. It is recommended to use the increaseAllowance()/decreaseAllowance() to avoid ths problem.

There are 1 instance(s) of this issue:

File: asD/src/asD.sol

}51:         SafeERC20.safeApprove(note, cNote, _amount);

GitHub : 51

[L‑02] Use of tx.origin is unsafe in almost every context

According to Vitalik Buterin, contracts should not assume that tx.origin will continue to be usable or meaningful. An example of this is EIP-3074 which explicitly mentions the intention to change its semantics when it's used with new op codes. There have also been calls to remove tx.origin, and there are security issues associated with using it for authorization. For these reasons, it's best to completely avoid the feature.

There are 2 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}96:             turnstile.register(tx.origin);

GitHub : 96

File: asD/src/asDFactory.sol

}29:             turnstile.register(tx.origin);

GitHub : 29

[L‑03] Variables shadowing other definitions

A variable declaration shadowing any other existing definition is error-prone. It can cause confusion for developers, potentially introduce bugs, and reduce the readability and maintainability.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit Shadows `state variable _uri`
91:     constructor(string memory _uri, address _paymentToken) ERC1155(_uri) Ownable() {

GitHub : 91

File: asD/src/asD.sol

}/// @audit Shadows `state variable _name`
29:         string memory _name,

/// @audit Shadows `state variable _symbol`
30:         string memory _symbol,

/// @audit Shadows `state variable _owner`
31:         address _owner,

GitHub : 29,30,31

[L‑04] Missing zero address check in constructor

Constructors often take address parameters to initialize important components of a contract, such as owner or linked contracts. However, without a checking, there's a risk that an address parameter could be mistakenly set to the zero address (0x0). This could be due to an error or oversight during contract deployment. A zero address in a crucial role can cause serious issues, as it cannot perform actions like a normal address, and any funds sent to it will be irretrievable. It's therefore crucial to include a zero address check in constructors to prevent such potential problems. If a zero address is detected, the constructor should revert the transaction.

There are 3 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit `_paymentToken not checked`
91:     constructor(string memory _uri, address _paymentToken) ERC1155(_uri) Ownable() {

GitHub : 91

File: asD/src/asD.sol

}/// @audit `_owner not checked`
/// @audit `_cNote not checked`
/// @audit `_csrRecipient not checked`
28:     constructor(
29:         string memory _name,
30:         string memory _symbol,
31:         address _owner,
32:         address _cNote,
33:         address _csrRecipient
34:     ) ERC20(_name, _symbol) {

GitHub : 28-34

File: asD/src/asDFactory.sol

}/// @audit `_cNote not checked`
24:     constructor(address _cNote) {

GitHub : 24

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

Solidity version 0.8.20 or above uses the new Shanghai EVM which introduces the PUSH0 opcode. This op code may not yet be implemented on all evm-chains or Layer2s, so deployment on these chains will fail. Consider using an earlier solidity version.

There are 2 instance(s) of this issue:

File: asD/src/asD.sol

}2: pragma solidity >=0.8.0;

GitHub : 2

File: asD/src/asDFactory.sol

}2: pragma solidity >=0.8.0;

GitHub : 2

[L‑06] Using >/>= without specifying an upper bound in version pragma is unsafe

There will be breaking changes in future versions of solidity, and at that point your code will no longer be compatible. While you may have the specific version to use in a configuration file, others that include your source files may not.

There are 2 instance(s) of this issue:

File: asD/src/asD.sol

}2: pragma solidity >=0.8.0;

GitHub : 2

File: asD/src/asDFactory.sol

}2: pragma solidity >=0.8.0;

GitHub : 2

[L‑07] Tokens may be minted to the zero address

The target address is not checked in the mint function.

There are 1 instance(s) of this issue:

File: asD/src/asD.sol

}47:     function mint(uint256 _amount) external {
48:         CErc20Interface cNoteToken = CErc20Interface(cNote);
49:         IERC20 note = IERC20(cNoteToken.underlying());
50:         SafeERC20.safeTransferFrom(note, msg.sender, address(this), _amount);
51:         SafeERC20.safeApprove(note, cNote, _amount);
52:         uint256 returnCode = cNoteToken.mint(_amount);
53:         // Mint returns 0 on success: https://docs.compound.finance/v2/ctokens/#mint
54:         require(returnCode == 0, "Error when minting");
55:         _mint(msg.sender, _amount);
56:     }

GitHub : 47-56

[L‑08] 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 2 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}104:     function changeBondingCurveAllowed(address _bondingCurve, bool _newState) external onlyOwner {
105:         require(whitelistedBondingCurves[_bondingCurve] != _newState, "State already set");
106:         whitelistedBondingCurves[_bondingCurve] = _newState;
107:         emit BondingCurveStateChange(_bondingCurve, _newState);
108:     }

309:     function changeShareCreatorWhitelist(address _address, bool _isWhitelisted) external onlyOwner {
310:         require(whitelistedShareCreators[_address] != _isWhitelisted, "State already set");
311:         whitelistedShareCreators[_address] = _isWhitelisted;
312:     }

GitHub : 104-108,309-312

[L‑09] Vulnerable versions of packages are being used

This project is using specific package versions which are vulnerable to the specific CVEs listed below. Consider switching to more recent versions of these packages that don't have these vulnerabilities.

  • CVE-2023-40014 - MEDIUM - (openzeppelin-solidity >=4.0.0 <4.9.3): OpenZeppelin Contracts is a library for secure smart contract development. Starting in version 4.0.0 and prior to version 4.9.3, contracts using ERC2771Context along with a custom trusted forwarder may see _msgSender return address(0) in calls that originate from the forwarder with calldata shorter than 20 bytes. This combination of circumstances does not appear to be common, in particular it is not the case for MinimalForwarder from OpenZeppelin Contracts, or any deployed forwarder the team is aware of, given that the signer address is appended to all calls that originate from these forwarders. The problem has been patched in v4.9.3.

  • CVE-2023-34459 - MEDIUM - (openzeppelin-solidity >=4.7.0 <4.9.2): OpenZeppelin Contracts is a library for smart contract development. Starting in version 4.7.0 and prior to version 4.9.2, when the verifyMultiProof, verifyMultiProofCalldata, procesprocessMultiProof, or processMultiProofCalldat functions are in use, it is possible to construct merkle trees that allow forging a valid multiproof for an arbitrary set of leaves. A contract may be vulnerable if it uses multiproofs for verification and the merkle tree that is processed includes a node with value 0 at depth 1 (just under the root). This could happen inadvertedly for balanced trees with 3 leaves or less, if the leaves are not hashed. This could happen deliberately if a malicious tree builder includes such a node in the tree. A contract is not vulnerable if it uses single-leaf proving (verify, verifyCalldata, processProof, or processProofCalldata), or if it uses multiproofs with a known tree that has hashed leaves. Standard merkle trees produced or validated with the @openzeppelin/merkle-tree library are safe. The problem has been patched in version 4.9.2. Some workarounds are available. For those using multiproofs: When constructing merkle trees hash the leaves and do not insert empty nodes in your trees. Using the @openzeppelin/merkle-tree package eliminates this issue. Do not accept user-provided merkle roots without reconstructing at least the first level of the tree. Verify the merkle tree structure by reconstructing it from the leaves.

There are 1 instance(s) of this issue:

/// @audit Global finding.

GitHub : 0

[L‑10] Missing checks for address(0) when setting address state variables

Consider adding a zero address check when setting address state variables.

There are 3 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}92:         token = IERC20(_paymentToken);

GitHub : 92

File: asD/src/asD.sol

}36:         cNote = _cNote;

GitHub : 36

File: asD/src/asDFactory.sol

}25:         cNote = _cNote;

GitHub : 25

[L‑11] Owner can renounce Ownership

Each of the following contracts implements or inherits the renounceOwnership() function. This can represent a certain risk if the ownership is renounced for any other reason than by design. Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.

There are 3 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}10: contract Market is ERC1155, Ownable2Step {
11:     /*//////////////////////////////////////////////////////////////
12:                                  CONSTANTS
13:     //////////////////////////////////////////////////////////////*/

GitHub : 10-13

File: asD/src/asD.sol

}11: contract asD is ERC20, Ownable2Step {
12:     /*//////////////////////////////////////////////////////////////
13:                                  STATE
14:     //////////////////////////////////////////////////////////////*/

GitHub : 11-14

File: asD/src/asDFactory.sol

}8: contract asDFactory is Ownable2Step {
9:     /*//////////////////////////////////////////////////////////////
10:                                  STATE
11:     //////////////////////////////////////////////////////////////*/

GitHub : 8-11

[L‑12] Constructor / initialization function lacks parameter validation

Constructors and initialization functions play a critical role in contracts by setting important initial states when the contract is first deployed before the system starts. The parameters passed to the constructor and initialization functions directly affect the behavior of the contract / protocol. If incorrect parameters are provided, the system may fail to run, behave abnormally, be unstable, or lack security. Therefore, it's crucial to carefully check each parameter in the constructor and initialization functions. If an exception is found, the transaction should be rolled back.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}/// @audit `_priceIncrease`
10:     constructor(uint256 _priceIncrease) {

GitHub : 10

[L‑13] Contracts are vulnerable to fee-on-transfer accounting-related issues

Some tokens take a transfer fee (e.g. STA, PAXG), some do not currently charge a fee but may do so in the future (e.g. USDT, USDC). 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 13 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}153:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), price + fee);

166:             SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

187:         SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim + price - fee);

206:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

217:             SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

229:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

238:         SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

247:         SafeERC20.safeTransfer(token, msg.sender, amount);

257:         SafeERC20.safeTransfer(token, msg.sender, amount);

267:             SafeERC20.safeTransfer(token, msg.sender, amount);

GitHub : 153,166,187,206,217,229,238,247,257,267

File: asD/src/asD.sol

}50:         SafeERC20.safeTransferFrom(note, msg.sender, address(this), _amount);

66:         SafeERC20.safeTransfer(note, msg.sender, _amount);

88:         SafeERC20.safeTransfer(note, msg.sender, _amount);

GitHub : 50,66,88

[L‑14] Functions calling contracts/addresses with transfer hooks should be protected by reentrancy guard

Even if the function follows the best practice of check-effects-interaction, not using a reentrancy guard when there may be transfer hooks opens the users of this protocol up to read-only reentrancy vulnerability with no way to protect them except by block-listing the entire protocol.

There are 13 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}153:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), price + fee);

166:             SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

187:         SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim + price - fee);

206:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

217:             SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

229:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

238:         SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

247:         SafeERC20.safeTransfer(token, msg.sender, amount);

257:         SafeERC20.safeTransfer(token, msg.sender, amount);

267:             SafeERC20.safeTransfer(token, msg.sender, amount);

GitHub : 153,166,187,206,217,229,238,247,257,267

File: asD/src/asD.sol

}50:         SafeERC20.safeTransferFrom(note, msg.sender, address(this), _amount);

66:         SafeERC20.safeTransfer(note, msg.sender, _amount);

88:         SafeERC20.safeTransfer(note, msg.sender, _amount);

GitHub : 50,66,88

[L‑15] Critical functions should be controlled by time locks

It is a good practice to give time for users to react and adjust to critical changes. A timelock provides more guarantees and reduces the level of trust required, thus decreasing risk for users. It also indicates that the project is legitimate (less risk of a malicious owner making a sandwich attack on a user).

There are 2 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}104:     function changeBondingCurveAllowed(address _bondingCurve, bool _newState) external onlyOwner {

309:     function changeShareCreatorWhitelist(address _address, bool _isWhitelisted) external onlyOwner {

GitHub : 104,309

[L‑16] The safeApprove() function is deprecated

The safeApprove() like function is deprecated. It is encouraged to use safeIncreaseAllowance() and safeDecreaseAllowance() instead.

There are 1 instance(s) of this issue:

File: asD/src/asD.sol

}51:         SafeERC20.safeApprove(note, cNote, _amount);

GitHub : 51

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

Despite the fact that EIP-20 states that zero-value 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 9 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}153:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), price + fee);

187:         SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim + price - fee);

206:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

229:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

238:         SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

247:         SafeERC20.safeTransfer(token, msg.sender, amount);

257:         SafeERC20.safeTransfer(token, msg.sender, amount);

GitHub : 153,187,206,229,238,247,257

File: asD/src/asD.sol

}50:         SafeERC20.safeTransferFrom(note, msg.sender, address(this), _amount);

66:         SafeERC20.safeTransfer(note, msg.sender, _amount);

GitHub : 50,66

[L‑18] Loss of precision in divisions

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 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}290:             shareData[_id].shareHolderRewardsPerTokenScaled += (shareHolderFee * 1e18) / _tokenCount;

GitHub : 290

[L‑19] Code does not follow the best practice of check-effects-interaction

Code should follow the best-practice of check-effects-interaction, where state variables are updated before any external calls are made. Doing so prevents a large class of reentrancy bugs.

There are 10 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit `safeTransferFrom()` is called on line 153
159:         rewardsLastClaimedValue[_id][msg.sender] = shareData[_id].shareHolderRewardsPerTokenScaled;

/// @audit `safeTransferFrom()` is called on line 153
161:         shareData[_id].tokenCount += _amount;

/// @audit `safeTransferFrom()` is called on line 153
162:         shareData[_id].tokensInCirculation += _amount;

/// @audit `safeTransferFrom()` is called on line 153
163:         tokensByAddress[_id][msg.sender] += _amount;

/// @audit `safeTransferFrom()` is called on line 206
210:         rewardsLastClaimedValue[_id][msg.sender] = shareData[_id].shareHolderRewardsPerTokenScaled;

/// @audit `safeTransferFrom()` is called on line 206
211:         tokensByAddress[_id][msg.sender] -= _amount;

/// @audit `safeTransferFrom()` is called on line 206
212:         shareData[_id].tokensInCirculation -= _amount;

/// @audit `safeTransferFrom()` is called on line 229
233:         rewardsLastClaimedValue[_id][msg.sender] = shareData[_id].shareHolderRewardsPerTokenScaled;

/// @audit `safeTransferFrom()` is called on line 229
234:         tokensByAddress[_id][msg.sender] += _amount;

/// @audit `safeTransferFrom()` is called on line 229
235:         shareData[_id].tokensInCirculation += _amount;

GitHub : 211,235,234,233,212,210,163,162,161,159

[L‑20] Some tokens may revert when large transfers are made

Tokens such as COMP or UNI will revert when an address' balance reaches type(uint96).max. Ensure that the calls below can be broken up into smaller batches if necessary.

There are 13 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}153:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), price + fee);

166:             SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

187:         SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim + price - fee);

206:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

217:             SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

229:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

238:         SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

247:         SafeERC20.safeTransfer(token, msg.sender, amount);

257:         SafeERC20.safeTransfer(token, msg.sender, amount);

267:             SafeERC20.safeTransfer(token, msg.sender, amount);

GitHub : 166,187,206,217,229,238,247,153,257,267

File: asD/src/asD.sol

}50:         SafeERC20.safeTransferFrom(note, msg.sender, address(this), _amount);

66:         SafeERC20.safeTransfer(note, msg.sender, _amount);

88:         SafeERC20.safeTransfer(note, msg.sender, _amount);

GitHub : 50,66,88

[L‑21] Contracts are vulnerable to rebasing accounting-related issues

Rebasing tokens are tokens that have each holder's balanceof() increase over time. Aave aTokens are an example of such tokens. If rebasing tokens are used, rewards accrue to the contract holding the tokens, and cannot be withdrawn by the original depositor. To address the issue, track 'shares' deposited on a pro-rata basis, and let shares be redeemed for their proportion of the current balance at the time of the withdrawal.

There are 9 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}150:     function buy(uint256 _id, uint256 _amount) external {

174:     function sell(uint256 _id, uint256 _amount) external {

203:     function mintNFT(uint256 _id, uint256 _amount) external {

226:     function burnNFT(uint256 _id, uint256 _amount) external {

244:     function claimPlatformFee() external onlyOwner {

253:     function claimCreatorFee(uint256 _id) external {

263:     function claimHolderFee(uint256 _id) external {

GitHub : 150,174,203,226,244,253,263

File: asD/src/asD.sol

}47:     function mint(uint256 _amount) external {

60:     function burn(uint256 _amount) external {

GitHub : 47,60### Gas Risk Issues

[G‑01] Using private for constants saves gas

If needed, the values can be read from the verified contract source code, or if there are multiple values there can be a single getter function that returns a tuple of the values of all currently-public constants. Saves 3406-3606 gas in deployment gas due to the compiler not having to create non-payable getter functions for deployment calldata, not having to store the bytes of the value outside of where it's used, and not adding another entry to the method ID table

There are 3 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}14:     uint256 public constant NFT_FEE_BPS = 1_000; // 10%

15:     uint256 public constant HOLDER_CUT_BPS = 3_300; // 33%

16:     uint256 public constant CREATOR_CUT_BPS = 3_300; // 33%

GitHub : 16,15,14

[G‑02] Constructors can be marked as payable to save deployment gas

Payable functions cost less gas to execute, because the compiler does not have to add extra checks to ensure that no payment is provided. A constructor can be safely marked as payable, because only the deployer would be able to pass funds, and the project itself would not pass any funds.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}91:     constructor(string memory _uri, address _paymentToken) ERC1155(_uri) Ownable() {

GitHub : 91

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}10:     constructor(uint256 _priceIncrease) {

GitHub : 10

File: asD/src/asD.sol

}28:     constructor(
29:         string memory _name,
30:         string memory _symbol,
31:         address _owner,
32:         address _cNote,
33:         address _csrRecipient
34:     ) ERC20(_name, _symbol) {

GitHub : 28-34

File: asD/src/asDFactory.sol

}24:     constructor(address _cNote) {

GitHub : 24

[G‑03] Using ++X/--X instead of X++/X-- can save gas

It can save 5 gas for each execution / per iteration.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}20:         for (uint256 i = shareCount; i < shareCount + amount; i++) {

GitHub : 20

[G‑04] Use custom errors rather than revert()/require() strings to save gas

Custom errors are available from solidity version 0.8.4. Custom errors save ~50 gas each time they're hit by avoiding having to allocate and store the revert string. Not defining the strings also save deployment gas.

There are 12 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}81:         require(
82:             !shareCreationRestricted || whitelistedShareCreators[msg.sender] || msg.sender == owner(),
83:             "Not allowed"
84:         );

105:         require(whitelistedBondingCurves[_bondingCurve] != _newState, "State already set");

119:         require(whitelistedBondingCurves[_bondingCurve], "Bonding curve not whitelisted");

120:         require(shareIDs[_shareName] == 0, "Share already exists");

151:         require(shareData[_id].creator != msg.sender, "Creator cannot buy");

254:         require(shareData[_id].creator == msg.sender, "Not creator");

301:         require(shareCreationRestricted != _isRestricted, "State already set");

310:         require(whitelistedShareCreators[_address] != _isWhitelisted, "State already set");

GitHub : 310,105,119,301,151,254,81-84,120

File: asD/src/asD.sol

}54:         require(returnCode == 0, "Error when minting");

64:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem-underlying

81:             require(_amount <= maximumWithdrawable, "Too many tokens requested");

86:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem

GitHub : 86,81,64,54

[G‑05] Do not cache state variables that are used only once

It's cheaper to access the state variable directly if it is accessed only once. This can save the 3 gas cost of the extra stack allocation.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}134:         address bondingCurve = shareData[_id].bondingCurve;

143:         address bondingCurve = shareData[_id].bondingCurve;

195:         address bondingCurve = shareData[_id].bondingCurve;

273:         uint256 lastClaimedValue = rewardsLastClaimedValue[_id][msg.sender];

GitHub : 143,195,134,273

[G‑06] Inline modifiers that are only used once to save gas

Inline modifiers that are only used once can save gas.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}80:     modifier onlyShareCreator() {

GitHub : 80

[G‑07] Functions that revert when called by normal users can be marked payable

If a function modifier such as onlyOwner is used, the function will revert if a normal user tries to pay the function. Marking the function as payable will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided. The extra opcodes avoided are: CALLVALUE(2), DUP1(3), ISZERO(3), PUSH2(3), JUMPI(10), PUSH1(3), DUP1(3), REVERT(0), JUMPDEST(1), POP(2) which cost an average of about 21 gas per call to the function, in addition to the extra deployment cost.

There are 6 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}104:     function changeBondingCurveAllowed(address _bondingCurve, bool _newState) external onlyOwner {

114:     function createNewShare(
115:         string memory _shareName,
116:         address _bondingCurve,
117:         string memory _metadataURI
118:     ) external onlyShareCreator returns (uint256 id) {

244:     function claimPlatformFee() external onlyOwner {

300:     function restrictShareCreation(bool _isRestricted) external onlyOwner {

309:     function changeShareCreatorWhitelist(address _address, bool _isWhitelisted) external onlyOwner {

GitHub : 300,104,114-118,244,309

File: asD/src/asD.sol

}72:     function withdrawCarry(uint256 _amount) external onlyOwner {

GitHub : 72

[G‑08] Use x = x + y instead of x += y for state variables

Using the x = x + y instead of x += y for state simple state variables can save 10 gas. The same applies to -=, *=, etc.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}295:         platformPool += platformFee;

GitHub : 295

[G‑09] Operator >=/<= costs less gas than operator >/<

The compiler uses opcodes GT and ISZERO for code that uses >, but only requires LT for >=. A similar behavior applies for >, which uses opcodes LT and ISZERO, but only requires GT for <=. It can save 3 gas for each. It should be converted to the <=/>= equivalent when comparing against integer literals.

There are 6 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}165:         if (rewardsSinceLastClaim > 0) {

216:         if (rewardsSinceLastClaim > 0) {

266:         if (amount > 0) {

289:         if (_tokenCount > 0) {

GitHub : 289,266,165,216

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}20:         for (uint256 i = shareCount; i < shareCount + amount; i++) {

29:         if (shareCount > 1) {

GitHub : 29,20

[G‑10] Unused non-constant state variables waste gas

If the variable is assigned a non-zero value, saves Gsset (20000 gas). If it's assigned a zero value, saves Gsreset (2900 gas). If the variable remains unassigned, there is no gas savings unless the variable is public, in which case the compiler-generated non-payable getter deployment cost is saved. If the state variable is overriding an interface's public function, mark the variable as constant or immutable so that it does not use a storage slot.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}46:     mapping(uint256 => address) public shareBondingCurves;

GitHub : 46

[G‑11] Usage of ints/uints smaller than 32 bytes incurs overhead

Using ints/uints smaller than 32 bytes may cost more gas. This is because the EVM operates on 32 bytes at a time, so if an element is smaller than 32 bytes, the EVM must perform more operations to reduce the size of the element from 32 bytes to the desired size.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit uint256
27:     uint256 public shareCount;

GitHub : 27

[G‑12] Divisions can be unchecked to save gas

The expression type(int).min/(-1) is the only case where division causes an overflow. Therefore, uncheck can be used to save gas in scenarios where it is certain that such an overflow will not occur.

There are 8 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}197:         fee = (priceForOne * _amount * NFT_FEE_BPS) / 10_000;

275:             ((shareData[_id].shareHolderRewardsPerTokenScaled - lastClaimedValue) * tokensByAddress[_id][msg.sender]) /
276:             1e18;

285:         uint256 shareHolderFee = (_fee * HOLDER_CUT_BPS) / 10_000;

286:         uint256 shareCreatorFee = (_fee * CREATOR_CUT_BPS) / 10_000;

290:             shareData[_id].shareHolderRewardsPerTokenScaled += (shareHolderFee * 1e18) / _tokenCount;

GitHub : 197,285,290,286,275-276

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}23:             fee += (getFee(i) * tokenPrice) / 1e18;

35:         return 1e17 / divisor;

GitHub : 23,35

File: asD/src/asD.sol

}75:         uint256 maximumWithdrawable = (CTokenInterface(cNote).balanceOf(address(this)) * exchangeRate) /
76:             1e28 -

GitHub : 75-76

[G‑13] Increments can be unchecked to save gas

Using unchecked increments can save gas by bypassing the built-in overflow checks. This can save 30-40 gas per iteration. So it is recommended to use unchecked increments when overflow is not possible.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}20:         for (uint256 i = shareCount; i < shareCount + amount; i++) {

GitHub : 20

[G‑14] Use assembly to validate msg.sender

We can use assembly to efficiently validate msg.sender with the least amount of opcodes necessary. For more details check the following report Here

There are 3 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}82:             !shareCreationRestricted || whitelistedShareCreators[msg.sender] || msg.sender == owner(),

151:         require(shareData[_id].creator != msg.sender, "Creator cannot buy");

254:         require(shareData[_id].creator == msg.sender, "Not creator");

GitHub : 254,82,151

[G‑15] Using assembly to check for zero can save gas

Using assembly to check for zero can save gas by allowing more direct access to the evm and reducing some of the overhead associated with high-level operations in solidity.

There are 5 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}120:         require(shareIDs[_shareName] == 0, "Share already exists");

GitHub : 120

File: asD/src/asD.sol

}54:         require(returnCode == 0, "Error when minting");

64:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem-underlying

78:         if (_amount == 0) {

86:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem

GitHub : 54,64,78,86

[G‑16] Avoid contract existence checks by using low level calls

Prior to 0.8.10 the compiler inserted extra code, including EXTCODESIZE (100 gas), to check for contract existence for external function calls. In more recent solidity versions, the compiler will not insert these checks if the external call has a return value. Similar behavior can be achieved in earlier versions by using low-level calls, since low level calls never check for contract existence.

There are 8 instance(s) of this issue:

File: asD/src/asD.sol

}49:         IERC20 note = IERC20(cNoteToken.underlying());

52:         uint256 returnCode = cNoteToken.mint(_amount);

62:         IERC20 note = IERC20(cNoteToken.underlying());

63:         uint256 returnCode = cNoteToken.redeemUnderlying(_amount); // Request _amount of NOTE (the underlying of cNOTE)

73:         uint256 exchangeRate = CTokenInterface(cNote).exchangeRateCurrent(); // Scaled by 1 * 10^(18 - 8 + Underlying Token Decimals), i.e. 10^(28) in our case

75:         uint256 maximumWithdrawable = (CTokenInterface(cNote).balanceOf(address(this)) * exchangeRate) /

85:         uint256 returnCode = CErc20Interface(cNote).redeemUnderlying(_amount);

87:         IERC20 note = IERC20(CErc20Interface(cNote).underlying());

GitHub : 87,49,52,62,63,73,75,85

[G‑17] Use uint256(1)/uint256(2) instead of true/false to save gas for changes

Use uint256(1) and uint256(2) for true/false to avoid a Gwarmaccess (100 gas), and to avoid Gsset (20000 gas) when changing from ‘false’ to ‘true’, after having been ‘true’ in the past. Refer to the source.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}49:     mapping(address => bool) public whitelistedBondingCurves;

61:     bool public shareCreationRestricted = true;

64:     mapping(address => bool) public whitelistedShareCreators;

GitHub : 64,49,61

File: asD/src/asDFactory.sol

}15:     mapping(address => bool) public isAsD;

GitHub : 15

[G‑18] Avoid zero transfer to save gas

In Solidity, unnecessary operations can waste gas. For example, a transfer function without a zero amount check uses gas even if called with a zero amount, since the contract state remains unchanged. Implementing a zero amount check avoids these unnecessary function calls, saving gas and improving efficiency.

There are 9 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}153:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), price + fee);

187:         SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim + price - fee);

206:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

229:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

238:         SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

247:         SafeERC20.safeTransfer(token, msg.sender, amount);

257:         SafeERC20.safeTransfer(token, msg.sender, amount);

GitHub : 247,153,187,206,229,238,257

File: asD/src/asD.sol

}50:         SafeERC20.safeTransferFrom(note, msg.sender, address(this), _amount);

66:         SafeERC20.safeTransfer(note, msg.sender, _amount);

GitHub : 66,50

[G‑19] Optimize names to save gas

public/external function names and public member variable names can be optimized to save gas. Below are the interfaces/abstract contracts that can be optimized so that the most frequently-called functions use the least amount of gas possible during method lookup. Method IDs that have two leading zero bytes can save 128 gas each during deployment, and renaming functions to have lower method IDs will save 22 gas per call, per sorted position shifted.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit changeBondingCurveAllowed(), createNewShare(), getBuyPrice(), getSellPrice(), buy(), sell(), getNFTMintingPrice(), mintNFT(), burnNFT(), claimPlatformFee(), claimCreatorFee(), claimHolderFee(), restrictShareCreation(), changeShareCreatorWhitelist(), NFT_FEE_BPS, HOLDER_CUT_BPS, CREATOR_CUT_BPS, token, shareCount, shareIDs, shareData, shareBondingCurves, whitelistedBondingCurves, tokensByAddress, rewardsLastClaimedValue, platformPool, shareCreationRestricted, whitelistedShareCreators
10: contract Market is ERC1155, Ownable2Step {

GitHub : 10

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}/// @audit getPriceAndFee(), getFee(), priceIncrease
6: contract LinearBondingCurve is IBondingCurve {

GitHub : 6

File: asD/src/asD.sol

}/// @audit mint(), burn(), withdrawCarry(), cNote
11: contract asD is ERC20, Ownable2Step {

GitHub : 11

File: asD/src/asDFactory.sol

}/// @audit create(), cNote, isAsD
8: contract asDFactory is Ownable2Step {

GitHub : 8

[G‑20] Reduce gas usage by moving to Solidity 0.8.19 or later

Solidity version 0.8.19 introduced a number of gas optimizations, refer to the Solidity 0.8.19 Release Announcement for details.

There are 2 instance(s) of this issue:

File: asD/src/asD.sol

}2: pragma solidity >=0.8.0;

GitHub : 2

File: asD/src/asDFactory.sol

}2: pragma solidity >=0.8.0;

GitHub : 2

[G‑21] Newer versions of solidity are more gas efficient

The solidity language continues to pursue more efficient gas optimization schemes. Adopting a newer version of solidity can be more gas efficient.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}2: pragma solidity 0.8.19;

GitHub : 2

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}2: pragma solidity 0.8.19;

GitHub : 2

File: asD/src/asD.sol

}2: pragma solidity >=0.8.0;

GitHub : 2

File: asD/src/asDFactory.sol

}2: pragma solidity >=0.8.0;

GitHub : 2

[G‑22] Avoid updating storage when the value hasn't changed

Manipulating storage in solidity is gas-intensive. It can be optimized by avoiding unnecessary storage updates when the new value equals the existing value. If the old value is equal to the new value, not re-storing the value will avoid a Gsreset (2900 gas), potentially at the expense of a Gcoldsload (2100 gas) or a Gwarmaccess (100 gas).

There are 5 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}159:         rewardsLastClaimedValue[_id][msg.sender] = shareData[_id].shareHolderRewardsPerTokenScaled;

180:         rewardsLastClaimedValue[_id][msg.sender] = shareData[_id].shareHolderRewardsPerTokenScaled;

210:         rewardsLastClaimedValue[_id][msg.sender] = shareData[_id].shareHolderRewardsPerTokenScaled;

233:         rewardsLastClaimedValue[_id][msg.sender] = shareData[_id].shareHolderRewardsPerTokenScaled;

265:         rewardsLastClaimedValue[_id][msg.sender] = shareData[_id].shareHolderRewardsPerTokenScaled;

GitHub : 159,265,233,210,180

[G‑23] State variables that are used multiple times in a function should be cached in stack variables

When performing multiple operations on a state variable in a function, it is recommended to cache it first. Either multiple reads or multiple writes to a state variable can save gas by caching it on the stack. Caching of a state variable replaces each Gwarmaccess (100 gas) with a much cheaper stack read. Other less obvious fixes/optimizations include having local memory caches of state variable structs, or having local caches of state variable contracts/addresses. Saves 100 gas per instance.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit shareData[_id].tokensInCirculation: 2 reads 1 writes
150:     function buy(uint256 _id, uint256 _amount) external {

/// @audit shareData[_id].tokensInCirculation: 2 reads 1 writes
174:     function sell(uint256 _id, uint256 _amount) external {

/// @audit shareData[_id].tokensInCirculation: 2 reads 1 writes
203:     function mintNFT(uint256 _id, uint256 _amount) external {

/// @audit shareData[_id].tokensInCirculation: 2 reads 1 writes
226:     function burnNFT(uint256 _id, uint256 _amount) external {

GitHub : 226,203,174,150

[G‑24] Contracts can use fewer storage slots by truncating state variables

Some state variables can be safely modified so that the contract uses fewer storage slots. Each saved slot can avoid an extra Gsset (20000 gas) for the first setting of the struct. Subsequent reads as well as writes have smaller gas savings.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit Truncate `shareCount` to `uint64`
/// @audit Fewer storage usage (10 slots -> 9 slots):
///        32 B: mapping(string => uint256) shareIDs
///        32 B: mapping(uint256 => ShareData) shareData
///        32 B: mapping(uint256 => address) shareBondingCurves
///        32 B: mapping(address => bool) whitelistedBondingCurves
///        32 B: mapping(uint256 => mapping(address => uint256)) tokensByAddress
///        32 B: mapping(uint256 => mapping(address => uint256)) rewardsLastClaimedValue
///        32 B: uint256 platformPool
///        32 B: mapping(address => bool) whitelistedShareCreators
///        4 B: uint64 shareCount
///        1 B: bool shareCreationRestricted
10: contract Market is ERC1155, Ownable2Step {

GitHub : 10

[G‑25] Refactor duplicated require()/revert() checks to save gas

Duplicate require()/revert() checks can be refactored into a modifier or function, saving deployment costs.

There are 1 instance(s) of this issue:

File: asD/src/asD.sol

}/// @audit Duplicated on line 86
64:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem-underlying

GitHub : 64

[G‑26] Use assembly to emit events

To efficiently emit events, it's possible to utilize assembly by making use of scratch space and the free memory pointer. This approach has the advantage of potentially avoiding the costs associated with memory expansion.

However, it's important to note that in order to safely optimize this process, it is preferable to cache and restore the free memory pointer.

A good example of such practice can be seen in Solady's codebase.

There are 9 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}107:         emit BondingCurveStateChange(_bondingCurve, _newState);

126:         emit ShareCreated(id, _shareName, _bondingCurve, msg.sender);

220:         emit NFTsCreated(_id, msg.sender, _amount, fee);

240:         emit NFTsBurned(_id, msg.sender, _amount, fee);

248:         emit PlatformFeeClaimed(msg.sender, amount);

258:         emit CreatorFeeClaimed(msg.sender, _id, amount);

269:         emit HolderFeeClaimed(msg.sender, _id, amount);

303:         emit ShareCreationRestricted(_isRestricted);

GitHub : 258,269,303,126,220,240,248,107

File: asD/src/asD.sol

}89:         emit CarryWithdrawal(_amount);

GitHub : 89

[G‑27] Use calldata instead of memory for immutable arguments

Mark data types as calldata instead of memory where possible. This makes it so that the data is not automatically loaded into memory. If the data passed into the function does not need to be changed (like updating values in an array), it can be passed in as calldata. The one exception to this is if the argument must later be passed into another function that takes an argument that specifies memory storage.

There are 2 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit _shareName
/// @audit _metadataURI
114:     function createNewShare(
115:         string memory _shareName,
116:         address _bondingCurve,
117:         string memory _metadataURI
118:     ) external onlyShareCreator returns (uint256 id) {

GitHub : 114-118

File: asD/src/asDFactory.sol

}/// @audit _name
/// @audit _symbol
33:     function create(string memory _name, string memory _symbol) external returns (address) {

GitHub : 33

[G‑28] Using bools for storage incurs overhead

Booleans are more expensive than uint256 or any type that takes up a full word because each write operation emits an extra SLOAD to first read the slot's contents, replace the bits taken up by the boolean, and then write back. This is the compiler's defense against contract upgrades and pointer aliasing, and it cannot be disabled. Use uint256(0) and uint256(1) for true/false to avoid a Gwarmaccess (100 gas) for the extra SLOAD.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}49:     mapping(address => bool) public whitelistedBondingCurves;

61:     bool public shareCreationRestricted = true;

64:     mapping(address => bool) public whitelistedShareCreators;

GitHub : 64,49,61

File: asD/src/asDFactory.sol

}15:     mapping(address => bool) public isAsD;

GitHub : 15

[G‑29] Multiple accesses of the same mapping/array key/index should be cached

The instances below point to the second+ access of a value inside a mapping/array, within a function. Caching a mapping's value in a local storage or calldata variable when the value is accessed multiple times, saves ~42 gas per access due to not having to recalculate the key's keccak256 hash (Gkeccak256 - 30 gas) and that calculation's associated stack operations. Caching an array's struct avoids recalculating the array offsets into memory/calldata

There are 13 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit `whitelistedBondingCurves[_bondingCurve]` is also accessed on line 105
106:         whitelistedBondingCurves[_bondingCurve] = _newState;

/// @audit `shareIDs[_shareName]` is also accessed on line 120
122:         shareIDs[_shareName] = id;

/// @audit `shareData[id]` is also accessed on line 124, 125
123:         shareData[id].bondingCurve = _bondingCurve;

/// @audit `shareData[_id]` is also accessed on line 135
134:         address bondingCurve = shareData[_id].bondingCurve;

/// @audit `shareData[_id]` is also accessed on line 144
143:         address bondingCurve = shareData[_id].bondingCurve;

/// @audit `shareData[_id]` is also accessed on line 159, 161, 162, 151
158:         _splitFees(_id, fee, shareData[_id].tokensInCirculation);

/// @audit `shareData[_id]` is also accessed on line 180, 182, 183
177:         _splitFees(_id, fee, shareData[_id].tokensInCirculation);

/// @audit `shareData[_id]` is also accessed on line 196
195:         address bondingCurve = shareData[_id].bondingCurve;

/// @audit `shareData[_id]` is also accessed on line 210, 212
207:         _splitFees(_id, fee, shareData[_id].tokensInCirculation);

/// @audit `shareData[_id]` is also accessed on line 233, 235
230:         _splitFees(_id, fee, shareData[_id].tokensInCirculation);

/// @audit `shareData[_id]` is also accessed on line 256, 254
255:         uint256 amount = shareData[_id].shareCreatorPool;

/// @audit `shareData[_id]` is also accessed on line 290
288:         shareData[_id].shareCreatorPool += shareCreatorFee;

/// @audit `whitelistedShareCreators[_address]` is also accessed on line 310
311:         whitelistedShareCreators[_address] = _isWhitelisted;

GitHub : 288,106,122,123,134,143,158,177,195,207,230,255,311

[G‑30] Multiple mappings can be replaced with a single struct mapping

Saves a storage slot for the mapping. Depending on the circumstances and sizes of types, can avoid a Gsset (20000 gas) per mapping combined. Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot. Finally, if both fields are accessed in the same function, can save ~42 gas per access due to not having to recalculate the key's keccak256 hash (Gkeccak256 - 30 gas) and that calculation's associated stack operations.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}43:     mapping(uint256 => ShareData) public shareData;

46:     mapping(uint256 => address) public shareBondingCurves;

52:     mapping(uint256 => mapping(address => uint256)) public tokensByAddress;

55:     mapping(uint256 => mapping(address => uint256)) public rewardsLastClaimedValue;

GitHub : 46,43,52,55### NonCritical Risk Issues

[N‑01] NatSpec documentation for contract is missing

e.g. @dev or @notice, and it must appear above the contract definition braces in order to be identified by the compiler as NatSpec.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}10: contract Market is ERC1155, Ownable2Step {

GitHub : 10

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}6: contract LinearBondingCurve is IBondingCurve {

GitHub : 6

File: asD/src/asD.sol

}11: contract asD is ERC20, Ownable2Step {

GitHub : 11

File: asD/src/asDFactory.sol

}8: contract asDFactory is Ownable2Step {

GitHub : 8

[N‑02] Names of private/internal functions should be prefixed with an underscore

It is recommended by the Solidity Style Guide.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}42:     function log2(uint256 x) internal pure returns (uint256 r) {

GitHub : 42

[N‑03] Order of functions does not follow the Solidity Style Guide

According to the Solidity Style Guide, functions should be grouped according to their visibility and ordered: constructor, receive, fallback, external, public, internal, private. Within a grouping, place the view and pure functions last.

There are 13 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit ↓↓ Out of order with `buy()`
141:     function getSellPrice(uint256 _id, uint256 _amount) public view returns (uint256 price, uint256 fee) {

/// @audit ↑↑ Out of order with `getSellPrice()`
150:     function buy(uint256 _id, uint256 _amount) external {

/// @audit ↑↑ Out of order with `buy()`
174:     function sell(uint256 _id, uint256 _amount) external {

/// @audit ↓↓ Out of order with `mintNFT()`
194:     function getNFTMintingPrice(uint256 _id, uint256 _amount) public view returns (uint256 fee) {

/// @audit ↑↑ Out of order with `getNFTMintingPrice()`
203:     function mintNFT(uint256 _id, uint256 _amount) external {

/// @audit ↑↑ Out of order with `mintNFT()`
226:     function burnNFT(uint256 _id, uint256 _amount) external {

/// @audit ↑↑ Out of order with `burnNFT()`
244:     function claimPlatformFee() external onlyOwner {

/// @audit ↑↑ Out of order with `claimPlatformFee()`
253:     function claimCreatorFee(uint256 _id) external {

/// @audit ↑↑ Out of order with `claimCreatorFee()`
263:     function claimHolderFee(uint256 _id) external {

/// @audit ↓↓ Out of order with `_splitFees()`
272:     function _getRewardsSinceLastClaim(uint256 _id) internal view returns (uint256 amount) {

/// @audit ↑↑ Out of order with `_getRewardsSinceLastClaim()`
280:     function _splitFees(
281:         uint256 _id,
282:         uint256 _fee,
283:         uint256 _tokenCount
284:     ) internal {

/// @audit ↑↑ Out of order with `_splitFees()`
300:     function restrictShareCreation(bool _isRestricted) external onlyOwner {

/// @audit ↑↑ Out of order with `restrictShareCreation()`
309:     function changeShareCreatorWhitelist(address _address, bool _isWhitelisted) external onlyOwner {

GitHub : 253,141,150,174,194,203,226,244,263,272,280-284,300,309

[N‑04] Use of override is unnecessary

Starting from Solidity 0.8.8, the override keyword is not required when overriding an interface function, except for the case where the function is defined in multiple bases.

There are 2 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}14:     function getPriceAndFee(uint256 shareCount, uint256 amount)
15:         external
16:         view
17:         override
18:         returns (uint256 price, uint256 fee)

27:     function getFee(uint256 shareCount) public pure override returns (uint256) {

GitHub : 14-18,27

[N‑05] Custom errors should be used rather than revert()/require()

Custom errors are available from solidity version 0.8.4. Custom errors are more easily processed in try-catch blocks, and are easier to re-use and maintain.

There are 12 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}81:         require(
82:             !shareCreationRestricted || whitelistedShareCreators[msg.sender] || msg.sender == owner(),
83:             "Not allowed"
84:         );

105:         require(whitelistedBondingCurves[_bondingCurve] != _newState, "State already set");

119:         require(whitelistedBondingCurves[_bondingCurve], "Bonding curve not whitelisted");

120:         require(shareIDs[_shareName] == 0, "Share already exists");

151:         require(shareData[_id].creator != msg.sender, "Creator cannot buy");

254:         require(shareData[_id].creator == msg.sender, "Not creator");

301:         require(shareCreationRestricted != _isRestricted, "State already set");

310:         require(whitelistedShareCreators[_address] != _isWhitelisted, "State already set");

GitHub : 81-84,105,119,120,151,254,301,310

File: asD/src/asD.sol

}54:         require(returnCode == 0, "Error when minting");

64:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem-underlying

81:             require(_amount <= maximumWithdrawable, "Too many tokens requested");

86:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem

GitHub : 54,64,81,86

[N‑06] Large numeric literals should use underscores for readability

Large hardcoded numbers in code can be difficult to read. Consider using underscores for number literals to improve readability (e.g 1234567 -> 1_234_567). Consider using an underscore for every third digit from the right.

There are 6 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}93:         if (block.chainid == 7700 || block.chainid == 7701) {

93:         if (block.chainid == 7700 || block.chainid == 7701) {

GitHub : 93,93

File: asD/src/asD.sol

}37:         if (block.chainid == 7700 || block.chainid == 7701) {

37:         if (block.chainid == 7700 || block.chainid == 7701) {

GitHub : 37,37

File: asD/src/asDFactory.sol

}26:         if (block.chainid == 7700 || block.chainid == 7701) {

26:         if (block.chainid == 7700 || block.chainid == 7701) {

GitHub : 26,26

[N‑07] Assembly blocks should have extensive comments

Assembly blocks take a lot more time to audit than normal Solidity code, and often have gotchas and side-effects that the Solidity versions of the same code do not. Consider adding more comments explaining what is being done in every step of the assembly code, and describe why assembly is being used instead of Solidity.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}44:         assembly {

GitHub : 44

[N‑08] Simplify complex require statements

Simplifying complex require statements with local variables and if(or revert) statements can improve readability, make debugging easier, and promote modularity and reusability in the code.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}81:         require(
82:             !shareCreationRestricted || whitelistedShareCreators[msg.sender] || msg.sender == owner(),
83:             "Not allowed"
84:         );

GitHub : 81-84

[N‑09] Consider moving msg.sender checks to modifiers

If some functions are only allowed to be called by some specific users, consider using a modifier instead of checking with a require statement, especially if this check is done in multiple functions.

There are 2 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}151:         require(shareData[_id].creator != msg.sender, "Creator cannot buy");

254:         require(shareData[_id].creator == msg.sender, "Not creator");

GitHub : 151,254

[N‑10] Consider adding a block/deny-list

Doing so will significantly increase centralization, but will help to prevent hackers from using stolen tokens

There are 2 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}10: contract Market is ERC1155, Ownable2Step {

GitHub : 10

File: asD/src/asD.sol

}11: contract asD is ERC20, Ownable2Step {

GitHub : 11

[N‑11] Constants/Immutables 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/immutables 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 2 instance(s) of this issue:

File: asD/src/asD.sol

}/// @audit Seen in asD/src/asDFactory.sol#12
15:     address public immutable cNote; // Reference to the cNOTE token

GitHub : 15

File: asD/src/asDFactory.sol

}/// @audit Seen in asD/src/asD.sol#15
12:     address public immutable cNote;

GitHub : 12

[N‑12] Convert simple if-statements to ternary expressions

Converting some if statements to ternaries (such as z = (a < b) ? x : y) can make the code more concise and easier to read.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}29:         if (shareCount > 1) {
30:             divisor = log2(shareCount);
31:         } else {
32:             divisor = 1;
33:         }

GitHub : 29-33

[N‑13] Events should be emitted before external calls

Ensure that events follow the best practice of check-effects-interaction, and are emitted before external calls.

There are 8 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit `safeTransferFrom()` is called on line 153
168:         emit SharesBought(_id, msg.sender, _amount, price, fee);

/// @audit `safeTransfer()` is called on line 187
188:         emit SharesSold(_id, msg.sender, _amount, price, fee);

/// @audit `safeTransferFrom()` is called on line 206
220:         emit NFTsCreated(_id, msg.sender, _amount, fee);

/// @audit `safeTransferFrom()` is called on line 229
240:         emit NFTsBurned(_id, msg.sender, _amount, fee);

/// @audit `safeTransfer()` is called on line 247
248:         emit PlatformFeeClaimed(msg.sender, amount);

/// @audit `safeTransfer()` is called on line 257
258:         emit CreatorFeeClaimed(msg.sender, _id, amount);

/// @audit `safeTransfer()` is called on line 267
269:         emit HolderFeeClaimed(msg.sender, _id, amount);

GitHub : 188,168,220,240,248,258,269

File: asD/src/asD.sol

}/// @audit `exchangeRateCurrent()` is called on line 73
89:         emit CarryWithdrawal(_amount);

GitHub : 89

[N‑14] Events are emitted without the 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 3 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}107:         emit BondingCurveStateChange(_bondingCurve, _newState);

303:         emit ShareCreationRestricted(_isRestricted);

GitHub : 107,303

File: asD/src/asD.sol

}89:         emit CarryWithdrawal(_amount);

GitHub : 89

[N‑15] Event is missing indexed fields

Index event fields makes the field more quickly accessible to off-chain tools that parse events. However, note that each indexed field costs extra gas during emission, so it's not necessarily best to index the maximum allowed per event (three fields). 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 fields, all of the fields should be indexed.

There are 3 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}69:     event BondingCurveStateChange(address indexed curve, bool isWhitelisted);

78:     event ShareCreationRestricted(bool isRestricted);

GitHub : 69,78

File: asD/src/asDFactory.sol

}20:     event CreatedToken(address token, string symbol, string name, address creator);

GitHub : 20

[N‑16] 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 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit Out of order with the prev import️ ⬆
5: import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

/// @audit Out of order with the prev import️ ⬆
7: import {IBondingCurve} from "../interface/IBondingCurve.sol";

GitHub : 5,7

File: asD/src/asD.sol

}/// @audit Out of order with the prev import️ ⬆
6: import {CTokenInterface, CErc20Interface} from "../interface/clm/CTokenInterfaces.sol";

/// @audit Out of order with the prev import️ ⬆
8: import {IERC20, ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

GitHub : 6,8

[N‑17] @openzeppelin/contracts should be upgraded to a newer version

These contracts import contracts from @openzeppelin/contracts, but they are not using the latest version.

The imported version is 4.9.0.

There are 6 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}4: import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";

4: import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";

GitHub : 4,4

File: asD/src/asD.sol

}7: import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";

7: import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";

GitHub : 7,7

File: asD/src/asDFactory.sol

}5: import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";

5: import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";

GitHub : 5,5

[N‑18] Lines are too long

The solidity style guide recommends a maximum line length of 120 characters. Lines of code that are longer than 120 should be wrapped.

There are 11 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}34:         uint256 tokensInCirculation; // Number of outstanding tokens - tokens that are minted as NFT, i.e. the number of tokens that receive fees

35:         uint256 shareHolderRewardsPerTokenScaled; // Accrued funds for the share holder per token, multiplied by 1e18 to avoid precision loss

155:         // The rewardsLastClaimedValue then needs to be updated with the new value such that the user cannot claim fees of this buy

231:         // The user does not get the proportional rewards for the burning (unless they have additional tokens that are not in the NFT)

GitHub : 155,34,35,231

File: asD/src/asD.sol

}64:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem-underlying

71:     /// @dev The function checks that the owner does not withdraw too much NOTE, i.e. that a 1:1 NOTE:asD exchange rate can be maintained after the withdrawal

73:         uint256 exchangeRate = CTokenInterface(cNote).exchangeRateCurrent(); // Scaled by 1 * 10^(18 - 8 + Underlying Token Decimals), i.e. 10^(28) in our case

74:         // The amount of cNOTE the contract has to hold (based on the current exchange rate which is always increasing) such that it is always possible to receive 1 NOTE when burning 1 asD

84:         // But we do not handle this case specifically, as the only consequence is that the owner wastes a bit of gas when there is nothing to withdraw

86:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem

GitHub : 86,64,71,73,74,84

File: asD/src/asDFactory.sol

}14:     /// @notice Stores the addresses of all created tokens, allowing third-party contracts to check if an address is a legit token

GitHub : 14

[N‑19] Magic numbers should be replaced with constants

Magic numbers are hard-coded values in code that can make it difficult for developers and maintainers to understand the code, and can also cause confusion or errors. To improve the readability and maintainability of code, it is recommended to replace magic numbers with constants that have good readability.

There are 14 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit 7700
/// @audit 7701
93:         if (block.chainid == 7700 || block.chainid == 7701) {

/// @audit 0xEcf044C5B4b867CFda001101c617eCd347095B44
95:             Turnstile turnstile = Turnstile(0xEcf044C5B4b867CFda001101c617eCd347095B44);

/// @audit 10_000
197:         fee = (priceForOne * _amount * NFT_FEE_BPS) / 10_000;

/// @audit 1e18
276:             1e18;

/// @audit 10_000
285:         uint256 shareHolderFee = (_fee * HOLDER_CUT_BPS) / 10_000;

/// @audit 10_000
286:         uint256 shareCreatorFee = (_fee * CREATOR_CUT_BPS) / 10_000;

/// @audit 1e18
290:             shareData[_id].shareHolderRewardsPerTokenScaled += (shareHolderFee * 1e18) / _tokenCount;

GitHub : 286,93,95,197,276,285,290

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}/// @audit 1e18
23:             fee += (getFee(i) * tokenPrice) / 1e18;

/// @audit 1e17
35:         return 1e17 / divisor;

GitHub : 23,35

File: asD/src/asD.sol

}/// @audit 7700
/// @audit 7701
37:         if (block.chainid == 7700 || block.chainid == 7701) {

/// @audit 0xEcf044C5B4b867CFda001101c617eCd347095B44
39:             Turnstile turnstile = Turnstile(0xEcf044C5B4b867CFda001101c617eCd347095B44);

/// @audit 1e28
76:             1e28 -

GitHub : 37,39,76

File: asD/src/asDFactory.sol

}/// @audit 7700
/// @audit 7701
26:         if (block.chainid == 7700 || block.chainid == 7701) {

/// @audit 0xEcf044C5B4b867CFda001101c617eCd347095B44
28:             Turnstile turnstile = Turnstile(0xEcf044C5B4b867CFda001101c617eCd347095B44);

GitHub : 26,28

[N‑20] Memory-safe annotation preferred over comment variant

The memory-safe annotation (assembly ("memory-safe") { ... }) is preferred over the comment variant, which will be removed in a future breaking release.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}43:         /// @solidity memory-safe-assembly

GitHub : 43

[N‑21] Use @inheritdoc for overridden functions

It is recommended to use @inheritdoc for overridden functions.

There are 2 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}14:     function getPriceAndFee(uint256 shareCount, uint256 amount)
15:         external
16:         view
17:         override
18:         returns (uint256 price, uint256 fee)

27:     function getFee(uint256 shareCount) public pure override returns (uint256) {

GitHub : 14-18,27

[N‑22] Contracts should have NatSpec @author tags

Contracts should have NatSpec @author tags

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}10: contract Market is ERC1155, Ownable2Step {

GitHub : 10

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}6: contract LinearBondingCurve is IBondingCurve {

GitHub : 6

File: asD/src/asD.sol

}11: contract asD is ERC20, Ownable2Step {

GitHub : 11

File: asD/src/asDFactory.sol

}8: contract asDFactory is Ownable2Step {

GitHub : 8

[N‑23] Contracts should have @notice tags

The @notice is used to explain to users what the contract does. The compiler interprets /// or /** comments as this tag if one wasn't explicitly provided.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}10: contract Market is ERC1155, Ownable2Step {

GitHub : 10

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}6: contract LinearBondingCurve is IBondingCurve {

GitHub : 6

File: asD/src/asD.sol

}11: contract asD is ERC20, Ownable2Step {

GitHub : 11

File: asD/src/asDFactory.sol

}8: contract asDFactory is Ownable2Step {

GitHub : 8

[N‑24] Contracts should have NatSpec @title tags

Some contract definitions have an incomplete NatSpec: add a @title notation to describe the contract to improve the code documentation.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}10: contract Market is ERC1155, Ownable2Step {

GitHub : 10

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}6: contract LinearBondingCurve is IBondingCurve {

GitHub : 6

File: asD/src/asD.sol

}11: contract asD is ERC20, Ownable2Step {

GitHub : 11

File: asD/src/asDFactory.sol

}8: contract asDFactory is Ownable2Step {

GitHub : 8

[N‑25] Events missing NatSpec @param tag

Each modifier parameter should have a @param notation to improve the code documentation.

There are 12 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit Missing @param for `curve`, `isWhitelisted`
69:     event BondingCurveStateChange(address indexed curve, bool isWhitelisted);

/// @audit Missing @param for `id`, `name`, `bondingCurve`, `creator`
70:     event ShareCreated(uint256 indexed id, string name, address indexed bondingCurve, address indexed creator);

/// @audit Missing @param for `id`, `buyer`, `amount`, `price`, `fee`
71:     event SharesBought(uint256 indexed id, address indexed buyer, uint256 amount, uint256 price, uint256 fee);

/// @audit Missing @param for `id`, `seller`, `amount`, `price`, `fee`
72:     event SharesSold(uint256 indexed id, address indexed seller, uint256 amount, uint256 price, uint256 fee);

/// @audit Missing @param for `id`, `creator`, `amount`, `fee`
73:     event NFTsCreated(uint256 indexed id, address indexed creator, uint256 amount, uint256 fee);

/// @audit Missing @param for `id`, `burner`, `amount`, `fee`
74:     event NFTsBurned(uint256 indexed id, address indexed burner, uint256 amount, uint256 fee);

/// @audit Missing @param for `claimer`, `amount`
75:     event PlatformFeeClaimed(address indexed claimer, uint256 amount);

/// @audit Missing @param for `claimer`, `id`, `amount`
76:     event CreatorFeeClaimed(address indexed claimer, uint256 indexed id, uint256 amount);

/// @audit Missing @param for `claimer`, `id`, `amount`
77:     event HolderFeeClaimed(address indexed claimer, uint256 indexed id, uint256 amount);

/// @audit Missing @param for `isRestricted`
78:     event ShareCreationRestricted(bool isRestricted);

GitHub : 77,76,75,74,78,72,73,69,70,71

File: asD/src/asD.sol

}/// @audit Missing @param for `amount`
20:     event CarryWithdrawal(uint256 amount);

GitHub : 20

File: asD/src/asDFactory.sol

}/// @audit Missing @param for `token`, `symbol`, `name`, `creator`
20:     event CreatedToken(address token, string symbol, string name, address creator);

GitHub : 20

[N‑26] Event declarations should have NatSpec descriptions

Event declarations should have NatSpec descriptions

There are 12 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}69:     event BondingCurveStateChange(address indexed curve, bool isWhitelisted);

70:     event ShareCreated(uint256 indexed id, string name, address indexed bondingCurve, address indexed creator);

71:     event SharesBought(uint256 indexed id, address indexed buyer, uint256 amount, uint256 price, uint256 fee);

72:     event SharesSold(uint256 indexed id, address indexed seller, uint256 amount, uint256 price, uint256 fee);

73:     event NFTsCreated(uint256 indexed id, address indexed creator, uint256 amount, uint256 fee);

74:     event NFTsBurned(uint256 indexed id, address indexed burner, uint256 amount, uint256 fee);

75:     event PlatformFeeClaimed(address indexed claimer, uint256 amount);

76:     event CreatorFeeClaimed(address indexed claimer, uint256 indexed id, uint256 amount);

77:     event HolderFeeClaimed(address indexed claimer, uint256 indexed id, uint256 amount);

78:     event ShareCreationRestricted(bool isRestricted);

GitHub : 74,69,70,71,72,73,75,76,77,78

File: asD/src/asD.sol

}20:     event CarryWithdrawal(uint256 amount);

GitHub : 20

File: asD/src/asDFactory.sol

}20:     event CreatedToken(address token, string symbol, string name, address creator);

GitHub : 20

[N‑27] Functions missing NatSpec @param tag

Each function parameter should have a @param notation to improve the code documentation.

There are 7 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit Missing @param for `_id`
272:     function _getRewardsSinceLastClaim(uint256 _id) internal view returns (uint256 amount) {

/// @audit Missing @param for `_id`, `_fee`, `_tokenCount`
280:     function _splitFees(
281:         uint256 _id,
282:         uint256 _fee,
283:         uint256 _tokenCount
284:     ) internal {

GitHub : 272,280-284

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}/// @audit Missing @param for `_priceIncrease`
10:     constructor(uint256 _priceIncrease) {

/// @audit Missing @param for `shareCount`, `amount`
14:     function getPriceAndFee(uint256 shareCount, uint256 amount)

/// @audit Missing @param for `shareCount`
27:     function getFee(uint256 shareCount) public pure override returns (uint256) {

/// @audit Missing @param for `x`
42:     function log2(uint256 x) internal pure returns (uint256 r) {

GitHub : 42,27,10,14

File: asD/src/asDFactory.sol

}/// @audit Missing @param for `_name`, `_symbol`
33:     function create(string memory _name, string memory _symbol) external returns (address) {

GitHub : 33

[N‑28] NatSpec documentation for function is missing

It is recommended that Solidity contracts are fully annotated using NatSpec for all public interfaces (everything in the ABI). It is clearly stated in the Solidity official documentation. In complex projects such as DeFi, the interpretation of all functions and their arguments and returns is important for code readability and auditability.

There are 5 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}272:     function _getRewardsSinceLastClaim(uint256 _id) internal view returns (uint256 amount) {

GitHub : 272

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}10:     constructor(uint256 _priceIncrease) {

14:     function getPriceAndFee(uint256 shareCount, uint256 amount)

27:     function getFee(uint256 shareCount) public pure override returns (uint256) {

GitHub : 10,14,27

File: asD/src/asDFactory.sol

}33:     function create(string memory _name, string memory _symbol) external returns (address) {

GitHub : 33

[N‑29] Functions missing NatSpec @return tag

Functions missing NatSpec @return tag

There are 9 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}114:     function createNewShare(
115:         string memory _shareName,
116:         address _bondingCurve,
117:         string memory _metadataURI
118:     ) external onlyShareCreator returns (uint256 id) {

132:     function getBuyPrice(uint256 _id, uint256 _amount) public view returns (uint256 price, uint256 fee) {

141:     function getSellPrice(uint256 _id, uint256 _amount) public view returns (uint256 price, uint256 fee) {

194:     function getNFTMintingPrice(uint256 _id, uint256 _amount) public view returns (uint256 fee) {

272:     function _getRewardsSinceLastClaim(uint256 _id) internal view returns (uint256 amount) {

GitHub : 114-118,272,194,141,132

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}14:     function getPriceAndFee(uint256 shareCount, uint256 amount)
15:         external
16:         view
17:         override
18:         returns (uint256 price, uint256 fee)

27:     function getFee(uint256 shareCount) public pure override returns (uint256) {

42:     function log2(uint256 x) internal pure returns (uint256 r) {

GitHub : 27,42,14-18

File: asD/src/asDFactory.sol

}33:     function create(string memory _name, string memory _symbol) external returns (address) {

GitHub : 33

[N‑30] State variables should have NatSpec descriptions

It is recommended to use the NatSpec tags @notice, @dev, @return, @inheritdoc for public state variables, and @dev for non-public state variables.

There are 6 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}14:     uint256 public constant NFT_FEE_BPS = 1_000; // 10%

15:     uint256 public constant HOLDER_CUT_BPS = 3_300; // 33%

16:     uint256 public constant CREATOR_CUT_BPS = 3_300; // 33%

GitHub : 14,16,15

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}8:     uint256 public immutable priceIncrease;

GitHub : 8

File: asD/src/asD.sol

}15:     address public immutable cNote; // Reference to the cNOTE token

GitHub : 15

File: asD/src/asDFactory.sol

}12:     address public immutable cNote;

GitHub : 12

[N‑31] Contract name does not follow the Solidity Style Guide

According to the Solidity Style Guide, contracts and libraries should be named using the CapWords style.

There are 2 instance(s) of this issue:

File: asD/src/asD.sol

}11: contract asD is ERC20, Ownable2Step {

GitHub : 11

File: asD/src/asDFactory.sol

}8: contract asDFactory is Ownable2Step {

GitHub : 8

[N‑32] Functions should be named in mixedCase style

As the Solidity Style Guide suggests: functions should be named in mixedCase style.

There are 3 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}194:     function getNFTMintingPrice(uint256 _id, uint256 _amount) public view returns (uint256 fee) {

203:     function mintNFT(uint256 _id, uint256 _amount) external {

226:     function burnNFT(uint256 _id, uint256 _amount) external {

GitHub : 194,226,203

[N‑33] Variable names for immutables should use UPPER_CASE_WITH_UNDERSCORES

For immutable variable names, each word should use all capital letters, with underscores separating each word (UPPER_CASE_WITH_UNDERSCORES)

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}20:     IERC20 public immutable token;

GitHub : 20

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}8:     uint256 public immutable priceIncrease;

GitHub : 8

File: asD/src/asD.sol

}15:     address public immutable cNote; // Reference to the cNOTE token

GitHub : 15

File: asD/src/asDFactory.sol

}12:     address public immutable cNote;

GitHub : 12

[N‑34] Missing zero address check in functions with address parameters

Adding a zero address check for each address type parameter can prevent errors.

There are 3 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit `_bondingCurve not checked`
104:     function changeBondingCurveAllowed(address _bondingCurve, bool _newState) external onlyOwner {

/// @audit `_bondingCurve not checked`
114:     function createNewShare(
115:         string memory _shareName,
116:         address _bondingCurve,
117:         string memory _metadataURI
118:     ) external onlyShareCreator returns (uint256 id) {

/// @audit `_address not checked`
309:     function changeShareCreatorWhitelist(address _address, bool _isWhitelisted) external onlyOwner {

GitHub : 309,114-118,104

[N‑35] Constants should be put on the left side of comparisons

Putting constants on the left side of comparison statements is a best practice known as Yoda conditions. Although solidity's static typing system prevents accidental assignments within conditionals, adopting this practice can improve code readability and consistency, especially when working across multiple languages.

There are 11 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit put `7700` on the left
93:         if (block.chainid == 7700 || block.chainid == 7701) {

/// @audit put `7701` on the left
93:         if (block.chainid == 7700 || block.chainid == 7701) {

/// @audit put `0` on the left
120:         require(shareIDs[_shareName] == 0, "Share already exists");

GitHub : 120,93,93

File: asD/src/asD.sol

}/// @audit put `7700` on the left
37:         if (block.chainid == 7700 || block.chainid == 7701) {

/// @audit put `7701` on the left
37:         if (block.chainid == 7700 || block.chainid == 7701) {

/// @audit put `0` on the left
54:         require(returnCode == 0, "Error when minting");

/// @audit put `0` on the left
64:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem-underlying

/// @audit put `0` on the left
78:         if (_amount == 0) {

/// @audit put `0` on the left
86:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem

GitHub : 78,37,37,54,64,86

File: asD/src/asDFactory.sol

}/// @audit put `7700` on the left
26:         if (block.chainid == 7700 || block.chainid == 7701) {

/// @audit put `7701` on the left
26:         if (block.chainid == 7700 || block.chainid == 7701) {

GitHub : 26,26

[N‑36] Large multiples of ten should use scientific notation

Use a scientific notation rather than decimal literals (e.g. 1e6 instead of 1000000), for better code readability.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit 1_000 -> 1e3
14:     uint256 public constant NFT_FEE_BPS = 1_000; // 10%

/// @audit 10_000 -> 1e4
197:         fee = (priceForOne * _amount * NFT_FEE_BPS) / 10_000;

/// @audit 10_000 -> 1e4
285:         uint256 shareHolderFee = (_fee * HOLDER_CUT_BPS) / 10_000;

/// @audit 10_000 -> 1e4
286:         uint256 shareCreatorFee = (_fee * CREATOR_CUT_BPS) / 10_000;

GitHub : 286,14,197,285

[N‑37] Non-interface files should use fixed compiler versions

To prevent the actual contracts being deployed from behaving differently depending on the compiler version, it is recommended to use fixed solidity versions for contracts and libraries.

Although we can configure a specific version through config (like hardhat, forge config files), it is recommended to set the fixed version in the solidity pragma directly before deploying to the mainnet.

There are 2 instance(s) of this issue:

File: asD/src/asD.sol

}2: pragma solidity >=0.8.0;

GitHub : 2

File: asD/src/asDFactory.sol

}2: pragma solidity >=0.8.0;

GitHub : 2

[N‑38] Unused contract variables

The following state variables are defined but not used. It is recommended to check the code for logical omissions that cause them not to be used. If it's determined that they are not needed anywhere, it's best to remove them from the codebase to improve code clarity and minimize confusion.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}46:     mapping(uint256 => address) public shareBondingCurves;

GitHub : 46

[N‑39] Unused import

The identifier is imported but never used within the file.

There are 1 instance(s) of this issue:

File: asD/src/asD.sol

}/// @audit IasDFactory
5: import {IasDFactory} from "../interface/IasDFactory.sol";

GitHub : 5

[N‑40] Consider using delete rather than assigning zero to clear values

The delete keyword more closely matches the semantics of what is being done, and draws more attention to the changing of state, which may lead to a more thorough audit of its associated logic.

There are 2 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}246:         platformPool = 0;

256:         shareData[_id].shareCreatorPool = 0;

GitHub : 246,256

[N‑41] Use the latest Solidity version

Upgrading to the latest solidity version (0.8.19 for L2s) can optimize gas usage, take advantage of new features and improve overall contract efficiency. Where possible, based on compatibility requirements, it is recommended to use newer/latest solidity version to take advantage of the latest optimizations and features.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}2: pragma solidity 0.8.19;

GitHub : 2

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}2: pragma solidity 0.8.19;

GitHub : 2

File: asD/src/asD.sol

}2: pragma solidity >=0.8.0;

GitHub : 2

File: asD/src/asDFactory.sol

}2: pragma solidity >=0.8.0;

GitHub : 2

[N‑42] Named mappings are recommended

Named mappings (with syntax mapping(KeyType KeyName? => ValueType ValueName?)) are recommended.It can make the mapping variables clearer, more readable and easier to maintain.

There are 10 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}30:     mapping(string => uint256) public shareIDs;

43:     mapping(uint256 => ShareData) public shareData;

46:     mapping(uint256 => address) public shareBondingCurves;

49:     mapping(address => bool) public whitelistedBondingCurves;

52:     mapping(uint256 => mapping(address => uint256)) public tokensByAddress;

52:     mapping(uint256 => mapping(address => uint256)) public tokensByAddress;

55:     mapping(uint256 => mapping(address => uint256)) public rewardsLastClaimedValue;

55:     mapping(uint256 => mapping(address => uint256)) public rewardsLastClaimedValue;

64:     mapping(address => bool) public whitelistedShareCreators;

GitHub : 55,64,52,55,52,30,43,46,49

File: asD/src/asDFactory.sol

}15:     mapping(address => bool) public isAsD;

GitHub : 15

[N‑43] Whitespace in Expressions

See the Whitespace in Expressions section of the Solidity Style Guide.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit Whitespace inside parenthesis
196:         (uint256 priceForOne, ) = IBondingCurve(bondingCurve).getPriceAndFee(shareData[_id].tokenCount, 1);

GitHub : 196

[N‑44] Modifier declarations should have NatSpec descriptions

Modifier declarations should have NatSpec descriptions

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}80:     modifier onlyShareCreator() {

GitHub : 80

[N‑45] Contract functions should use an interface

All external/public functions should extend an interface. This is useful to ensure that the whole API is extracted and can be more easily integrated by other projects.

There are 18 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}104:     function changeBondingCurveAllowed(address _bondingCurve, bool _newState) external onlyOwner {

114:     function createNewShare(
115:         string memory _shareName,
116:         address _bondingCurve,
117:         string memory _metadataURI
118:     ) external onlyShareCreator returns (uint256 id) {

132:     function getBuyPrice(uint256 _id, uint256 _amount) public view returns (uint256 price, uint256 fee) {

141:     function getSellPrice(uint256 _id, uint256 _amount) public view returns (uint256 price, uint256 fee) {

150:     function buy(uint256 _id, uint256 _amount) external {

174:     function sell(uint256 _id, uint256 _amount) external {

194:     function getNFTMintingPrice(uint256 _id, uint256 _amount) public view returns (uint256 fee) {

203:     function mintNFT(uint256 _id, uint256 _amount) external {

226:     function burnNFT(uint256 _id, uint256 _amount) external {

244:     function claimPlatformFee() external onlyOwner {

253:     function claimCreatorFee(uint256 _id) external {

263:     function claimHolderFee(uint256 _id) external {

300:     function restrictShareCreation(bool _isRestricted) external onlyOwner {

309:     function changeShareCreatorWhitelist(address _address, bool _isWhitelisted) external onlyOwner {

GitHub : 114-118,104,132,141,150,174,194,203,226,244,253,263,300,309

File: asD/src/asD.sol

}47:     function mint(uint256 _amount) external {

60:     function burn(uint256 _amount) external {

72:     function withdrawCarry(uint256 _amount) external onlyOwner {

GitHub : 72,47,60

File: asD/src/asDFactory.sol

}33:     function create(string memory _name, string memory _symbol) external returns (address) {

GitHub : 33

[N‑46] Addresses shouldn't be hard-coded

It is often better to declare addresses as constant or immutable which can be assigned in constructor. This allows the code to remain the same across deployments on different networks, and avoids recompilation when addresses need to change.

There are 3 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}95:             Turnstile turnstile = Turnstile(0xEcf044C5B4b867CFda001101c617eCd347095B44);

GitHub : 95

File: asD/src/asD.sol

}39:             Turnstile turnstile = Turnstile(0xEcf044C5B4b867CFda001101c617eCd347095B44);

GitHub : 39

File: asD/src/asDFactory.sol

}28:             Turnstile turnstile = Turnstile(0xEcf044C5B4b867CFda001101c617eCd347095B44);

GitHub : 28

[N‑47] Multiple mappings with same keys can be combined into a single struct mapping for readability

Well-organized data structures make code reviews easier, which may lead to fewer bugs. Consider combining related mappings into mappings to structs, so it's clear what data is related.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}43:     mapping(uint256 => ShareData) public shareData;

46:     mapping(uint256 => address) public shareBondingCurves;

52:     mapping(uint256 => mapping(address => uint256)) public tokensByAddress;

55:     mapping(uint256 => mapping(address => uint256)) public rewardsLastClaimedValue;

GitHub : 55,43,46,52

[N‑48] Control structures do not follow the Solidity Style Guide

Refer to the Solidity style guide - Control Structures.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}14:     function getPriceAndFee(uint256 shareCount, uint256 amount)
15:         external
16:         view
17:         override
18:         returns (uint256 price, uint256 fee)
19:     {

GitHub : 14-19

[N‑49] Do not cache immutable variables

Instead of caching immutable variables, using them directly can make code more consistent and less prone to errors.

There are 2 instance(s) of this issue:

File: asD/src/asD.sol

}48:         CErc20Interface cNoteToken = CErc20Interface(cNote);

61:         CErc20Interface cNoteToken = CErc20Interface(cNote);

GitHub : 61,48

[N‑50] Missing event for critical changes

Events should be emitted when critical changes are made to the contracts.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}309:     function changeShareCreatorWhitelist(address _address, bool _isWhitelisted) external onlyOwner {
310:         require(whitelistedShareCreators[_address] != _isWhitelisted, "State already set");
311:         whitelistedShareCreators[_address] = _isWhitelisted;
312:     }

GitHub : 309-312

[N‑51] Duplicated require()/revert() checks should be refactored

Refactoring duplicate require()/revert() checks into a modifier or function can make the code more concise, readable and maintainable, and less likely to make errors or omissions when modifying the require() or revert().

There are 1 instance(s) of this issue:

File: asD/src/asD.sol

}/// @audit Duplicated on line 86
64:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem-underlying

GitHub : 64

[N‑52] 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 3 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}10: contract Market is ERC1155, Ownable2Step {

GitHub : 10

File: asD/src/asD.sol

}11: contract asD is ERC20, Ownable2Step {

GitHub : 11

File: asD/src/asDFactory.sol

}8: contract asDFactory is Ownable2Step {

GitHub : 8

[N‑53] Avoid the use of sensitive terms

Use alternative variants, e.g. allowlist/denylist instead of whitelist/blacklist.

There are 23 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}49:     mapping(address => bool) public whitelistedBondingCurves;

60:     /// @notice If true, only the whitelisted addresses can create shares

64:     mapping(address => bool) public whitelistedShareCreators;

69:     event BondingCurveStateChange(address indexed curve, bool isWhitelisted);

82:             !shareCreationRestricted || whitelistedShareCreators[msg.sender] || msg.sender == owner(),

100:     /// @notice Whitelist or remove whitelist for a bonding curve.

100:     /// @notice Whitelist or remove whitelist for a bonding curve.

101:     /// @dev Whitelisting status is only checked when adding a share

103:     /// @param _newState True if whitelisted, false if not

105:         require(whitelistedBondingCurves[_bondingCurve] != _newState, "State already set");

106:         whitelistedBondingCurves[_bondingCurve] = _newState;

112:     /// @param _bondingCurve Address of the bonding curve, has to be whitelisted

119:         require(whitelistedBondingCurves[_bondingCurve], "Bonding curve not whitelisted");

119:         require(whitelistedBondingCurves[_bondingCurve], "Bonding curve not whitelisted");

306:     /// @notice Adds or removes an address from the whitelist of share creators

308:     /// @param _isWhitelisted True if whitelisted, false if not

308:     /// @param _isWhitelisted True if whitelisted, false if not

309:     function changeShareCreatorWhitelist(address _address, bool _isWhitelisted) external onlyOwner {

309:     function changeShareCreatorWhitelist(address _address, bool _isWhitelisted) external onlyOwner {

310:         require(whitelistedShareCreators[_address] != _isWhitelisted, "State already set");

310:         require(whitelistedShareCreators[_address] != _isWhitelisted, "State already set");

311:         whitelistedShareCreators[_address] = _isWhitelisted;

311:         whitelistedShareCreators[_address] = _isWhitelisted;

GitHub : 101,311,311,310,310,309,309,308,308,306,119,119,112,106,105,103,100,100,82,69,64,60,49

[N‑54] Contracts should have NatSpec @dev tags

The @dev tag is used to explain extra details to developers.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}10: contract Market is ERC1155, Ownable2Step {

GitHub : 10

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}6: contract LinearBondingCurve is IBondingCurve {

GitHub : 6

File: asD/src/asD.sol

}11: contract asD is ERC20, Ownable2Step {

GitHub : 11

File: asD/src/asDFactory.sol

}8: contract asDFactory is Ownable2Step {

GitHub : 8

[N‑55] Missing NatSpec @dev from event declaration

Some events have an incomplete NatSpec: add a @dev notation to describe the event to improve the code documentation.

There are 12 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}69:     event BondingCurveStateChange(address indexed curve, bool isWhitelisted);

70:     event ShareCreated(uint256 indexed id, string name, address indexed bondingCurve, address indexed creator);

71:     event SharesBought(uint256 indexed id, address indexed buyer, uint256 amount, uint256 price, uint256 fee);

72:     event SharesSold(uint256 indexed id, address indexed seller, uint256 amount, uint256 price, uint256 fee);

73:     event NFTsCreated(uint256 indexed id, address indexed creator, uint256 amount, uint256 fee);

74:     event NFTsBurned(uint256 indexed id, address indexed burner, uint256 amount, uint256 fee);

75:     event PlatformFeeClaimed(address indexed claimer, uint256 amount);

76:     event CreatorFeeClaimed(address indexed claimer, uint256 indexed id, uint256 amount);

77:     event HolderFeeClaimed(address indexed claimer, uint256 indexed id, uint256 amount);

78:     event ShareCreationRestricted(bool isRestricted);

GitHub : 72,71,70,69,76,73,74,78,77,75

File: asD/src/asD.sol

}20:     event CarryWithdrawal(uint256 amount);

GitHub : 20

File: asD/src/asDFactory.sol

}20:     event CreatedToken(address token, string symbol, string name, address creator);

GitHub : 20

[N‑56] Missing NatSpec @notice from event declaration

Some events have an incomplete NatSpec: add a @notice notation to describe the event to improve the code documentation.

There are 12 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}69:     event BondingCurveStateChange(address indexed curve, bool isWhitelisted);

70:     event ShareCreated(uint256 indexed id, string name, address indexed bondingCurve, address indexed creator);

71:     event SharesBought(uint256 indexed id, address indexed buyer, uint256 amount, uint256 price, uint256 fee);

72:     event SharesSold(uint256 indexed id, address indexed seller, uint256 amount, uint256 price, uint256 fee);

73:     event NFTsCreated(uint256 indexed id, address indexed creator, uint256 amount, uint256 fee);

74:     event NFTsBurned(uint256 indexed id, address indexed burner, uint256 amount, uint256 fee);

75:     event PlatformFeeClaimed(address indexed claimer, uint256 amount);

76:     event CreatorFeeClaimed(address indexed claimer, uint256 indexed id, uint256 amount);

77:     event HolderFeeClaimed(address indexed claimer, uint256 indexed id, uint256 amount);

78:     event ShareCreationRestricted(bool isRestricted);

GitHub : 71,69,72,70,78,77,76,75,74,73

File: asD/src/asD.sol

}20:     event CarryWithdrawal(uint256 amount);

GitHub : 20

File: asD/src/asDFactory.sol

}20:     event CreatedToken(address token, string symbol, string name, address creator);

GitHub : 20

[N‑57] Missing NatSpec @dev from function declaration

Some functions have an incomplete NatSpec: add a @dev notation to describe the function to improve the code documentation.

There are 23 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}91:     constructor(string memory _uri, address _paymentToken) ERC1155(_uri) Ownable() {

114:     function createNewShare(

132:     function getBuyPrice(uint256 _id, uint256 _amount) public view returns (uint256 price, uint256 fee) {

141:     function getSellPrice(uint256 _id, uint256 _amount) public view returns (uint256 price, uint256 fee) {

150:     function buy(uint256 _id, uint256 _amount) external {

174:     function sell(uint256 _id, uint256 _amount) external {

194:     function getNFTMintingPrice(uint256 _id, uint256 _amount) public view returns (uint256 fee) {

203:     function mintNFT(uint256 _id, uint256 _amount) external {

226:     function burnNFT(uint256 _id, uint256 _amount) external {

244:     function claimPlatformFee() external onlyOwner {

253:     function claimCreatorFee(uint256 _id) external {

263:     function claimHolderFee(uint256 _id) external {

272:     function _getRewardsSinceLastClaim(uint256 _id) internal view returns (uint256 amount) {

280:     function _splitFees(

300:     function restrictShareCreation(bool _isRestricted) external onlyOwner {

309:     function changeShareCreatorWhitelist(address _address, bool _isWhitelisted) external onlyOwner {

GitHub : 309,91,114,132,141,150,174,194,203,226,244,253,263,272,280,300

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}10:     constructor(uint256 _priceIncrease) {

14:     function getPriceAndFee(uint256 shareCount, uint256 amount)

27:     function getFee(uint256 shareCount) public pure override returns (uint256) {

GitHub : 10,14,27

File: asD/src/asD.sol

}28:     constructor(

60:     function burn(uint256 _amount) external {

GitHub : 28,60

File: asD/src/asDFactory.sol

}24:     constructor(address _cNote) {

33:     function create(string memory _name, string memory _symbol) external returns (address) {

GitHub : 33,24

[N‑58] Missing NatSpec @notice from function declaration

Some functions have an incomplete NatSpec: add a @notice notation to describe the function to improve the code documentation.

There are 5 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}272:     function _getRewardsSinceLastClaim(uint256 _id) internal view returns (uint256 amount) {

GitHub : 272

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}10:     constructor(uint256 _priceIncrease) {

14:     function getPriceAndFee(uint256 shareCount, uint256 amount)

27:     function getFee(uint256 shareCount) public pure override returns (uint256) {

GitHub : 10,14,27

File: asD/src/asDFactory.sol

}33:     function create(string memory _name, string memory _symbol) external returns (address) {

GitHub : 33

[N‑59] Missing NatSpec @dev from modifier declaration

Some modifiers have an incomplete NatSpec: add a @dev notation to describe the modifier to improve the code documentation.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}80:     modifier onlyShareCreator() {

GitHub : 80

[N‑60] Missing NatSpec @notice from modifier declaration

Some modifiers have an incomplete NatSpec: add a @notice notation to describe the modifier to improve the code documentation.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}80:     modifier onlyShareCreator() {

GitHub : 80

[N‑61] Contracts should have full test coverage

While 100% code coverage does not guarantee that there are no bugs, it often will catch easy-to-find bugs, and will ensure that there are fewer regressions when the code invariably has to be modified. Furthermore, in order to get full coverage, code authors will often have to re-organize their code so that it is more modular, so that each component can be tested separately, which reduces interdependencies between modules and layers, and makes for code that is easier to reason about and audit.

There are 1 instance(s) of this issue:

/// @audit Global finding.

GitHub : 0

[N‑62] Large or complicated code bases should implement invariant tests

This includes: large code bases, or code with lots of inline-assembly, complicated math, or complicated interactions between multiple contracts. Invariant fuzzers such as Echidna require the test writer to come up with invariants which should not be violated under any circumstances, and the fuzzer tests various inputs and function calls to ensure that the invariants always hold. Even code with 100% code coverage can still have bugs due to the order of the operations a user performs, and invariant fuzzers may help significantly.

There are 1 instance(s) of this issue:

/// @audit Global finding.

GitHub : 0

[N‑63] Top-level declarations should be separated by at least two lines

There are 12 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}2: pragma solidity 0.8.19;
3: 
4: import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";

8: import {Turnstile} from "../interface/Turnstile.sol";
9: 
10: contract Market is ERC1155, Ownable2Step {

270:     }
271: 
272:     function _getRewardsSinceLastClaim(uint256 _id) internal view returns (uint256 amount) {

GitHub : 270-272,8-10,2-4

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}2: pragma solidity 0.8.19;
3: 
4: import {IBondingCurve} from "../../interface/IBondingCurve.sol";

4: import {IBondingCurve} from "../../interface/IBondingCurve.sol";
5: 
6: contract LinearBondingCurve is IBondingCurve {

12:     }
13: 
14:     function getPriceAndFee(uint256 shareCount, uint256 amount)

25:     }
26: 
27:     function getFee(uint256 shareCount) public pure override returns (uint256) {

GitHub : 2-4,4-6,12-14,25-27

File: asD/src/asD.sol

}2: pragma solidity >=0.8.0;
3: 
4: import {Turnstile} from "../interface/Turnstile.sol";

9: import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
10: 
11: contract asD is ERC20, Ownable2Step {

GitHub : 2-4,9-11

File: asD/src/asDFactory.sol

}2: pragma solidity >=0.8.0;
3: 
4: import {Turnstile} from "../interface/Turnstile.sol";

6: import {asD} from "./asD.sol";
7: 
8: contract asDFactory is Ownable2Step {

31:     }
32: 
33:     function create(string memory _name, string memory _symbol) external returns (address) {

GitHub : 2-4,31-33,6-8

[N‑64] Consider adding formal verification proofs

Formal verification is the act of proving or disproving the correctness of intended algorithms underlying a system with respect to a certain formal specification/property/invariant, using formal methods of mathematics.

Some tools that are currently available to perform these tests on smart contracts are SMTChecker and Certora Prover.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}```


*GitHub* : [0](https://github.com/code-423n4/2023-11-canto/blob/516099801101950ac9e1117a70e095b06f9bf6a1/1155tech-contracts/src/Market.sol)

```solidity
File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}```


*GitHub* : [0](https://github.com/code-423n4/2023-11-canto/blob/516099801101950ac9e1117a70e095b06f9bf6a1/1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol)

```solidity
File: asD/src/asD.sol

}```


*GitHub* : [0](https://github.com/code-423n4/2023-11-canto/blob/516099801101950ac9e1117a70e095b06f9bf6a1/asD/src/asD.sol)

```solidity
File: asD/src/asDFactory.sol

}```


*GitHub* : [0](https://github.com/code-423n4/2023-11-canto/blob/516099801101950ac9e1117a70e095b06f9bf6a1/asD/src/asDFactory.sol)
### [N&#x2011;65]<a name="N-65"></a> Error messages should be descriptive, not cryptic
Consider make these error messages more descriptive.

*There are 6 instance(s) of this issue:*

```solidity
File: 1155tech-contracts/src/Market.sol

}81:         require(
82:             !shareCreationRestricted || whitelistedShareCreators[msg.sender] || msg.sender == owner(),
83:             "Not allowed"
84:         );

105:         require(whitelistedBondingCurves[_bondingCurve] != _newState, "State already set");

301:         require(shareCreationRestricted != _isRestricted, "State already set");

310:         require(whitelistedShareCreators[_address] != _isWhitelisted, "State already set");

GitHub : 301,105,81-84,310

File: asD/src/asD.sol

}64:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem-underlying

86:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem

GitHub : 86,64### Disputed Risk Issues

[D‑01] Using private rather than public for constants, saves gas

If needed, the values can be read from the verified contract source code, or if there are multiple values there can be a single getter function that returns a tuple of the values of all currently-public constants. Saves 3406-3606 gas in deployment gas due to the compiler not having to create non-payable getter functions for deployment calldata, not having to store the bytes of the value outside of where it's used, and not adding another entry to the method ID table

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}20:     IERC20 public immutable token;

GitHub : 20

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}8:     uint256 public immutable priceIncrease;

GitHub : 8

File: asD/src/asD.sol

}15:     address public immutable cNote; // Reference to the cNOTE token

GitHub : 15

File: asD/src/asDFactory.sol

}12:     address public immutable cNote;

GitHub : 12

[D‑02] Event names should use CamelCase

The instances below are already CamelCase (events are supposed to use CamelCase, not lowerCamelCase).

There are 12 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}69:     event BondingCurveStateChange(address indexed curve, bool isWhitelisted);

70:     event ShareCreated(uint256 indexed id, string name, address indexed bondingCurve, address indexed creator);

71:     event SharesBought(uint256 indexed id, address indexed buyer, uint256 amount, uint256 price, uint256 fee);

72:     event SharesSold(uint256 indexed id, address indexed seller, uint256 amount, uint256 price, uint256 fee);

73:     event NFTsCreated(uint256 indexed id, address indexed creator, uint256 amount, uint256 fee);

74:     event NFTsBurned(uint256 indexed id, address indexed burner, uint256 amount, uint256 fee);

75:     event PlatformFeeClaimed(address indexed claimer, uint256 amount);

76:     event CreatorFeeClaimed(address indexed claimer, uint256 indexed id, uint256 amount);

77:     event HolderFeeClaimed(address indexed claimer, uint256 indexed id, uint256 amount);

78:     event ShareCreationRestricted(bool isRestricted);

GitHub : 72,73,74,75,76,77,78,69,70,71

File: asD/src/asD.sol

}20:     event CarryWithdrawal(uint256 amount);

GitHub : 20

File: asD/src/asDFactory.sol

}20:     event CreatedToken(address token, string symbol, string name, address creator);

GitHub : 20

[D‑03] Avoid double casting

The rule is valid, but the following findings are invalid.

There are 1 instance(s) of this issue:

File: asD/src/asD.sol

}87:         IERC20 note = IERC20(CErc20Interface(cNote).underlying());

GitHub : 87

[D‑04] Event is missing indexed fields

The rule is valid, but the following findings are invalid.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}70:     event ShareCreated(uint256 indexed id, string name, address indexed bondingCurve, address indexed creator);

GitHub : 70

[D‑05] internal functions only called once can be inlined to save gas

The rule is valid, but the following findings are invalid.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}42:     function log2(uint256 x) internal pure returns (uint256 r) {

GitHub : 42

[D‑06] Variables should be named in mixedCase style

As the Solidity Style Guide suggests: arguments, local variables and mutable state variables should be named in mixedCase style.

There are 1 instance(s) of this issue:

File: asD/src/asDFactory.sol

}/// @audit isAsD
15:     mapping(address => bool) public isAsD;

GitHub : 15

[D‑07] safeMint should be used in place of mint

The following are not ERC721.mint() calls.

There are 3 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}214:         _mint(msg.sender, _id, _amount, "");

GitHub : 214

File: asD/src/asD.sol

}52:         uint256 returnCode = cNoteToken.mint(_amount);

55:         _mint(msg.sender, _amount);

GitHub : 52,55

[D‑08] x += y is more expensive than x = x + y for state variables

It is not applicable to complex state variables.

There are 12 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}161:         shareData[_id].tokenCount += _amount;

162:         shareData[_id].tokensInCirculation += _amount;

163:         tokensByAddress[_id][msg.sender] += _amount;

182:         shareData[_id].tokenCount -= _amount;

183:         shareData[_id].tokensInCirculation -= _amount;

184:         tokensByAddress[_id][msg.sender] -= _amount; // Would underflow if user did not have enough tokens

211:         tokensByAddress[_id][msg.sender] -= _amount;

212:         shareData[_id].tokensInCirculation -= _amount;

234:         tokensByAddress[_id][msg.sender] += _amount;

235:         shareData[_id].tokensInCirculation += _amount;

288:         shareData[_id].shareCreatorPool += shareCreatorFee;

290:             shareData[_id].shareHolderRewardsPerTokenScaled += (shareHolderFee * 1e18) / _tokenCount;

GitHub : 235,161,162,163,182,183,184,211,212,234,290,288

[D‑09] Revert on transfer to the zero address

The rule is valid, but the following findings are invalid.

There are 13 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}153:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), price + fee);

166:             SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

187:         SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim + price - fee);

206:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

217:             SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

229:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

238:         SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

247:         SafeERC20.safeTransfer(token, msg.sender, amount);

257:         SafeERC20.safeTransfer(token, msg.sender, amount);

267:             SafeERC20.safeTransfer(token, msg.sender, amount);

GitHub : 187,153,166,206,217,229,238,247,257,267

File: asD/src/asD.sol

}50:         SafeERC20.safeTransferFrom(note, msg.sender, address(this), _amount);

66:         SafeERC20.safeTransfer(note, msg.sender, _amount);

88:         SafeERC20.safeTransfer(note, msg.sender, _amount);

GitHub : 50,66,88

[D‑10] SafeTransferLib does not ensure that the token contract exists

There is a subtle difference between the implementation of solady/solmate's SafeTransferLib and OZ's SafeERC20. OZ's SafeERC20 checks if the token is a contract or not, while SafeTransferLib does not:

@dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.

There are 14 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}153:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), price + fee);

166:             SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

187:         SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim + price - fee);

206:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

217:             SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

229:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

238:         SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);

247:         SafeERC20.safeTransfer(token, msg.sender, amount);

257:         SafeERC20.safeTransfer(token, msg.sender, amount);

267:             SafeERC20.safeTransfer(token, msg.sender, amount);

GitHub : 187,206,217,229,238,247,267,257,153,166

File: asD/src/asD.sol

}50:         SafeERC20.safeTransferFrom(note, msg.sender, address(this), _amount);

51:         SafeERC20.safeApprove(note, cNote, _amount);

66:         SafeERC20.safeTransfer(note, msg.sender, _amount);

88:         SafeERC20.safeTransfer(note, msg.sender, _amount);

GitHub : 66,50,51,88

[D‑11] Solidity version 0.8.20 or above may not work on other chains due to PUSH0

The rule is invalid for this project

There are 2 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}2: pragma solidity 0.8.19;

GitHub : 2

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}2: pragma solidity 0.8.19;

GitHub : 2

[D‑12] SPDX identifier should be the in the first line of a solidity file

SPDX identifier should be the in the first line of a solidity file.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}1: // SPDX-License-Identifier: GPL-3.0-only

GitHub : 1

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}1: // SPDX-License-Identifier: GPL-3.0-only

GitHub : 1

File: asD/src/asD.sol

}1: // SPDX-License-Identifier: GPL-3.0-only

GitHub : 1

File: asD/src/asDFactory.sol

}1: // SPDX-License-Identifier: GPL-3.0-only

GitHub : 1

[D‑13] Numbers downcast to addresses may result in collisions

The rule is valid, but the following findings are invalid.

There are 8 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}153:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), price + fee);

206:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

229:         SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);

GitHub : 206,153,229

File: asD/src/asD.sol

}50:         SafeERC20.safeTransferFrom(note, msg.sender, address(this), _amount);

75:         uint256 maximumWithdrawable = (CTokenInterface(cNote).balanceOf(address(this)) * exchangeRate) /

GitHub : 50,75

File: asD/src/asDFactory.sol

}35:         isAsD[address(createdToken)] = true;

36:         emit CreatedToken(address(createdToken), _symbol, _name, msg.sender);

37:         return address(createdToken);

GitHub : 36,35,37

[D‑14] Unused named return

The rule is valid, but the following findings are invalid.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}/// @audit r is used in assembly
42:     function log2(uint256 x) internal pure returns (uint256 r) {

GitHub : 42

[D‑15] Unused named return variables without optimizer waste gas

Suggestions that only apply when the optimizer is off are not useful to sponsors. Why would they pay for gas optimizations if they don't have the optimizer on, and don't plan to turn it on? Only a small minority have the optimizer off; the majority have it set to more than 200 runs

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}/// @audit r is used in assembly
42:     function log2(uint256 x) internal pure returns (uint256 r) {

GitHub : 42

[D‑16] Using bitmap to store bool states can save gas

None of these are examples where bitmaps can be used

There are 3 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}49:     mapping(address => bool) public whitelistedBondingCurves;

64:     mapping(address => bool) public whitelistedShareCreators;

GitHub : 64,49

File: asD/src/asDFactory.sol

}15:     mapping(address => bool) public isAsD;

GitHub : 15

[D‑17] Using delete statement can save gas

Using delete instead of assigning zero to state variables does not save any extra gas with the optimizer on (saves 5-8 gas with optimizer completely off), so this finding is invalid, especially since if they were interested in gas savings, they'd have the optimizer enabled.

There are 2 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}246:         platformPool = 0;

256:         shareData[_id].shareCreatorPool = 0;

GitHub : 246,256

[D‑18] Use != 0 or == 0 for unsigned integer comparison

Only valid prior to solidity version 0.8.13, and only for require() statements, and at least one of those is not true for the examples below.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}165:         if (rewardsSinceLastClaim > 0) {

216:         if (rewardsSinceLastClaim > 0) {

266:         if (amount > 0) {

289:         if (_tokenCount > 0) {

GitHub : 289,165,216,266

[D‑19] Avoid contract existence checks by using low level calls

Prior to 0.8.10 the compiler inserted extra code, including EXTCODESIZE (100 gas), to check for contract existence for external function calls. In more recent solidity versions, the compiler will not insert these checks if the external call has a return value. Similar behavior can be achieved in earlier versions by using low-level calls, since low level calls never check for contract existence.

There are 6 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit Return value not used.
96:             turnstile.register(tx.origin);

/// @audit Invalid for solidity version >= 0.8.10
135:         (price, fee) = IBondingCurve(bondingCurve).getPriceAndFee(shareData[_id].tokenCount + 1, _amount);

/// @audit Invalid for solidity version >= 0.8.10
144:         (price, fee) = IBondingCurve(bondingCurve).getPriceAndFee(shareData[_id].tokenCount - _amount + 1, _amount);

/// @audit Invalid for solidity version >= 0.8.10
196:         (uint256 priceForOne, ) = IBondingCurve(bondingCurve).getPriceAndFee(shareData[_id].tokenCount, 1);

GitHub : 144,96,135,196

File: asD/src/asD.sol

}/// @audit Return value not used.
40:             turnstile.register(_csrRecipient);

GitHub : 40

File: asD/src/asDFactory.sol

}/// @audit Return value not used.
29:             turnstile.register(tx.origin);

GitHub : 29

[D‑20] Use Ownable2Step instead of 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 3 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}10: contract Market is ERC1155, Ownable2Step {

GitHub : 10

File: asD/src/asD.sol

}11: contract asD is ERC20, Ownable2Step {

GitHub : 11

File: asD/src/asDFactory.sol

}8: contract asDFactory is Ownable2Step {

GitHub : 8

[D‑21] 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 1 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}107:         emit BondingCurveStateChange(_bondingCurve, _newState);

GitHub : 107

[D‑22] safeTransfer function does not check for contract existence

The examples below are either not token transfers, or are making high-level transfer()/transferFrom() calls (which check for contract existence), or are from a library that checks for contract existence.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}91:     constructor(string memory _uri, address _paymentToken) ERC1155(_uri) Ownable() {

GitHub : 91

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}10:     constructor(uint256 _priceIncrease) {

GitHub : 10

File: asD/src/asD.sol

}28:     constructor(

GitHub : 28

File: asD/src/asDFactory.sol

}24:     constructor(address _cNote) {

GitHub : 24

[D‑23] Assembly block creates dirty bits

Writing data to the free memory pointer without later updating the free memory pointer will cause there to be dirty bits at that memory location. Not updating the free memory pointer will make it harder for the optimizer to reason about whether the memory needs to be cleaned before use, which will lead to worse optimizations. Update the free memory pointer and annotate the block (assembly ("memory-safe") { ... }) to avoid this issue.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}44:         assembly {

GitHub : 44

[D‑24] require() or revert() statements that check input arguments should be at the top of the function

The rule is valid, but the following findings are invalid.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/Market.sol

}/// @audit should check before line 119
120:         require(shareIDs[_shareName] == 0, "Share already exists");

GitHub : 120

File: asD/src/asD.sol

}/// @audit should check before line 48
54:         require(returnCode == 0, "Error when minting");

/// @audit should check before line 61
64:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem-underlying

/// @audit should check before line 73
86:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem

GitHub : 86,54,64

[D‑25] Division by zero not prevented

The divisions below take an input parameter that has no zero-value checks, which can cause the functions reverting if zero is passed.

There are 1 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}35:         return 1e17 / divisor;

GitHub : 35

[D‑26] Inconsistent spacing in comments

The comments below are in the //x format, which differs from the commonly used idiomatic comment syntax of //<space>x. It is recommended to use a consistent comment syntax throughout.

There are 4 instance(s) of this issue:

File: 1155tech-contracts/src/bonding_curve/LinearBondingCurve.sol

}/// @audit It is an URL
41:     /// @notice Copied from Solady: https://github.com/Vectorized/solady/blob/main/src/utils/FixedPointMathLib.sol

GitHub : 41

File: asD/src/asD.sol

}/// @audit It is an URL
53:         // Mint returns 0 on success: https://docs.compound.finance/v2/ctokens/#mint

/// @audit It is an URL
64:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem-underlying

/// @audit It is an URL
86:         require(returnCode == 0, "Error when redeeming"); // 0 on success: https://docs.compound.finance/v2/ctokens/#redeem

GitHub : 86,53,64

[D‑27] Consider activating via-ir for deploying

The rule is invalid for this project

There are 1 instance(s) of this issue:

/// @audit Global finding.

GitHub : 0

[D‑28] Enable IR-based code generation

The rule is invalid for this project

There are 1 instance(s) of this issue:

/// @audit Global finding.

GitHub : 0

[D‑29] Large approvals may not work with some ERC20 tokens

Some tokens such as COMP downcast such approvals to uint96 and use that as a raw value rather than interpreting it as an infinite approval. Eventually these approvals will reach zero, at which point the calling contract will no longer function properly.

There are 1 instance(s) of this issue:

File: asD/src/asD.sol

}51:         SafeERC20.safeApprove(note, cNote, _amount);

GitHub : 51

[D‑30] Contracts are vulnerable to rebasing accounting-related issues

The rule is invalid for this project

There are 1 instance(s) of this issue:

File: asD/src/asD.sol

}72:     function withdrawCarry(uint256 _amount) external onlyOwner {

GitHub : 72 Thanks for reading!