Skip to content
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

Deploy/puffer #36

Open
wants to merge 17 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 31 additions & 0 deletions DEPLOYMENT_ADDRESSES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Deployment Addresses Puffer Mainnet

```yaml
Deploying from: 0x36b6fE474dAD8e822d3133B76E9adA671E75eC86

Chain ID: 1
Factory: 0xfbF3B5Fa2380C77a6ac255A8e19a142490601767

DAO: 0x5dEA8E499b05de8F86E7521F039770268055b23F

Plugins
- Multisig plugin: 0xA303C435563a4544a84E26501F4666346Ff73a0d

Gauge voter plugin: 0x69E8D5151d71d4cde35b5076aF3023C7D54d379E
Curve: 0xAaAb5528aFf964CEAc972E39c2357c2D503A9196
Exit Queue: 0xD9C2d314E29F1940d2a65A691881F0950fE4A455
Voting Escrow: 0xA55eD5808aeCDF23AE3782C1443185f5D2363ce7
Clock: 0x8BCDf6291F251cF8eCf5ac06bFc4A2B02Ecc26eB
NFT Lock: 0x1b6ec227ceBeC25118270efbb4b67642fc29965E

Plugin repositories
- Multisig plugin repository (existing): 0x8c278e37D0817210E18A7958524b7D0a1fAA6F7b
- Gauge voter plugin repository: 0xa10192700F6c3A0ee0deAA2EE72A91916a4CBb70

Router
- 0xD33340fb9C8c2aEBC6922552bf3bC268a3682696


```

The deployment addresses can also be verified [on the factory contract via Etherscan](https://etherscan.io/address/0xfbf3b5fa2380c77a6ac255a8e19a142490601767#readContract)
62 changes: 62 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,31 @@ 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-mainnet.g.alchemy.com/v2/$(ALCHEMY_API_KEY) \
-vvvvv

#### Deployments ####

deploy-preview-mainnet :; forge script script/Deploy.s.sol:Deploy \
--rpc-url https://eth-mainnet.g.alchemy.com/v2/$(ALCHEMY_API_KEY) \
--private-key $(DEPLOYMENT_PRIVATE_KEY) \
-vvvvv

deploy-mainnet :; forge script script/Deploy.s.sol:Deploy \
--rpc-url https://eth-mainnet.g.alchemy.com/v2/$(ALCHEMY_API_KEY) \
--slow \
--resume \
--private-key $(DEPLOYMENT_PRIVATE_KEY) \
--verify \
--etherscan-api-key $(ETHERSCAN_API_KEY) \
-vvvvv

log-mainnet :; forge script Logger \
--rpc-url https://eth-mainnet.g.alchemy.com/v2/$(ALCHEMY_API_KEY) \
-vvvvv

deploy-preview-mode-sepolia :; forge script script/Deploy.s.sol:Deploy \
--rpc-url https://sepolia.mode.network \
--private-key $(DEPLOYMENT_PRIVATE_KEY) \
Expand Down Expand Up @@ -66,3 +89,42 @@ deploy-mode :; forge script script/Deploy.s.sol:Deploy \
--etherscan-api-key $(ETHERSCAN_API_KEY) \
-vvv

deploy-preview-holesky :; forge script script/Deploy.s.sol:Deploy \
--rpc-url https://holesky.drpc.org \
--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) \
--broadcast \
--verify \
--etherscan-api-key $(ETHERSCAN_API_KEY) \
-vvv

deploy-preview-sepolia :; forge script script/Deploy.s.sol:Deploy \
--rpc-url https://1rpc.io/sepolia \
--private-key $(DEPLOYMENT_PRIVATE_KEY) \
-vvvvv

router-preview-sepolia :; forge script DeployRouter \
--rpc-url https://1rpc.io/sepolia \
--private-key $(DEPLOYMENT_PRIVATE_KEY) \
-vvvvv

router-sepolia :; forge script DeployRouter \
--rpc-url https://1rpc.io/sepolia \
--private-key $(DEPLOYMENT_PRIVATE_KEY) \
--broadcast \
--verify \
--etherscan-api-key $(ETHERSCAN_API_KEY) \
-vvvvv

