-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New pool can deploy failed due to front-running #235
Comments
Picodes marked the issue as unsatisfactory: |
Hi, this issue front-running is just call
This issue is simliar to https://www.trust-security.xyz/post/permission-denied. When a single tx has A,B,C actions, if A/B action can be front-running, the whole tx can be reverted, so the C action can't be finished. In this issue is that the later actions can't be executed successfully. |
Hi @Picodes, thanks for judging! Since I happened to view this issue, I would like to share the following test for it. function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
// Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
// of the `implementation` address with the bytecode before the address.
mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
// Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
instance := create2(0, 0x09, 0x37, salt)
}
require(instance != address(0), "ERC1167: create2 failed");
}
function test_cloneDeterministic() public {
bytes32 salt = bytes32(uint96(block.timestamp) + (uint256(uint160(address(this))) << 96));
vm.startPrank(address(123));
address instance1 = cloneDeterministic(address(this), salt);
vm.stopPrank();
vm.startPrank(address(321));
address instance2 = cloneDeterministic(address(this), salt);
vm.stopPrank();
assert(instance1 != instance2);
} This test will pass to demonstrate that when different Along the same line, I wonder how #482, which is judged as a medium risk at this moment, would be possible. #482 mentions that the attacker would use |
Thanks for your test case, you are right that different msg.sender can create different instance, this issue indeed an invalid issue. |
@rbserver thanks for your test! |
@Picodes I know QA ended yesterday, but, I would like to share my thoughts about this, hope this can be considered So, if the attacker and the deployer are the same person, does not that mean that such an attack is possible only after Panoptic fully decentralizes the creation of the pools? In the beginning, only the owner can deploy new pools. If so, at that moment, PanopticPools could be deployed for worthlessTokens/worhtTokens , tokens with reentrancy, a number of different combinations that could one way or the other cause damage to the users.
The report can be a perfect QA because the team now is aware of one extra check when they do their due diligence when validating if a pool is good to be listed for users to deposit in it |
@stalinMacias thanks for your comment. Indeed this is only for the permissionless setup. I still think this attack path is expensive but credible and the cost is likely to decrease in the future, could be done for interesting pools where the expected extractable value is high, and could easily have been missed by Panoptic and users without this report, so is worth Medium severity |
@Picodes, thanks for judging and the clarification! @yuliyu123 and @stalinMacias , thanks for the discussion! |
Lines of code
https://github.com/code-423n4/2024-04-panoptic/blob/833312ebd600665b577fbd9c03ffa0daf250ed24/contracts/PanopticFactory.sol#L210-L259
Vulnerability details
Impact
When deploy a new pool by
PanopticFactory#deployNewPool
, it callPOOL_REFERENCE.cloneDeterministic(salt)
to calculate the pool address, then start the pool and record the pool's address tos_getPanopticPool
mapping. ThePOOL_REFERENCE.cloneDeterministic
finally call OpenZeppelin libraryClones#cloneDeterministic
to calculate and create the pool address based oncreate2
opcode.As we can see,
implementation
andsalt
can be seen in memory, malicious users can monitor the two parameters and run with OpenZeppelinClones#cloneDeterministic
function directly to create the address, such that thePanopticFactory#deployNewPool
tx would be failed because the pool's address already exist in ethereum account's db, so the later actionnewPoolContract#startPool
can not be executed.Tools Used
vscode
Recommended Mitigation Steps
Consider predicting the pool's address and use
abi.encode(nonce, salt)
as salt before deploy the pool, if the pool's address existed, increase thenonce
and then deploy the pool again.Assessed type
DoS
The text was updated successfully, but these errors were encountered: