diff --git a/.env.example b/.env.example index d3cc417..9845036 100644 --- a/.env.example +++ b/.env.example @@ -1,34 +1,44 @@ -# Test mode: -# "local" will redeploy OSx contracts, +# Fork Test mode: # "fork-deploy" will run against the live network fork, deploying new contracts via a new instance of the factory # "fork-existing" will run against the live network fork, using the existing factory & therefore the existing contracts -# Local is not yet supported as requires further mocking of OSx -TEST_MODE="fork-deploy" -TOKEN_TEST_WHALE="0x" # for fork testing, if you need to distribute tokens, pick a whale -FACTORY="0x26afd02483951953B0F8A21123169cf7747CA8e2" +FORK_TEST_MODE="fork-deploy" + +# With false, the script will deploy mock tokens with open mint functions +DEPLOY_AS_PRODUCTION=false + +# If deploying against a fork, pass the address of a large token holder who will be +# impersonated to distribute tokens to addresses inside test cases +# the whale should have >= 3000 tokens +TOKEN_TEST_WHALE="0x" + +# If the factory singleton is deployed, pass the address. "Fork existing" mode will use this previously +# deployed factory, and "fork deploy" will deploy a new factory instance +FACTORY="0x0000000000000000000000000000000000000000" # NETWORK AND DEPLOYMENT WALLET DEPLOYMENT_PRIVATE_KEY="..." -ALCHEMY_API_KEY="..." -# note - including this can slow down forge -ETHERSCAN_API_KEY="..." NETWORK="sepolia" -# With false, the script will deploy mock tokens -DEPLOY_AS_PRODUCTION=true -MULTISIG_MEMBERS_JSON_FILE_NAME="/script/multisig-members.json" +# API Keys (optional) +# Note that having these active will slow down unit tests even when not needed +# So recommended to only activate when needed +# ETHERSCAN_API_KEY="..." +# ALCHEMY_API_KEY="..." + # MULTISIG PARAMETERS -MIN_APPROVALS="5" # How many multisig approvals are required +# define a list of multisig members - said multisig will be assigned administrator roles of the ve contracts +MULTISIG_MEMBERS_JSON_FILE_NAME="/script/multisig-members.json" +MIN_APPROVALS="1" # How many multisig approvals are required MULTISIG_PROPOSAL_EXPIRATION_PERIOD="864000" # How long until a pending proposal expires (10 days) # GAUGE VOTER PARAMETERS # The token to be used for the escrow -TOKEN1_ADDRESS="0xdc518215FCbeB2b641073F4387895E64d65D51fB" +TOKEN1_ADDRESS="0x0000000000000000000000000000000000000000" VE_TOKEN1_NAME="Voting Escrow Token 1" VE_TOKEN1_SYMBOL="veTK1" -# Additional tokens +# Additional tokens these will have secondary escrow contracts TOKEN2_ADDRESS="0x0000000000000000000000000000000000000000" # Ignored if 0x0 VE_TOKEN2_NAME="Voting Escrow Token 2" VE_TOKEN2_SYMBOL="veTK2" @@ -43,7 +53,7 @@ WARMUP_PERIOD="259200" # 3 days COOLDOWN_PERIOD="259200" # 3 days # Min seconds a user must have locked in escrow before they can queue an exit -MIN_LOCK_DURATION="4838400" # 8 weeks +MIN_LOCK_DURATION="3600" # 1 hour # Prevent voting until manually activated by the multisig VOTING_PAUSED=true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 130a421..9a6b3c7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,5 +36,5 @@ jobs: - name: Run Forge tests run: | - forge test -vvv + forge test --no-match-path "test/fork/**/*.sol" -vvv id: test diff --git a/AUDITORS_README.md b/AUDITORS_README.md deleted file mode 100644 index d4c772e..0000000 --- a/AUDITORS_README.md +++ /dev/null @@ -1,9 +0,0 @@ -Audit scope is all files in the src folder. The `ProxyLib.sol` is a pre-audited contract unchanged from Aragon OSx and we do not require any further reviews. - -## Curve conventions - -QuadraticIncreasingEscrow attempts to follow a generalised structure that can work for both increasing curves and decreasing curves. Because of this, certain functions have limited use in the current, increasing case: - -- It's not possible to increase a lock qty, hence `oldLocked` is not used -- Binary searching through user points is somewhat redundant given the low number of possible locks -- We assume that the calling contract aligns checkpoints with the checkpoint epoch. diff --git a/Makefile b/Makefile index 8371f5a..6be48c6 100644 --- a/Makefile +++ b/Makefile @@ -3,25 +3,48 @@ # (-include to ignore error if it does not exist) -include .env -# env var check -check-env :; echo $(ETHERSCAN_API_KEY) - # linux: allow shell scripts to be executed allow-scripts:; chmod +x ./coverage.sh +# init the repo +install :; make allow-scripts && forge build + # create an HTML coverage report in ./report (requires lcov & genhtml) coverage:; ./coverage.sh + # +# run unit tests +test-unit :; forge test --no-match-path "test/fork/**/*.sol" -# init the repo -install :; make allow-scripts && make coverage +#### Fork testing #### -# tests +# Fork testing - mode sepolia +ft-mode-sepolia-fork :; forge test --match-contract TestE2EV2 \ + --rpc-url https://sepolia.mode.network \ + -vv + +# Fork testing - mode mainnet +ft-mode-fork :; forge test --match-contract TestE2EV2 \ + --rpc-url https://mainnet.mode.network/ \ + -vvvvv -test-unit :; forge test --no-match-contract "TestE2EV2" -w -tu :; make test-unit +# Fork testing - holesky +ft-holesky-fork :; forge test --match-contract TestE2EV2 \ + --rpc-url https://holesky.drpc.org \ + -vvvvv + +# Fork testing - sepolia +ft-sepolia-fork :; forge test --match-contract TestE2EV2 \ + --rpc-url https://sepolia.drpc.org \ + -vvvvv + +# Fork testing - mainnet +ft-mainnet-fork :; forge test --match-contract TestE2EV2 \ + --rpc-url https://eth.llamarpc.com \ + --fork-block-number 20890902 \ + -vvvvv +#### Deployments #### -# deployments deploy-preview-mode-sepolia :; forge script script/Deploy.s.sol:Deploy \ --rpc-url https://sepolia.mode.network \ --private-key $(DEPLOYMENT_PRIVATE_KEY) \ @@ -54,7 +77,6 @@ deploy-preview-holesky :; forge script script/Deploy.s.sol:Deploy \ --private-key $(DEPLOYMENT_PRIVATE_KEY) \ -vvvvv - deploy-holesky :; forge script script/Deploy.s.sol:Deploy \ --rpc-url https://holesky.drpc.org \ --private-key $(DEPLOYMENT_PRIVATE_KEY) \ @@ -89,30 +111,3 @@ deploy-sepolia :; forge script script/Deploy.s.sol:Deploy \ --etherscan-api-key $(ETHERSCAN_API_KEY) \ -vvvvv -# Fork testing -ft-mode-sepolia-fork :; forge test --match-contract TestE2EV2 \ - --rpc-url https://sepolia.mode.network \ - --fork-block-number 19911297 \ - -vv - -ft-mode-sepolia-fork-nocache :; forge test --match-contract TestE2EV2 \ - --rpc-url https://sepolia.mode.network \ - --fork-block-number 19911297 \ - --no-cache \ - -vv - -ft-mode-fork :; forge test --match-contract TestE2EV2 \ - --rpc-url https://mainnet.mode.network/ \ - --fork-block-number 13848964 \ - -vvvvv - - -ft-holesky-fork :; forge test --match-contract TestE2EV2 \ - --rpc-url https://holesky.drpc.org \ - --fork-block-number 2464835 \ - -vvvvv - -ft-mainnet-fork :; forge test --match-contract TestE2EV2 \ - --rpc-url https://eth.llamarpc.com \ - --fork-block-number 20890902 \ - -vvvvv diff --git a/README.md b/README.md index 7762dd9..d8092af 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,136 @@ # Aragon VE Governance Hub -# Contracts Overview +Welcome to Aragon's veGovernance Plugin - a flexible, modular and secure system which can be used to create custom DAOs that foster a strong alignment between token holders and capital flows. + +## Setup + +To get started, ensure that [Foundry](https://getfoundry.sh/) is installed on your computer, then copy `.env.example` into `.env` and define the parameters + +### Understanding `.env.example` + +The env.example file contains descriptions for all the initial settings. You don't need all of these right away but should review prior to fork tests and deployments + +## Using the Makefile + +The `Makefile` functions as a script runner for common tasks. It's recommended to start there. Ensure you have the required tools installed to run the `make` command on your system: + +```sh +# debian +sudo apt install build-essential + +# arch +sudo pacman -S base-devel + +# nix +nix-env -iA nixpkgs.gnumake + +# macOS +brew install make +``` + +Then run the commands as needed + +```sh +# Setup the repo +make install + +# run unit tests +make unit-test + +# generate coverage report in the `report` directory +# requires lcov and genhtml +# serve the report/index.html in browser to view +make coverage + +# the .env.example is set to work with sepolia +make ft-sepolia-fork +``` + +## Running fork tests + +Fork testing has 2 modes: + +1. "fork-deploy" will run against the live network fork, deploying new contracts via a new instance of the factory + +2. "fork-existing" will run against the live network fork, using the existing factory & therefore the existing contracts + +In both cases, you will need to find the correct Aragon OSx contracts for the chain you wish to fork against. These can be found in the [OSx commons repo](https://github.com/aragon/osx-commons/tree/main/configs/src/deployments/json) + +> If running frequent fork tests it's recommended you pass a block number to enable caching + +## Deployment + +Deployments are done using the deployment factory. This is a singleton contract that will: + +- Deploy all contracts +- Set permissions +- Transfer ownership to a freshly deployed multisig +- Store the addresses of the deployment in a single, queriable place. + +Check the `Makefile` for examples of deployments on different networks. + +### Deployment Checklist + +- [] I have reviewed the parameters for the veDAO I want to deploy +- [] I have reviewed the multisig file for the correct addresses + - [] I have ensured all multisig members have undergone a proper security review and are aware of the security implications of being on said multisig +- [] I have updated the `.env` with these parameters +- [] I have updated the `CurveConstantLib` and `Clock` with any new constants. +- [] All my unit tests pass +- [] I have run a fork test in `fork-deploy` mode against the OSx contracts on my target testnet +- [] I have deployed my contracts successfully to a target testnet +- [] I have confirmed my tests still work in `fork-existing` mode with the live tokens and the factory. +- [] I have run the same workflow against the mainnet I wish to deploy on +- [] I have previewed my deploy +- [] My deployer address is a fresh wallet or setup for repeat production deploys in a safe manner. +- [] My wallet has sufficient native token for gas + +**Puffer Only** + +- [] I have deployed the Router contract + +### Manual from the command line + +You can of course run all commands from the command line: + +```sh +# Load the env vars +source .env +``` + +```sh +# run unit tests +forge test --no-match-path "test/fork/**/*.sol" +``` + +```sh +# Set the right RPC URL +RPC_URL="https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}" +``` + +```sh +# Run the deployment script + +# If using Etherscan +forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify + +# If using BlockScout +forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify --verifier blockscout --verifier-url "https://sepolia.explorer.mode.network/api\?" +``` + +If you get the error Failed to get EIP-1559 fees, add `--legacy` to the command: + +```sh +forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify --legacy +``` + +If some contracts fail to verify on Etherscan, retry with this command: + +```sh +forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --verify --legacy --private-key "$DEPLOYMENT_PRIVATE_KEY" --resume +``` + +## Contracts Overview The primary contracts in the governance hub are found in the `src` directory. The key contracts include @@ -61,43 +191,3 @@ The main workflow in the Mode Governance build is as follows: ## Curve design To build a flexible approach to curve design, we reviewed implementations such as seen in Curve and Aerodrome and attempted to generalise to higher order polynomials [Details on the curve design research can be found here](https://github.com/jordaniza/ve-explainer/blob/main/README.md) - -## Deployment - -To deploy the DAO, ensure that [Foundry](https://getfoundry.sh/) is installed on your computer. - -1. Edit `script/multisig-members.json` with the list of addresses to set as signers -2. Run `forge build && forge test` -3. Copy `.env.example` into `.env` and define the parameters - -```sh -# Load the env vars -source .env -``` - -```sh -# Set the right RPC URL -RPC_URL="https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}" -``` - -```sh -# Run the deployment script - -# If using Etherscan -forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify - -# If using BlockScout -forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify --verifier blockscout --verifier-url "https://sepolia.explorer.mode.network/api\?" -``` - -If you get the error Failed to get EIP-1559 fees, add `--legacy` to the command: - -```sh -forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --broadcast --verify --legacy -``` - -If some contracts fail to verify on Etherscan, retry with this command: - -```sh -forge script --chain "$NETWORK" script/Deploy.s.sol:Deploy --rpc-url "$RPC_URL" --verify --legacy --private-key "$DEPLOYMENT_PRIVATE_KEY" --resume -``` diff --git a/audits/AUDIT_REPORT.md b/audits/AUDIT_REPORT.md new file mode 100644 index 0000000..f00c0df --- /dev/null +++ b/audits/AUDIT_REPORT.md @@ -0,0 +1,98 @@ +# Aragon Ve Governance Audit + +Aragon's first version of ve governance underwent 2 audits by Halborn and Blocksec, as well as an internal review by senior engineering in Aragon. The findings, changelog and associated PRs are included in the document below. + +1. [Summary of Changes](#summary-of-changes) +2. [Notes from the Halborn Audit](#notes-from-the-halborn-audit) + - [Critical and High Severity Issues](#critical-and-high-severity) + - [Other Severity Issues](#other-severity) + - [HAL-06 Issue](#hal-06) +3. [Notes from the BlocSec Audit](#notes-from-the-blocsec-audit) +4. [Notes from Aragon Internal Audit](#notes-from-aragon-internal-audit) + +# Summary of changes + +Audit scope is all files in the src folder. The `ProxyLib.sol` is a pre-audited contract unchanged from Aragon OSx and we do not require any further reviews. + +Changes have been added into a rollup commit https://github.com/aragon/ve-governance/pull/30 + +The git history of this commit has been carefully squashed to make it clean and easy to review the incremental changes added at each step. We propose going ahead with this. + +# Notes from the Halborn Audit + +https://www.halborn.com/portal/reports/ve-governance-hub + +## Critical and High Severity + +| Severity | Issue | Status | Comment or PR | +| -------- | ------------------------------------------------------------------------ | ---------- | ----------------------------------------------- | +| C | (HAL-13) Token ID reuse leads to protocol deadlock | Fixed | https://github.com/aragon/ve-governance/pull/3 | +| H | (HAL-14) Unsafe minting in Lock contract | Fixed | https://github.com/aragon/ve-governance/pull/4 | +| H | (HAL-15) Critical withdrawal blockage due to escrow address whitelisting | Fixed | https://github.com/aragon/ve-governance/pull/5 | +| H | (HAL-16) Potential token lock due to unrestricted escrow transfers | Fixed | https://github.com/aragon/ve-governance/pull/6 | +| H | (HAL-10) Unrestricted NFT contract change enables potential fund theft | Fixed | https://github.com/aragon/ve-governance/pull/6 | +| H | (HAL-12) Inaccurate voting power reporting after withdrawal initiation | Semi-Fixed | https://github.com/aragon/ve-governance/pull/22 | + +## Other Severity + +| Severity | Issue | Status | Comment or PR | +| -------- | ---------------------------------------------------------------------------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------- | +| I | (HAL-01/02) Naming issues with Clock contract | Fixed | https://github.com/aragon/ve-governance/pull/10 | +| L | (HAL-08) Shared role for pause and unpause functions | Acknowledged | Noted for future releases | +| I | 7.12 (HAL-22) Critical roles not assigned in contract setup | Fixed | https://github.com/aragon/ve-governance/pull/11 | +| I | 7.19 (HAL-05) Unnecessary calculation in checkpoint function (+other simple gas optimisations) | Fixed | https://github.com/aragon/ve-governance/pull/12 | +| I | 7.20 (HAL-20) Potentially unnecessary check in reset function | Fixed | https://github.com/aragon/ve-governance/pull/13 | +| I | 7.18 (HAL-19) Fee precision too high | Fixed + Revised | https://github.com/aragon/ve-governance/pull/14 | +| I | 7.17 (HAL-18) Redundant exit check and missing documentation in exit function | Acknowledged | Accepted the redundancy - we prefer to have the check in place given the critical nature of the exit queue | +| I | 7.16 (HAL-09) Unset dependencies may cause reverts and improper behavior | Acknowledged | Noted for future: implement a graceful and idomatic revert strategy. | +| I | 7.15 (HAL-07) Misleading variable name for user interaction tracking | Fixed | https://github.com/aragon/ve-governance/pull/15 | +| I | 7.13 (HAL-03) Lack of contract validation in initializer | Acknowledged | The DAO and deployers are responsible for ensuring they validate the contracts and can update if needed | +| I | 7.11 (HAL-21) Inconsistent voting power reporting in Reset event | Fixed | https://github.com/aragon/ve-governance/pull/16 | +| M | 7.8 (HAL-11) Incorrect balance tracking for non-standard ERC20 tokens | Fixed + Revised | https://github.com/aragon/ve-governance/pull/17 | +| L | 7.9 (HAL-17) Potential bypass of minimum lock time at checkpoint boundaries | Fixed | https://github.com/aragon/ve-governance/pull/25 | +| M | 7.7 (HAL-06) Checkpoint function allows non-chronological updates | Fixed | See [HAL-06 Below](#HAL-06) Fix is https://github.com/aragon/ve-governance/pull/26 | +| I | 7.14 (HAL-04) Unbounded warmup period can span multiple epochs | Semi-Fixed | https://github.com/aragon/ve-governance/pull/27 | + +- See the aragon section below for some consistent findings wrt strict inequalities which we have addressed + +### HAL-06 + +![image](https://github.com/user-attachments/assets/b211c368-2e14-4d80-a7f4-de7d1b83fbfb) + +# Notes from the BlockSec Audit + +https://docs.google.com/document/d/1bLOIahrZjzf7DrraT42F9mBiLwpn4b9_Npn3GJlK93M/ + +| Severity | Issue | Status | Comment or PR | +| -------- | ------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------ | +| H | Incorrect calculation of newTokenId in function `\_createLockFor()` | Fixed | https://github.com/aragon/ve-governance/pull/3 | +| U | Override function \_baseURI() for contract Lock | Acknowledged | Noted for future: have a proper Art Proxy or metadata proxy for the NFTs | +| U | Lack of checks in function setWhitelisted() | Fixed | https://github.com/aragon/ve-governance/pull/5 | +| U | Lack of refund method in contract VotingEscrow | Fixed | https://github.com/aragon/ve-governance/pull/6 | +| U | Use dedicated event for function enableTransfers() | Acknowledged | Happy to leave as the single event with the signalling address | + +# Notes from Aragon Internal Audit + +Aragon Audits were conducted by various team members. + +- @novaknole provided a [gist](https://gist.github.com/novaknole/53d1478a724ab707b2c39ad41f05a636) with _findings_ +- @brickpop @xavikh @carlosgj94 all contributed on an [internal audit document that you may not have access to](https://www.notion.so/aragonorg/ve-Internal-Review-641d2e99c53e4f2391821e6d3ef0673a) but which have been added as _Internal Review_ notes below. + +| Severity | Issue | Status | Comment or PR | +| -------- | ----------------------------------------------------------------------------------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------- | +| U | Finding 5: Fee percentage can be set by admin to 100% | Acknowledged | This is a trust vector of the protocol at this current time | +| U | Finding 4: Admin can update cooldown after users stake to prevent unlock near permanently | Acknowledged | This is a trust vector of the protocol at this current time | +| U | Finding 3: Choice of epoch duration can affect voting power due to FPA | Acknowledged | We acknowledge that choosing an appropriate epoch length + testing curves is important for FPA | +| U | Finding 2: Questions regarding the change in voting power over time | Resolved | These discussions were settled in private chats | +| U | Finding 1: Tokens that do not support `.decimals` are not supported | TBC | This check is potentially unneccessary https://github.com/aragon/ve-governance/pull/18 | +| U | Finding 7: SupportsInterface should include the interface Ids | Fixed | https://github.com/aragon/ve-governance/pull/20 | +| U | Finding 8: For loop in `ownedTokens` can be used as a DoS vector | Fixed | https://github.com/aragon/ve-governance/pull/24 | +| U | Internal Review 1: metadata hash does nothing in the gauges | Fixed | https://github.com/aragon/ve-governance/pull/21 | +| U | Internal Review 2: opportunities to compress storage with structs | Part Fixed | https://github.com/aragon/ve-governance/pull/23 | +| U | Internal Review 3: use strict inequalities where possible | Fixed | https://github.com/aragon/ve-governance/pull/28 | +| U | Internal Review 4: Check \_\_gap values to ensure they align with occupied storage slots | Fixed | https://github.com/aragon/ve-governance/pull/30 review | +| U | Internal Review: can use early returns in the clock contract | Acknowledged | Minor optimisation - can be added as a refinement feature later | +| U | Internal Review: Log the timestamp of checkpoints | Fixed | https://github.com/aragon/ve-governance/pull/22 | +| U | Internal Review: x.pow(2) is less precise and more expensive than x.mul(x) | Fixed | https://github.com/aragon/ve-governance/pull/12 | +| U | Internal Review: passing very small weights to gauges leads to precision loss | Acknowledged | In this build, voting is signalling only, so rounding errors are ok for small values, we may wish to reevaluate with onchain voting | +| U | Internal Review: Small deposits and fees will round to zero in the exit queue | Acknowledged | Fee rounding to zero simply won't charge a fee, we don't think it's a major issue + we can enforce a min deposit | diff --git a/audits/audit_halborn.pdf b/audits/audit_halborn.pdf new file mode 100644 index 0000000..2aa81a9 Binary files /dev/null and b/audits/audit_halborn.pdf differ diff --git a/coverage.sh b/coverage.sh index dbc76ba..34ba4be 100755 --- a/coverage.sh +++ b/coverage.sh @@ -1,9 +1,9 @@ #!/bin/sh echo "Removing test, script and src/escrow/increasing/delegation and proxylib files from coverage report" -forge coverage --report lcov && - lcov --remove ./lcov.info -o ./lcov.info.pruned \ - 'test/**/*.sol' 'script/**/*.sol' 'test/*.sol' \ - 'script/*.sol' 'src/escrow/increasing/delegation/*.sol' \ - 'src/libs/ProxyLib.sol' && - genhtml lcov.info.pruned -o report --branch-coverage +forge coverage --no-match-path "test/fork/**/*.sol" --report lcov && + lcov --remove ./lcov.info -o ./lcov.info.pruned \ + 'test/**/*.sol' 'script/**/*.sol' 'test/*.sol' \ + 'script/*.sol' 'src/escrow/increasing/delegation/*.sol' \ + 'src/libs/ProxyLib.sol' && + genhtml lcov.info.pruned -o report --branch-coverage diff --git a/foundry.toml b/foundry.toml index 830a338..45dd58f 100644 --- a/foundry.toml +++ b/foundry.toml @@ -16,6 +16,7 @@ solc = "0.8.17" src = "src" test = "test" verbosity = 3 +evm_version = "shanghai" [profile.ci] fuzz = { runs = 10_000 } @@ -34,6 +35,3 @@ polygon = "https://polygon-mainnet.infura.io/v3/${API_KEY_INFURA}" sepolia = "https://sepolia.infura.io/v3/${API_KEY_INFURA}" -[profile.mode_sepolia_test] -rpc_url = "https://sepolia.mode.network" -fork_block_number = 19911297 \ No newline at end of file diff --git a/script/DeployRouter.s.sol b/script/DeployRouter.s.sol new file mode 100644 index 0000000..b4dff2f --- /dev/null +++ b/script/DeployRouter.s.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.17; + +import {Script, console} from "forge-std/Script.sol"; +import {VotingEscrow} from "src/voting/SimpleGaugeVoterSetup.sol"; +import {GaugesDaoFactory, GaugePluginSet, Deployment} from "src/factory/GaugesDaoFactory.sol"; + +contract Router { + address public escrow; + + constructor(address _escrow) { + escrow = _escrow; + } + + function getLocked(uint _tokenId) public view returns (uint256) { + return VotingEscrow(escrow).locked(_tokenId).amount; + } + + function getTotalLocked(address _user) public view returns (uint256) { + uint256[] memory ids = VotingEscrow(escrow).ownedTokens(_user); + + uint256 totalLocked = 0; + + for (uint i = 0; i < ids.length; i++) { + totalLocked += VotingEscrow(escrow).locked(ids[i]).amount; + } + return totalLocked; + } +} + +contract DeployRouter is Script { + function run() public { + address factoryAddress = vm.envAddress("FACTORY"); + if (factoryAddress == address(0)) { + revert("Factory address not set"); + } + GaugesDaoFactory factory = GaugesDaoFactory(factoryAddress); + + // set our contracts + Deployment memory deployment = factory.getDeployment(); + + // if deploying multiple tokens, you can adjust the index here + GaugePluginSet memory pluginSet = deployment.gaugeVoterPluginSets[0]; + + vm.startBroadcast(vm.envUint("DEPLOYMENT_PRIVATE_KEY")); + { + Router router = new Router({_escrow: address(pluginSet.votingEscrow)}); + console.log("Router deployed at:", address(router)); + } + vm.stopBroadcast(); + } +} diff --git a/test/e2eV2.t.sol b/test/fork/e2eV2.t.sol similarity index 99% rename from test/e2eV2.t.sol rename to test/fork/e2eV2.t.sol index 94fdee5..cf92ea5 100644 --- a/test/e2eV2.t.sol +++ b/test/fork/e2eV2.t.sol @@ -9,7 +9,7 @@ import {DAO} from "@aragon/osx/core/dao/DAO.sol"; import {Multisig, MultisigSetup} from "@aragon/multisig/MultisigSetup.sol"; import {UUPSUpgradeable as UUPS} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import "./helpers/OSxHelpers.sol"; +import "../helpers/OSxHelpers.sol"; import {Clock} from "@clock/Clock.sol"; import {IEscrowCurveTokenStorage} from "@escrow-interfaces/IEscrowCurveIncreasing.sol"; @@ -1349,7 +1349,7 @@ contract TestE2EV2 is Test, IWithdrawalQueueErrors, IGaugeVote, IEscrowCurveToke //////////////////////////////////////////////////////////////*/ function _getTestMode() internal view returns (TestMode) { - string memory mode = vm.envString("TEST_MODE"); + string memory mode = vm.envString("FORK_TEST_MODE"); if (keccak256(abi.encodePacked(mode)) == keccak256(abi.encodePacked("fork-deploy"))) { return TestMode.ForkDeploy; } else if ( @@ -1357,7 +1357,7 @@ contract TestE2EV2 is Test, IWithdrawalQueueErrors, IGaugeVote, IEscrowCurveToke ) { return TestMode.ForkExisting; } else if (keccak256(abi.encodePacked(mode)) == keccak256(abi.encodePacked("local"))) { - return TestMode.Local; + revert("Local mode not yet supported"); } else { revert("Invalid test mode - valid options are fork-deploy, fork-existing, local"); } @@ -1427,22 +1427,12 @@ contract TestE2EV2 is Test, IWithdrawalQueueErrors, IGaugeVote, IEscrowCurveToke } /// depending on the network, we need different approaches to mint tokens - /// on a fork function _resolveMintTokens() internal returns (bool) { + // if deploying a mock, mint will be open try token.mint(address(distributor), 3_000 ether) { return true; } catch {} - // next check if ownable - we can spoof this - (bool success, bytes memory data) = address(token).call(abi.encodeWithSignature("owner()")); - - if (success) { - address owner = abi.decode(data, (address)); - vm.prank(owner); - token.mint(address(distributor), 3_000 ether); - return true; - } - // next we just try a good old fashioned find a whale and rug them in the test address whale = vm.envAddress("TOKEN_TEST_WHALE"); if (whale == address(0)) {