deploy-sepolia :; forge script script/Deploy.s.sol:Deploy \
--rpc-url https://1rpc.io/sepolia \
--private-key $(DEPLOYMENT_PRIVATE_KEY) \
--broadcast \
--verify \
--etherscan-api-key $(ETHERSCAN_API_KEY) \
-vvvvv

29 changes: 17 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

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.

The mainnet deployment addresses can be found [here](./DEPLOYMENT_ADDRESSES.md).

## 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
Expand Down Expand Up @@ -71,19 +73,22 @@ 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
- [x] I have reviewed the parameters for the veDAO I want to deploy
- [x] I have reviewed the multisig file for the correct addresses
- [x] I have ensured all multisig members have undergone a proper security review and are aware of the security implications of being on said multisig
- [x] I have updated the `.env` with these parameters
- [x] I have updated the `CurveConstantLib` and `Clock` with any new constants.
- [x] All my unit tests pass
- [x] I have run a fork test in `fork-deploy` mode against the OSx contracts on my target testnet
- [x] I have deployed my contracts successfully to a target testnet
- [x] I have previewed my deploy
- [x] My deployer address is a fresh wallet or setup for repeat production deploys in a safe manner.
- [x] My wallet has sufficient native token for gas
- [] 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

Expand Down
52 changes: 52 additions & 0 deletions script/DeployRouter.s.sol
Original file line number Diff line number Diff line change
@@ -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();
}
}
22 changes: 11 additions & 11 deletions src/libs/CurveConstantLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ pragma solidity ^0.8.0;

/// @title CurveConstantLib
/// @notice Precomputed coefficients for escrow curve
/// This curve implementation is a quadratic curve of the form y = (1/7)t^2 + (2/7)t + 1
/// Which is a transformation of the quadratic curve y = (x^2 + 6)/7
/// That starts with 1 unit of voting in period 1, and max 6 in period 6.
/// To use this in zero indexed time, with a per-second rate of increase,
/// we transform this to the polynomial y = (1/7)t^2 + (2/7)t + 1
/// where t = timestamp / 2_weeks (2 weeks is one period)
/// Below are the shared coefficients for the linear and quadratic terms
/// @dev This curve goes from 1x -> 2x voting power over a 2 year time horizon
/// Epochs are still 2 weeks long
library CurveConstantLib {
int256 internal constant SHARED_CONSTANT_COEFFICIENT = 1e18;
/// @dev 2 / (7 * 2_weeks) - expressed in fixed point
int256 internal constant SHARED_LINEAR_COEFFICIENT = 236205593348;
/// @dev 1 / (7 * (2_weeks)^2) - expressed in fixed point
int256 internal constant SHARED_QUADRATIC_COEFFICIENT = 97637;

/// @dev straight line so the curve is increasing only in the linear term
/// 1 / (52 * SECONDS_IN_2_WEEKS)
int256 internal constant SHARED_LINEAR_COEFFICIENT = 15898453398;

/// @dev this curve is linear
int256 internal constant SHARED_QUADRATIC_COEFFICIENT = 0;

/// @dev the maxiumum number of epochs the cure can keep increasing
uint256 internal constant MAX_EPOCHS = 5;
/// 26 epochs in a year, 2 years = 52 epochs
uint256 internal constant MAX_EPOCHS = 52;
}
72 changes: 42 additions & 30 deletions test/escrow/curve/QuadraticCurveMath.t.sol
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

import {console2 as console} from "forge-std/console2.sol";
Expand All @@ -8,16 +9,7 @@ import {IVotingEscrowIncreasing, ILockedBalanceIncreasing} from "src/escrow/incr
import {QuadraticCurveBase} from "./QuadraticCurveBase.t.sol";

