Platform: Code4rena
Start Date: 04/11/2022
Pot Size: $42,500 USDC
Total HM: 9
Participants: 88
Period: 4 days
Judge: 0xean
Total Solo HM: 2
Id: 180
League: ETH
Rank: 36/88
Findings: 3
Award: $73.96
๐ Selected for report: 0
๐ Solo Findings: 0
๐ Selected for report: neko_nyaa
Also found by: 0x52, 0xSmartContract, 0xc0ffEE, Josiah, KingNFT, Lambda, R2, RaymondFam, Ruhum, TomJ, Trust, TwelveSec, __141345__, c7e7eff, cccz, cryptostellar5, fs0c, hansfriese, horsefacts, ladboy233, minhtrng, pashov, rvierdiiev, sashik_eth, tonisives, wagmi
8.5414 USDC - $8.54
https://github.com/code-423n4/2022-11-size/blob/main/src/SizeSealed.sol#L103
The createAuction
function checks the balance before and after the balance with the following code due to the feature of transfer Fee ERC20 tokens
This phrase in the NatSpec comments confirms this; "// Transfer base tokens to auction contract and check for tax tokensโ Because Tax tokens do not have a suitable architecture for the project and should not be included.
However, the balance of some reflection tokens does not change in every transfer, and their balanceOf can be determined not as uint256, but as a percentage of a certain amount, that is, it can pass through the balance check of the createAuction
function at first, and then the balance can change up or down before the Auction ends, which breaks the logic of the project.
A simple example from the balanceOf function of a similar token;
function balanceOf(address account) public view override returns (uint256) { if (_isExcluded[account]) return _tOwned[account]; return tokenFromReflection(_rOwned[account]);//=> rAmount/currentRate }
src/SizeSealed.sol: 95 // Transfer base tokens to auction contract and check for tax tokens 96: uint256 balanceBeforeTransfer = ERC20(auctionParams.baseToken).balanceOf(address(this)); 97: 98: SafeTransferLib.safeTransferFrom( 99: ERC20(auctionParams.baseToken), msg.sender, address(this), auctionParams.totalBaseAmount 100: ); 101: 102: uint256 balanceAfterTransfer = ERC20(auctionParams.baseToken).balanceOf(address(this)); 103: if (balanceAfterTransfer - balanceBeforeTransfer != auctionParams.totalBaseAmount) { 104: revert UnexpectedBalanceChange(); 105: } 106
Manual Code Review
The balance of such tokens during the createAuction
function should be compared with the balance during the finalize
function, and if there is a difference, the transaction should be reverted and the user should get their tokens back.
#0 - 0xean
2022-11-09T19:25:29Z
roughly a dupe of "special" token handling.
#1 - c4-judge
2022-11-09T19:25:34Z
0xean marked the issue as duplicate
#2 - c4-judge
2022-12-06T00:22:46Z
0xean marked the issue as satisfactory
๐ Selected for report: 0x1f8b
Also found by: 0xSmartContract, 0xc0ffEE, Aymen0909, B2, Deivitto, Josiah, KingNFT, Rahoz, RaymondFam, RedOneN, ReyAdmirado, Trust, ajtra, aviggiano, brgltd, c7e7eff, cryptonue, ctf_sec, delfin454000, djxploit, lukris02, peanuts, rvierdiiev, shark, simon135, slowmoses, tnevler, trustindistrust
44.2869 USDC - $44.29
foundry.toml: 1: [profile.default] 2: src = 'src' 3: out = 'out' 4: libs = ['lib'] 5: 6: optimizer=true 7 via_ir=true
Description: Protocol has enabled optional compiler optimizations in Solidity. There have been several optimization bugs with security implications. Moreover, optimizations are actively being developed. Solidity compiler optimizations are disabled by default, and it is unclear how many contracts in the wild actually use them.
Therefore, it is unclear how well they are being tested and exercised. High-severity security issues due to optimization bugs have occurred in the past. A high-severity bug in the emscripten-generated solc-js compiler used by Truffle and Remix persisted until late 2018. The fix for this bug was not reported in the Solidity CHANGELOG.
Another high-severity optimization bug resulting in incorrect bit shift results was patched in Solidity 0.5.6. More recently, another bug due to the incorrect caching of keccak256 was reported. A compiler audit of Solidity from November 2018 concluded that the optional optimizations may not be safe. It is likely that there are latent bugs related to optimization and that new bugs will be introduced due to future optimizations.
Exploit Scenario A latent or future bug in Solidity compiler optimizationsโor in the Emscripten transpilation to solc-jsโcauses a security vulnerability in the contracts.
Recommendation: Short term, measure the gas savings from optimizations and carefully weigh them against the possibility of an optimization-related bug. Long term, monitor the development and adoption of Solidity compiler optimizations to assess their maturity.
Description: NatSpec is missing for the following functions, mappings , structs and modifiers:
Context: SizeSealed.sol#L20 SizeSealed.sol#L22 SizeSealed.sol#L28 SizeSealed.sol#L466 SizeSealed.sol#L470 SizeSealed.sol#L474 SizeSealed.sol#L478 ECCMath.sol#L11
Context:
src/util/CommonTokenMath.sol: 47: function tokensAvailableAtTime( 48: uint32 vestingStart, 49: uint32 vestingEnd, 50: uint32 currentTime, 51: uint128 cliffPercent, 52: uint128 baseAmount 53: ) internal pure returns (uint128) { 54 if (currentTime > vestingEnd) { src/util/ECCMath.sol: 17 /// @dev calculates G^k, aka G^privateKey = publicKey 18: function publicKey(uint256 privateKey) internal view returns (Point memory) { src/util/ECCMath.sol: 24 /// @return corresponding point 25: function ecMul(Point memory point, uint256 scalar) internal view returns (Point memory) { src/util/ECCMath.sol: 36 /// @param message arbitrary 32 bytes 37: function encryptMessage(Point memory encryptToPub, uint256 encryptWithPriv, bytes32 message) 38: internal 39: view 40 returns (Point memory buyerPub, bytes32 encryptedMessage)
Description: The above codes don't follow Solidity's standard naming convention, internal and private functions : the mixedCase format starting with an underscore (_mixedCase starting with an underscore) public and external functions : only mixedCase constant variable : UPPER_CASE_WITH_UNDERSCORES (separated by uppercase and underscore)
Description: Index event fields make the field more quickly accessible to off-chain tools that parse events. However, note that each index field costs extra gas during emission, so it's not necessarily best to index the maximum allowed per event (three fields). 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.
Context:
src/interfaces/ISizeSealed.sol: 97: event AuctionCreated( 98: uint256 auctionId, address seller, AuctionParameters params, Timings timings, bytes encryptedPrivKey 99: ); 102: 103: event Bid( 104: address sender, 105: uint256 auctionId, 106: uint256 bidIndex, 107: uint128 quoteAmount, 108: bytes32 commitment, 109: ECCMath.Point pubKey, 110: bytes32 encryptedMessage, 111: bytes encryptedPrivateKey 112: );
#0 - c4-judge
2022-11-10T02:51:27Z
0xean marked the issue as grade-b
๐ Selected for report: 0x1f8b
Also found by: 0xSmartContract, 0xdeadbeef, Aymen0909, B2, Bnke0x0, Deivitto, Diana, Dinesh11G, JC, RaymondFam, ReyAdmirado, Rolezn, Sathish9098, TomJ, ajtra, aviggiano, chaduke, cryptostellar5, djxploit, gianganhnguyen, gogo, halden, karanctf, leosathya, lukris02, mcwildy, oyc_109, ret2basic, skyle, slowmoses
21.132 USDC - $21.13
x -= y (x += y)
costs more gas than x = x โ y (x = x + y)
for state variablesDescription:
src/SizeSealed.sol: 309: data.filledBase += baseAmount; 388: b.baseWithdrawn += baseTokensAvailable;
Proof Of Concept: The optimizer was turned on and set to 10000 runs.
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testGas() public { c0.swap(2,3); c1.swap1(2,3); } } contract Contract0 { uint256 public amountIn = 10; function swap(uint256 amountInToBin, uint256 fee) external returns (uint256 ) { return amountIn -= amountInToBin + fee; } } contract Contract1 { uint256 public amountIn = 10; function swap1(uint256 amountInToBin, uint256 fee) external returns (uint256 result1) { return (amountIn = amountIn - (amountInToBin + fee)); } }
Gas Report:
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโฌโโโโโโโฌโโโโโโโโโฌโโโโโโโฌโโโโโโโโโโฎ โ src/test/test.sol:Contract0 contract โ โ โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโชโโโโโโโชโโโโโโโโโชโโโโโโโชโโโโโโโโโโก โ Deployment Cost โ Deployment Size โ โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโผโโโโโโโโโผโโโโโโโผโโโโโโโโโโค โ 83017 โ 341 โ โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโผโโโโโโโโโผโโโโโโโผโโโโโโโโโโค โ Function Name โ min โ avg โ median โ max โ # calls โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโผโโโโโโโโโผโโโโโโโผโโโโโโโโโโค โ swap โ 5454 โ 5454 โ 5454 โ 5454 โ 1 โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโดโโโโโโโดโโโโโโโโโดโโโโโโโดโโโโโโโโโโฏ โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโฌโโโโโโโฌโโโโโโโโโฌโโโโโโโฌโโโโโโโโโโฎ โ src/test/test.sol:Contract1 contract โ โ โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโชโโโโโโโชโโโโโโโโโชโโโโโโโชโโโโโโโโโโก โ Deployment Cost โ Deployment Size โ โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโผโโโโโโโโโผโโโโโโโผโโโโโโโโโโค โ 83017 โ 341 โ โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโผโโโโโโโโโผโโโโโโโผโโโโโโโโโโค โ Function Name โ min โ avg โ median โ max โ # calls โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโผโโโโโโโโโผโโโโโโโผโโโโโโโโโโค โ swap1 โ 5431 โ 5431 โ 5431 โ 5431 โ 1 โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโดโโโโโโโดโโโโโโโโโดโโโโโโโดโโโโโโโโโโฏ
Context:ย All Contracts
Description:ย
Contracts most called functions could simply save gas by function ordering via Method ID
. Calling a function at runtime will be cheaper if the function is positioned earlier in the order (has a relatively lower Method ID) because 22 gas
are added to the cost of a function for every position that came before it. The caller can save on gas if you prioritize most called functions.ย
Recommendation:ย
Find a lower method ID
name for the most called functions for exampleย Call()ย vs.ย Call1()ย is cheaper by 22 gas
For example, the function IDs in the SizeSealed.sol
contract will be the most used; A lower method ID may be given.
Proof of Consept: https://medium.com/joyso/solidity-how-does-function-name-affect-gas-consumption-in-smart-contract-47d270d8ac92
SizeSealed.sol function names can be named and sorted according to METHOD ID
Sighash | Function Signature ======================== 2585613a => createAuction(AuctionParameters,Timings,bytes) 3d4fec96 => bid(uint256,uint128,bytes32,ECCMath.Point256,bytes32,bytes,bytes32[]) a90fe861 => reveal(uint256,uint256,bytes) f9ca43e5 => finalize(uint256,uint256[],uint128,uint128) 5af36e3e => refund(uint256,uint256) 441a3e70 => withdraw(uint256,uint256) 96b5a755 => cancelAuction(uint256) 4b393605 => cancelBid(uint256,uint256) 37c0d67a => tokensAvailableForWithdrawal(uint256,uint128) c387742b => computeCommitment(bytes32) 089bc2a1 => computeMessage(uint128,bytes16) 9f57665d => getTimings(uint256) 44f27e30 => getAuctionData(uint256)
assembly
to write address storage valuesContext:
src/SizeSealed.sol: 83 84: uint256 auctionId = ++currentAuctionId;
Proof Of Concept: The optimizer was turned on and set to 10000 runs.
contract GasTestFoundry is DSTest { Contract1 c1; Contract2 c2; function setUp() public { c1 = new Contract1(); c2 = new Contract2(); } function testGas() public { c1.setRewardTokenAndAmount(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4,356); c2.setRewardTokenAndAmount(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4,356); } } contract Contract1 { address rewardToken ; uint256 reward; function setRewardTokenAndAmount(address token_, uint256 reward_) external { rewardToken = token_; reward = reward_; } } contract Contract2 { address rewardToken ; uint256 reward; function setRewardTokenAndAmount(address token_, uint256 reward_) external { assembly { sstore(rewardToken.slot, token_) sstore(reward.slot, reward_) } } }
Gas Report:
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโฌโโโโโโโโฌโโโโโโโโโฌโโโโโโโโฌโโโโโโโโโโฎ โ src/test/GasTest.t.sol:Contract1 contract โ โ โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโชโโโโโโโโชโโโโโโโโโชโโโโโโโโชโโโโโโโโโโก โ Deployment Cost โ Deployment Size โ โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโโผโโโโโโโโโผโโโโโโโโผโโโโโโโโโโค โ 50899 โ 285 โ โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโโผโโโโโโโโโผโโโโโโโโผโโโโโโโโโโค โ Function Name โ min โ avg โ median โ max โ # calls โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโโผโโโโโโโโโผโโโโโโโโผโโโโโโโโโโค โ setRewardTokenAndAmount โ 44490 โ 44490 โ 44490 โ 44490 โ 1 โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโดโโโโโโโโดโโโโโโโโโดโโโโโโโโดโโโโโโโโโโฏ โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโฌโโโโโโโโฌโโโโโโโโโฌโโโโโโโโฌโโโโโโโโโโฎ โ src/test/GasTest.t.sol:Contract2 contract โ โ โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโชโโโโโโโโโโโโโโโโโโชโโโโโโโโชโโโโโโโโโชโโโโโโโโชโโโโโโโโโโก โ Deployment Cost โ Deployment Size โ โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโโผโโโโโโโโโผโโโโโโโโผโโโโโโโโโโค โ 38087 โ 221 โ โ โ โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโโผโโโโโโโโโผโโโโโโโโผโโโโโโโโโโค โ Function Name โ min โ avg โ median โ max โ # calls โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโผโโโโโโโโผโโโโโโโโโผโโโโโโโโผโโโโโโโโโโค โ setRewardTokenAndAmount โ 44457 โ 44457 โ 44457 โ 44457 โ 1 โ โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโดโโโโโโโโดโโโโโโโโโดโโโโโโโโดโโโโโโโโโโฏ
#0 - c4-judge
2022-11-10T02:30:18Z
0xean marked the issue as grade-b