Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
c13ddc2
initial reduction
bulkcade Mar 7, 2025
825b36c
fix tests
bulkcade Mar 7, 2025
a243a7c
cherry pick factory splitter from monorepo main 4df25be3bab3f1a0e8247…
bulkcade Feb 27, 2025
e949623
deploy test
bulkcade Feb 26, 2025
8206067
further deploy
bulkcade Mar 6, 2025
41f9387
further deployment test progress
bulkcade Mar 10, 2025
bacfdf2
slight tidy up and new deploy antimom test
bulkcade Mar 12, 2025
fcefe6b
audit review md file
bulkcade Mar 11, 2025
a2121c1
initialise script
bulkcade Mar 18, 2025
19fdbf1
different pool_checks
bulkcade Apr 3, 2025
0ce23c9
push hardhat optimiser runs for further efficiencies
bulkcade Mar 12, 2025
92d1d9f
add view functions for intermediate states to help monitoring and DR …
bulkcade Apr 3, 2025
3f5690a
new scripts
bulkcade Apr 7, 2025
0203236
Merge remote-tracking branch 'origin/main' into deploy-sepolia
bulkcade Apr 8, 2025
b7dba5d
restructure scripts location for public use
bulkcade Apr 8, 2025
0c59961
fixes to imports
bulkcade Apr 9, 2025
c05839a
Merge remote-tracking branch 'origin/main' into deploy-sepolia
bulkcade Apr 11, 2025
0893df6
new test net push
bulkcade Apr 11, 2025
0811c3a
Merge remote-tracking branch 'origin/main' into deploy-sepolia
bulkcade Apr 15, 2025
2a8cad4
updates to scripts
bulkcade Apr 18, 2025
1331d6d
additional diagnostics
bulkcade Apr 23, 2025
cd972e8
new update weight runner
bulkcade Apr 23, 2025
d2af47a
updated diagnostic scripts
bulkcade Apr 25, 2025
ee26aa9
fix
bulkcade Apr 25, 2025
93c5342
add liquidity permit2
bulkcade Apr 25, 2025
143f1e8
update initialise pool
MatthewWilletts Apr 27, 2025
6929a53
updated scripts
bulkcade Apr 27, 2025
5bba951
bump liquiditiy depoloyment script
MatthewWilletts Apr 28, 2025
5d75437
Merge branch 'deploy-sepolia' of github.com:QuantAMMProtocol/QuantAMM…
MatthewWilletts Apr 28, 2025
ee458a1
update pool address to mainnet safe haven pool, set deposit amounts to 0
MatthewWilletts Apr 29, 2025
de3ce14
Merge remote-tracking branch 'origin/main' into deploy-sepolia
bulkcade May 6, 2025
0bc202d
CODEHAWKS-H-02
bulkcade Jun 12, 2025
c742f09
H-06 admin fee divide
bulkcade Jun 17, 2025
39322c6
H-07 send to owner not contract address
bulkcade Jun 17, 2025
82e78e6
H-11 proportional to deposits now
bulkcade Jun 17, 2025
b0e8f77
M-1 fix setters for uplift fee
bulkcade Jun 17, 2025
1ca2089
M-03 fix scaling for computation
bulkcade Jun 17, 2025
b698ec0
M-04 restrict transfer to sell
bulkcade Jun 17, 2025
de95ff3
M-06 add check that recipient does not have more than 100 deposits
bulkcade Jun 17, 2025
01c89a3
M-08 add maximum fee take
bulkcade Jun 17, 2025
9d62582
M-13 retain original fee level on transfer
bulkcade Jun 17, 2025
f37a650
M-18 get correct swap fee take
bulkcade Jun 17, 2025
2668238
L-14 change number to timestamp tracking
bulkcade Jun 17, 2025
0cdf0bb
restrict to 1 deposit per block
bulkcade Jun 17, 2025
8c58044
use errors instead of requires
bulkcade Jun 17, 2025
d02671d
fix ownership tests
bulkcade Jun 18, 2025
56264ba
fix tests and tweaks to logic
bulkcade Jun 26, 2025
3f1a7be
remove build warnings
bulkcade Jun 26, 2025
e7b3dcc
fuzz test progress
bulkcade Jun 27, 2025
259cf09
add debug version
bulkcade Jul 4, 2025
9651faf
uplift fuzz progress
bulkcade Jul 9, 2025
44d2961
fixes to rounding given fuzz tests, convert fees to be stored in 18dp…
bulkcade Jul 15, 2025
2688629
add fuzz and move tests
bulkcade Jul 16, 2025
89656ba
fix expectations
bulkcade Jul 16, 2025
719f92b
tidy up
bulkcade Jul 21, 2025
db903ca
merge from main
bulkcade Sep 29, 2025
0c235c2
fix build
bulkcade Sep 29, 2025
9693ffa
stack too deep in the tests
bulkcade Sep 30, 2025
168f211
fix tests
bulkcade Sep 30, 2025
e52af3d
formatting
bulkcade Sep 30, 2025
befc311
unbalanced add debug
bulkcade Oct 2, 2025
a08cd72
change to send to for the admin
bulkcade Oct 7, 2025
828fbad
uplift example
bulkcade Oct 10, 2025
e5bb5b4
uplift fuzz correction
bulkcade Oct 20, 2025
4b3c605
add too fast withdrawal
bulkcade Oct 23, 2025
52f6815
fix test
bulkcade Oct 24, 2025
5687e7c
remove deployment folder
bulkcade Nov 10, 2025
02af346
trim logic not related to uplift hook
bulkcade Nov 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/pool-hooks/contracts/hooks-quantamm/LPNFT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ contract LPNFT is ERC721 {
previousOwner = super._update(to, tokenId, auth);
//_update is called during mint, burn and transfer. This functionality is only for transfer
if (to != address(0) && previousOwner != address(0)) {
require(previousOwner != to, "CANNOT_TRANSFER_TO_SELF");
//if transfering the record in the vault needs to be changed to reflect the change in ownership
router.afterUpdate(previousOwner, to, tokenId);
}
Expand Down
354 changes: 225 additions & 129 deletions pkg/pool-hooks/contracts/hooks-quantamm/UpliftOnlyExample.sol

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pkg/pool-hooks/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ remappings = [
]
optimizer = true
optimizer_runs = 999
solc_version = '0.8.26'
solc_version = '0.8.27'
auto_detect_solc = false
evm_version = 'cancun'
ignored_error_codes = [2394, 5574, 3860] # Transient storage, code size
Expand Down
1,420 changes: 782 additions & 638 deletions pkg/pool-hooks/test/foundry/UpliftExample.t.sol

Large diffs are not rendered by default.

207 changes: 207 additions & 0 deletions pkg/pool-hooks/test/foundry/UpliftExampleCodeHawkTests.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity ^0.8.24;

import { BaseVaultTest } from "@balancer-labs/v3-vault/test/foundry/utils/BaseVaultTest.sol";
import { QuantAMMWeightedPool, IQuantAMMWeightedPool } from "pool-quantamm/contracts/QuantAMMWeightedPool.sol";
import {QuantAMMWeightedPoolFactory} from "pool-quantamm/contracts/QuantAMMWeightedPoolFactory.sol";
import { UpdateWeightRunner, IUpdateRule } from "pool-quantamm/contracts/UpdateWeightRunner.sol";
import { MockChainlinkOracle } from "./utils/MockChainlinkOracles.sol";
import "@balancer-labs/v3-interfaces/contracts/pool-quantamm/OracleWrapper.sol";
import { IUpdateRule } from "pool-quantamm/contracts/rules/UpdateRule.sol";
import { MockMomentumRule } from "pool-quantamm/contracts/mock/mockRules/MockMomentumRule.sol";
import { UpliftOnlyExample } from "../../contracts/hooks-quantamm/UpliftOnlyExample.sol";
import { IPermit2 } from "permit2/src/interfaces/IPermit2.sol";
import { IVault } from "@balancer-labs/v3-interfaces/contracts/vault/IVault.sol";
import { IVaultAdmin } from "@balancer-labs/v3-interfaces/contracts/vault/IVaultAdmin.sol";
import { PoolRoleAccounts, TokenConfig, HooksConfig } from "@balancer-labs/v3-interfaces/contracts/vault/VaultTypes.sol";
import { IWETH } from "@balancer-labs/v3-interfaces/contracts/solidity-utils/misc/IWETH.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { Router } from "@balancer-labs/v3-vault/contracts/Router.sol";
import {console} from "forge-std/console.sol";

contract UpliftExampleCode is BaseVaultTest { // use default dai, usdc, weth and mock oracle
//address daiOnETH = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
//address usdcOnETH = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
//address wethOnETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
uint256 internal daiIdx;
uint256 internal usdcIdx;

uint256 SWAP_FEE_PERCENTAGE = 10e16;

address quantAdmin = makeAddr("quantAdmin");
address owner = makeAddr("owner");
address poolCreator = makeAddr("poolCreator");
address liquidityProvider1 = makeAddr("liquidityProvider1");
address liquidityProvider2 = makeAddr("liquidityProvider2");
address attacker = makeAddr("attacker");
//address usdcUsd = 0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6;
//address daiUsd = 0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9;
//address ethOracle = 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419;

QuantAMMWeightedPool public weightedPool;
QuantAMMWeightedPoolFactory public weightedPoolFactory;
UpdateWeightRunner public updateWeightRunner;
MockChainlinkOracle mockOracledai;
MockChainlinkOracle mockOracleusdc;
MockChainlinkOracle ethOracle;
Router externalRouter;

UpliftOnlyExample upLifthook;

function setUp() public override {
vm.warp(block.timestamp + 3600);
mockOracledai = new MockChainlinkOracle(1e18, 0);
mockOracleusdc = new MockChainlinkOracle(1e18, 0);
ethOracle = new MockChainlinkOracle(2000e18, 0);
updateWeightRunner = new UpdateWeightRunner(quantAdmin, address(ethOracle));

vm.startPrank(quantAdmin);
updateWeightRunner.addOracle(OracleWrapper(address(mockOracledai)));
updateWeightRunner.addOracle(OracleWrapper(address(mockOracleusdc)));
vm.stopPrank();

super.setUp();

(daiIdx, usdcIdx) = getSortedIndexes(address(dai), address(usdc));

vm.prank(quantAdmin);
updateWeightRunner.setApprovedActionsForPool(pool, 2);
}

function createHook() internal override returns (address) {
// Create the factory here, because it needs to be deployed after the Vault, but before the hook contract.
weightedPoolFactory = new QuantAMMWeightedPoolFactory(IVault(address(vault)), 365 days, "Factory v1", "Pool v1", address(updateWeightRunner));
// lp will be the owner of the hook. Only LP is able to set hook fee percentages.
vm.prank(quantAdmin);
upLifthook = new UpliftOnlyExample(IVault(address(vault)), IWETH(weth), IPermit2(permit2), 100, 100, address(updateWeightRunner), "version 1", "lpnft", "LP-NFT");
return address(upLifthook);
}

function _createPool(
address[] memory tokens,
string memory label
) internal override returns (address newPool, bytes memory poolArgs) {
QuantAMMWeightedPoolFactory.CreationNewPoolParams memory poolParams = _createPoolParams(tokens);

(newPool, poolArgs) = weightedPoolFactory.create(poolParams);
vm.label(newPool, label);

authorizer.grantRole(vault.getActionId(IVaultAdmin.setStaticSwapFeePercentage.selector), quantAdmin);
vm.prank(quantAdmin);
vault.setStaticSwapFeePercentage(newPool, SWAP_FEE_PERCENTAGE);
}

function _createPoolParams(address[] memory tokens) internal returns (QuantAMMWeightedPoolFactory.CreationNewPoolParams memory retParams) {
PoolRoleAccounts memory roleAccounts;

uint64[] memory lambdas = new uint64[](1);
lambdas[0] = 0.2e18;

int256[][] memory parameters = new int256[][](1);
parameters[0] = new int256[](1);
parameters[0][0] = 0.2e18;

address[][] memory oracles = new address[][](2);
oracles[0] = new address[](1);
oracles[0][0] = address(mockOracledai);
oracles[1] = new address[](1);
oracles[1][0] = address(mockOracleusdc);

uint256[] memory normalizedWeights = new uint256[](2);
normalizedWeights[0] = uint256(0.5e18);
normalizedWeights[1] = uint256(0.5e18);

IERC20[] memory ierctokens = new IERC20[](2);
for (uint256 i = 0; i < tokens.length; i++) {
ierctokens[i] = IERC20(tokens[i]);
}

int256[] memory initialWeights = new int256[](2);
initialWeights[0] = 0.5e18;
initialWeights[1] = 0.5e18;

int256[] memory initialMovingAverages = new int256[](2);
initialMovingAverages[0] = 0.5e18;
initialMovingAverages[1] = 0.5e18;

int256[] memory initialIntermediateValues = new int256[](2);
initialIntermediateValues[0] = 0.5e18;
initialIntermediateValues[1] = 0.5e18;

TokenConfig[] memory tokenConfig = vault.buildTokenConfig(ierctokens);

retParams = QuantAMMWeightedPoolFactory.CreationNewPoolParams(
"Pool With Donation",
"PwD",
tokenConfig,
normalizedWeights,
roleAccounts,
0.02e18,
address(poolHooksContract),
true,
true, // Do not disable unbalanced add/remove liquidity
0x0000000000000000000000000000000000000000000000000000000000000000,
initialWeights,
IQuantAMMWeightedPool.PoolSettings(
ierctokens,
IUpdateRule(new MockMomentumRule(owner)),
oracles,
60,
lambdas,
0.2e18,
0.2e18,
0.3e18,
parameters,
poolCreator
),
initialMovingAverages,
initialIntermediateValues,
3600,
16,//able to set weights
new string[][](0)
);
}

function testRemoveLiquidityUplift() public {
addLiquidity();

uint256[] memory minAmountsOut = new uint256[](2);
minAmountsOut[0] = 1;
minAmountsOut[1] = 1;

vm.prank(liquidityProvider1);
vm.warp(block.timestamp + 1 days); // ensure time has passed for fee calc
UpliftOnlyExample(payable(poolHooksContract)).removeLiquidityProportional(2e18, minAmountsOut, true, pool);
}

function addLiquidity() public {
deal(address(dai), liquidityProvider1, 100e18);
deal(address(usdc), liquidityProvider1, 100e18);

uint256[] memory maxAmountsIn = new uint256[](2);
maxAmountsIn[0] = 2.1e18;
maxAmountsIn[1] = 2.1e18;
uint256 exactBptAmountOut = 2e18;

vm.startPrank(liquidityProvider1);
IERC20(address(dai)).approve(address(permit2), 100e18);
IERC20(address(usdc)).approve(address(permit2), 100e18);
permit2.approve(address(dai), address(poolHooksContract), 100e18, uint48(block.timestamp));
permit2.approve(address(usdc), address(poolHooksContract), 100e18, uint48(block.timestamp));
UpliftOnlyExample(payable(poolHooksContract)).addLiquidityProportional(pool, maxAmountsIn, exactBptAmountOut, false, abi.encodePacked(liquidityProvider1));
vm.stopPrank();

deal(address(dai), liquidityProvider2, 100e18);
deal(address(usdc), liquidityProvider2, 100e18);

vm.startPrank(liquidityProvider2);
IERC20(address(dai)).approve(address(permit2), 100e18);
IERC20(address(usdc)).approve(address(permit2), 100e18);
permit2.approve(address(dai), address(poolHooksContract), 100e18, uint48(block.timestamp));
permit2.approve(address(usdc), address(poolHooksContract), 100e18, uint48(block.timestamp));
UpliftOnlyExample(payable(poolHooksContract)).addLiquidityProportional(pool, maxAmountsIn, exactBptAmountOut, false, abi.encodePacked(liquidityProvider2));
vm.stopPrank();

console.log("Liquidity added");
}
}
Loading
Loading