contract TestQuadraticIncreasingCurve is QuadraticCurveBase {
function test_votingPowerComputesCorrect() public {
/**
Period Result
1 1
2 1.428571429
3 2.142857143
4 3.142857143
5 4.428571429
6 6
*/
function test_votingPowerComputesCorrect() public view {
uint256 amount = 100e18;

int256[3] memory coefficients = curve.getCoefficients(100e18);
Expand All @@ -30,7 +22,7 @@ contract TestQuadraticIncreasingCurve is QuadraticCurveBase {

console.log("Coefficients: %st^2 + %st + %s", quadratic, linear, const);

for (uint i; i <= 6; i++) {
for (uint i; i <= 53; i++) {
uint period = 2 weeks * i;
console.log(
"Period: %d Voting Power : %s",
Expand Down Expand Up @@ -58,6 +50,35 @@ contract TestQuadraticIncreasingCurve is QuadraticCurveBase {
}

// write a new checkpoint
/*
* for the 1000 tokens (Python) (extend to 1bn with more zeros)
* 0 Voting Power: 1000000000000000000000
* 1 minute Voting Power: 1000000953907203932160
* 1 hour Voting Power: 1000057234432234487808
* 1 day Voting Power: 1001373626373626396672
* WARMUP_PERIOD (3 days) Voting Power: 1004120879120879058944
* WARMUP_PERIOD + 1s Voting Power: 1004120895019332534272
* 1 week Voting Power: 1009615384615384645632
* 1 period (2 weeks) Voting Power: 1019230769230769160192
* 10 periods (10 * PERIOD) Voting Power: 1192307692307692388352
* 50% periods (26 * PERIOD) Voting Power: 1500000000000000000000
* 35 periods (35 * PERIOD) Voting Power: 1673076923076923097088
* PERIOD_END (26 * PERIOD) Voting Power: 2000000000000000000000

* for the 420.69 tokens (Python)
* 0 Voting Power: 420690000000000000000
* 1 minute Voting Power: 420690401299221577728
* 1 hour Voting Power: 420714077953296695296
* 1 day Voting Power: 421267870879120883712
* WARMUP_PERIOD (3 days) Voting Power: 422423612637362651136
* WARMUP_PERIOD + 1s Voting Power: 422423619325683040256
* 1 week Voting Power: 424735096153846120448
* 1 period (2 weeks) Voting Power: 428780192307692306432
* 10 periods (10 * PERIOD) Voting Power: 501591923076923064320
* 50% periods (26 * PERIOD) Voting Power: 631035000000000032768
* 35 periods (35 * PERIOD) Voting Power: 703846730769230856192
* PERIOD_END (26 * PERIOD) Voting Power: 841380000000000000000
*/
function testWritesCheckpoint() public {
uint tokenIdFirst = 1;
uint tokenIdSecond = 2;
Expand Down Expand Up @@ -104,52 +125,43 @@ contract TestQuadraticIncreasingCurve is QuadraticCurveBase {
// warmup complete
vm.warp(block.timestamp + 1);

// python: 449.206279554928541696
// solmate (optimized): 449.206254284606635135
assertEq(
curve.votingPowerAt(tokenIdFirst, block.timestamp),
449206254284606635135,
422423619325633557508,
"Balance incorrect after warmup"
);
assertEq(curve.isWarm(tokenIdFirst), true, "Still warming up");

// python: 1067784543380942056100724736
// solmate: 1067784483312193385000000000
assertEq(
curve.votingPowerAt(tokenIdSecond, block.timestamp),
1067784483312193385000000000,
1004120895019214998000000000,
"Balance incorrect after warmup II"
);

// warp to the start of period 2
vm.warp(start + clock.epochDuration());
// excel: 600.985714300000000000
// PRB: 600.985163959347100568
// solmate: 600.985163959347101852
// python : 600.985714285714341888
// solmate2: 600.985163959347101952
assertEq(
curve.votingPowerAt(tokenIdFirst, block.timestamp),
600985163959347101952,
428780192307461588352,
"Balance incorrect after p1"
);

uint256 expectedMaxI = 2524126241845405205760;
uint256 expectedMaxII = 5999967296216704000000000000;
uint256 expectedMaxI = 841379999988002594304;
uint256 expectedMaxII = 1999999999971481600000000000;

// warp to the final period
// TECHNICALLY, this should finish at exactly 5 periodd and 6 * voting power
// but FP arithmetic has a small rounding error
vm.warp(start + clock.epochDuration() * 5);
// TECHNICALLY, this should round to a whole max
// but FP arithmetic has a small rounding error and it finishes just below
vm.warp(start + clock.epochDuration() * 52);
assertEq(
curve.votingPowerAt(tokenIdFirst, block.timestamp),
expectedMaxI,
"Balance incorrect after p6"
"Balance incorrect after pend"
);
assertEq(
curve.votingPowerAt(tokenIdSecond, block.timestamp),
expectedMaxII,
"Balance incorrect after p6 II "
"Balance incorrect after pend II "
);

// warp to the future and balance should be the same
Expand Down
Loading