Skip to content

Commit 83c6572

Browse files
committed
refactor: compression of config in gov to reduce costs.
1 parent 2640bfe commit 83c6572

31 files changed

+761
-194
lines changed

l1-contracts/foundry.toml

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ gas_reports = [
1616
"CoinIssuer",
1717
"FeeJuicePortal",
1818
"Governance",
19+
"TestGov",
1920
"GovernanceProposer",
2021
"GSE",
2122
"Inbox",
@@ -36,38 +37,37 @@ remappings = [
3637
"@aztec/=src",
3738
"@test/=test",
3839
"@zkpassport/=lib/circuits/src/solidity/src/",
39-
"@zkpassport-test/=lib/circuits/src/solidity/test"
40+
"@zkpassport-test/=lib/circuits/src/solidity/test",
4041
]
4142

4243
# See more config options https://github.com/foundry-rs/foundry/tree/master/config
4344

4445
fs_permissions = [
45-
{access = "read", path = "./test/fixtures/bn254_constants.json"},
46-
{access = "read", path = "./test/fixtures/mixed_block_1.json"},
47-
{access = "read", path = "./test/fixtures/mixed_block_2.json"},
48-
{access = "read", path = "./test/fixtures/single_tx_block_1.json"},
49-
{access = "read", path = "./test/fixtures/single_tx_block_2.json"},
50-
{access = "read", path = "./test/fixtures/empty_block_1.json"},
51-
{access = "read", path = "./test/fixtures/empty_block_2.json"},
52-
{access = "read", path = "./test/fixtures/fee_data_points.json"},
53-
{access = "read", path = "./test/staking_asset_handler/zkpassport/fixtures/valid_proof.hex"},
54-
{access = "read", path = "./test/staking_asset_handler/zkpassport/fixtures/valid_committed_inputs.hex"},
55-
{access = "read", path = "./test/staking_asset_handler/zkpassport/fixtures/valid_public_inputs.json"},
56-
{access = "read", path = "./test/fixtures/boosted_rewards/shares.json"},
57-
{access = "read", path = "./test/fixtures/boosted_rewards/activity_scores.json"},
58-
{access = "read", path = "./script/registration_data.json"},
46+
{ access = "read", path = "./test/fixtures/bn254_constants.json" },
47+
{ access = "read", path = "./test/fixtures/mixed_block_1.json" },
48+
{ access = "read", path = "./test/fixtures/mixed_block_2.json" },
49+
{ access = "read", path = "./test/fixtures/single_tx_block_1.json" },
50+
{ access = "read", path = "./test/fixtures/single_tx_block_2.json" },
51+
{ access = "read", path = "./test/fixtures/empty_block_1.json" },
52+
{ access = "read", path = "./test/fixtures/empty_block_2.json" },
53+
{ access = "read", path = "./test/fixtures/fee_data_points.json" },
54+
{ access = "read", path = "./test/staking_asset_handler/zkpassport/fixtures/valid_proof.hex" },
55+
{ access = "read", path = "./test/staking_asset_handler/zkpassport/fixtures/valid_committed_inputs.hex" },
56+
{ access = "read", path = "./test/staking_asset_handler/zkpassport/fixtures/valid_public_inputs.json" },
57+
{ access = "read", path = "./test/fixtures/boosted_rewards/shares.json" },
58+
{ access = "read", path = "./test/fixtures/boosted_rewards/activity_scores.json" },
59+
{ access = "read", path = "./script/registration_data.json" },
5960
]
6061

61-
no_match_contract="(ScreamAndShoutTest|UniswapPortalTest|MerkleCheck)"
62+
no_match_contract = "(ScreamAndShoutTest|UniswapPortalTest|MerkleCheck)"
6263

6364
[fmt]
6465
line_length = 120
6566
tab_width = 2
66-
variable_override_spacing=false
67+
variable_override_spacing = false
6768
wrap_comments = true
6869
number_underscore = "thousands"
6970
override_spacing = false
7071

7172
[rpc_endpoints]
72-
mainnet_fork="https://mainnet.infura.io/v3/9928b52099854248b3a096be07a6b23c"
73-
73+
mainnet_fork = "https://mainnet.infura.io/v3/9928b52099854248b3a096be07a6b23c"

l1-contracts/script/InternalGov.s.sol

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import {IRegistry} from "@aztec/governance/interfaces/IRegistry.sol";
1313
import {IValidatorSelection} from "@aztec/core/interfaces/IValidatorSelection.sol";
1414
import {IPayload} from "@aztec/governance/interfaces/IPayload.sol";
1515
import {RegisterNewRollupVersionPayload} from "../test/governance/scenario/RegisterNewRollupVersionPayload.sol";
16-
import {ProposalLib} from "@aztec/governance/libraries/ProposalLib.sol";
1716
import {Ownable} from "@oz/access/Ownable.sol";
1817
import {Fakerollup} from "../test/governance/governance-proposer/mocks/Fakerollup.sol";
1918
import {StakingAssetHandler} from "../src/mock/StakingAssetHandler.sol";
@@ -23,9 +22,10 @@ import {IStaking} from "@aztec/core/interfaces/IStaking.sol";
2322
import {RewardDistributor} from "@aztec/governance/RewardDistributor.sol";
2423
import {IInstance} from "@aztec/core/interfaces/IInstance.sol";
2524
import {RoundAccounting} from "@aztec/governance/proposer/EmpireBase.sol";
25+
import {UncompressedProposalWrapper} from "@test/governance/helpers/UncompressedProposalTestLib.sol";
2626

2727
contract GovScript is Test {
28-
using ProposalLib for Proposal;
28+
UncompressedProposalWrapper internal upw = new UncompressedProposalWrapper();
2929

3030
address internal constant ME = address(0xf8d7d601759CBcfB78044bA7cA9B0c0D6301A54f);
3131

@@ -138,14 +138,14 @@ contract GovScript is Test {
138138
proposal = governance.getProposal(_proposalId);
139139
ProposalState state = governance.getProposalState(_proposalId);
140140

141-
Timestamp pendingThrough = proposal.pendingThrough();
141+
Timestamp pendingThrough = upw.pendingThrough(proposal);
142142

143143
emit log_named_string("Proposal state", stateNames[uint256(state)]);
144144
emit log_named_address("Proposal payload", address(proposal.payload));
145145
emit log_named_uint("pendingThrough ", Timestamp.unwrap(pendingThrough));
146-
emit log_named_uint("activeThrough ", Timestamp.unwrap(proposal.activeThrough()));
147-
emit log_named_uint("queuedThrough ", Timestamp.unwrap(proposal.queuedThrough()));
148-
emit log_named_uint("executableThrough", Timestamp.unwrap(proposal.executableThrough()));
146+
emit log_named_uint("activeThrough ", Timestamp.unwrap(upw.activeThrough(proposal)));
147+
emit log_named_uint("queuedThrough ", Timestamp.unwrap(upw.queuedThrough(proposal)));
148+
emit log_named_uint("executableThrough", Timestamp.unwrap(upw.executableThrough(proposal)));
149149
emit log_named_uint("creation ", Timestamp.unwrap(proposal.creation));
150150
emit log_named_decimal_uint("yeaCount ", proposal.summedBallot.yea, 18);
151151
emit log_named_decimal_uint("nayCount ", proposal.summedBallot.nay, 18);
@@ -317,7 +317,7 @@ contract GovScript is Test {
317317

318318
proposal = governance.getProposal(_proposalId);
319319

320-
uint256 power = governance.powerAt(ME, proposal.pendingThrough());
320+
uint256 power = governance.powerAt(ME, upw.pendingThrough(proposal));
321321
emit log_named_decimal_uint("power", power, 18);
322322

323323
vm.startBroadcast(ME);

l1-contracts/src/core/libraries/rollup/StakingLib.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ library StakingLib {
147147
Proposal memory proposal = gov.getProposal(_proposalId);
148148
require(proposal.proposer == address(govProposer), Errors.Staking__IncorrectGovProposer(_proposalId));
149149

150-
Timestamp ts = proposal.pendingThroughMemory();
150+
Timestamp ts = proposal.creation + proposal.config.votingDelay;
151151

152152
// Cast votes with all our power
153153
uint256 vp = store.gse.getVotingPowerAt(address(this), ts);

l1-contracts/src/governance/GSE.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
DepositDelegationLib, DepositAndDelegationAccounting
1111
} from "@aztec/governance/libraries/DepositDelegationLib.sol";
1212
import {Errors} from "@aztec/governance/libraries/Errors.sol";
13-
import {ProposalLib} from "@aztec/governance/libraries/ProposalLib.sol";
1413
import {BN254Lib, G1Point, G2Point} from "@aztec/shared/libraries/BN254Lib.sol";
1514
import {Timestamp} from "@aztec/shared/libraries/TimeMath.sol";
1615
import {Ownable} from "@oz/access/Ownable.sol";
@@ -122,7 +121,6 @@ contract GSECore is IGSECore, Ownable {
122121
using SafeCast for uint224;
123122
using Checkpoints for Checkpoints.Trace224;
124123
using DepositDelegationLib for DepositAndDelegationAccounting;
125-
using ProposalLib for Proposal;
126124

127125
/**
128126
* Create a special "bonus" address for use by the latest rollup.
@@ -619,7 +617,9 @@ contract GSECore is IGSECore, Ownable {
619617
}
620618

621619
function _pendingThrough(uint256 _proposalId) internal view returns (Timestamp) {
622-
return getGovernance().getProposal(_proposalId).pendingThroughMemory();
620+
// Directly compute pendingThrough for memory proposal
621+
Proposal memory proposal = getGovernance().getProposal(_proposalId);
622+
return proposal.creation + proposal.config.votingDelay;
623623
}
624624
}
625625

l1-contracts/src/governance/Governance.sol

Lines changed: 51 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@ import {
77
Proposal,
88
ProposalState,
99
Configuration,
10-
Ballot,
10+
ProposeConfiguration,
1111
Withdrawal
1212
} from "@aztec/governance/interfaces/IGovernance.sol";
1313
import {IPayload} from "@aztec/governance/interfaces/IPayload.sol";
1414
import {Checkpoints, CheckpointedUintLib} from "@aztec/governance/libraries/CheckpointedUintLib.sol";
15+
import {Ballot, CompressedBallot, BallotLib} from "@aztec/governance/libraries/compressed-data/Ballot.sol";
16+
import {
17+
CompressedConfiguration,
18+
CompressedConfigurationLib
19+
} from "@aztec/governance/libraries/compressed-data/Configuration.sol";
20+
import {CompressedProposal, CompressedProposalLib} from "@aztec/governance/libraries/compressed-data/Proposal.sol";
1521
import {ConfigurationLib} from "@aztec/governance/libraries/ConfigurationLib.sol";
1622
import {Errors} from "@aztec/governance/libraries/Errors.sol";
1723
import {ProposalLib, VoteTabulationReturn} from "@aztec/governance/libraries/ProposalLib.sol";
@@ -129,9 +135,13 @@ struct DepositControl {
129135
*/
130136
contract Governance is IGovernance {
131137
using SafeERC20 for IERC20;
132-
using ProposalLib for Proposal;
138+
using ProposalLib for CompressedProposal;
133139
using CheckpointedUintLib for Checkpoints.Trace224;
134140
using ConfigurationLib for Configuration;
141+
using ConfigurationLib for CompressedConfiguration;
142+
using CompressedConfigurationLib for CompressedConfiguration;
143+
using CompressedProposalLib for CompressedProposal;
144+
using BallotLib for CompressedBallot;
135145

136146
IERC20 public immutable ASSET;
137147

@@ -155,15 +165,16 @@ contract Governance is IGovernance {
155165
* New proposals are created by calling `_propose`, via `propose` or `proposeWithLock`.
156166
* The storage of a proposal may be modified by calling `vote`, `execute`, or `dropProposal`.
157167
*/
158-
mapping(uint256 proposalId => Proposal proposal) internal proposals;
168+
mapping(uint256 proposalId => CompressedProposal proposal) internal proposals;
159169

160170
/**
161171
* @dev The ballots that have been cast for each proposal.
162172
*
163-
* `Ballot`s contain a `yea` and `nay` count, which are the number of votes for and against the proposal.
173+
* `CompressedBallot`s contain a compressed `yea` and `nay` count (uint128 each packed into uint256),
174+
* which are the number of votes for and against the proposal.
164175
* `ballots` is only updated during `vote`.
165176
*/
166-
mapping(uint256 proposalId => mapping(address user => Ballot ballot)) public ballots;
177+
mapping(uint256 proposalId => mapping(address user => CompressedBallot ballot)) internal ballots;
167178

168179
/**
169180
* @dev Checkpointed deposit amounts for an address.
@@ -185,7 +196,7 @@ contract Governance is IGovernance {
185196
* `configuration` is set in the constructor, and is only updated during `updateConfiguration`,
186197
* which must be done via a proposal.
187198
*/
188-
Configuration internal configuration;
199+
CompressedConfiguration internal configuration;
189200

190201
/**
191202
* @dev The total power of the governance contract.
@@ -237,8 +248,8 @@ contract Governance is IGovernance {
237248
ASSET = _asset;
238249
governanceProposer = _governanceProposer;
239250

240-
configuration = _configuration;
241-
configuration.assertValid();
251+
_configuration.assertValid();
252+
configuration = CompressedConfigurationLib.compress(_configuration);
242253

243254
// Unnecessary to set, but better clarity.
244255
depositControl.allBeneficiariesAllowed = false;
@@ -296,7 +307,7 @@ contract Governance is IGovernance {
296307
// This following MUST revert if the configuration is invalid
297308
_configuration.assertValid();
298309

299-
configuration = _configuration;
310+
configuration = CompressedConfigurationLib.compress(_configuration);
300311

301312
emit ConfigurationUpdated(Timestamp.wrap(block.timestamp));
302313
}
@@ -332,14 +343,14 @@ contract Governance is IGovernance {
332343
* @notice Initiate a withdrawal of funds from the governance contract,
333344
* decreasing the power of the beneficiary within the governance contract.
334345
*
335-
* @dev the withdraw may be finalized by anyone after configuration.withdrawalDelay() has passed.
346+
* @dev the withdraw may be finalized by anyone after configuration.getWithdrawalDelay() has passed.
336347
*
337348
* @param _to The address that will receive the funds when the withdrawal is finalized.
338349
* @param _amount The amount of power to reduce, and thus funds to withdraw.
339350
* @return The id of the withdrawal, passed to `finalizeWithdraw`.
340351
*/
341352
function initiateWithdraw(address _to, uint256 _amount) external override(IGovernance) returns (uint256) {
342-
return _initiateWithdraw(msg.sender, _to, _amount, configuration.withdrawalDelay());
353+
return _initiateWithdraw(msg.sender, _to, _amount, configuration.getWithdrawalDelay());
343354
}
344355

345356
/**
@@ -405,7 +416,8 @@ contract Governance is IGovernance {
405416
* @return The id of the proposal
406417
*/
407418
function proposeWithLock(IPayload _proposal, address _to) external override(IGovernance) returns (uint256) {
408-
_initiateWithdraw(msg.sender, _to, configuration.proposeConfig.lockAmount, configuration.proposeConfig.lockDelay);
419+
ProposeConfiguration memory proposeConfig = configuration.getProposeConfig();
420+
_initiateWithdraw(msg.sender, _to, proposeConfig.lockAmount, proposeConfig.lockDelay);
409421
return _propose(_proposal, address(this));
410422
}
411423

@@ -435,18 +447,18 @@ contract Governance is IGovernance {
435447
// alter the power while the proposal is active since all txs in a block have the same timestamp.
436448
uint256 userPower = users[msg.sender].valueAt(proposals[_proposalId].pendingThrough());
437449

438-
Ballot storage userBallot = ballots[_proposalId][msg.sender];
450+
CompressedBallot userBallot = ballots[_proposalId][msg.sender];
439451

440-
uint256 availablePower = userPower - (userBallot.nay + userBallot.yea);
452+
uint256 availablePower = userPower - (userBallot.getNay() + userBallot.getYea());
441453
require(_amount <= availablePower, Errors.Governance__InsufficientPower(msg.sender, availablePower, _amount));
442454

443-
Ballot storage summedBallot = proposals[_proposalId].summedBallot;
455+
CompressedProposal storage proposal = proposals[_proposalId];
444456
if (_support) {
445-
userBallot.yea += _amount;
446-
summedBallot.yea += _amount;
457+
ballots[_proposalId][msg.sender] = userBallot.addYea(_amount);
458+
proposal.addYea(_amount);
447459
} else {
448-
userBallot.nay += _amount;
449-
summedBallot.nay += _amount;
460+
ballots[_proposalId][msg.sender] = userBallot.addNay(_amount);
461+
proposal.addNay(_amount);
450462
}
451463

452464
emit VoteCast(_proposalId, msg.sender, _support, _amount);
@@ -470,7 +482,7 @@ contract Governance is IGovernance {
470482
ProposalState state = getProposalState(_proposalId);
471483
require(state == ProposalState.Executable, Errors.Governance__ProposalNotExecutable());
472484

473-
Proposal storage proposal = proposals[_proposalId];
485+
CompressedProposal storage proposal = proposals[_proposalId];
474486
proposal.cachedState = ProposalState.Executed;
475487

476488
IPayload.Action[] memory actions = proposal.payload.getActions();
@@ -496,7 +508,7 @@ contract Governance is IGovernance {
496508
* @param _proposalId The id of the proposal to mark as `Dropped`.
497509
*/
498510
function dropProposal(uint256 _proposalId) external override(IGovernance) returns (bool) {
499-
Proposal storage self = proposals[_proposalId];
511+
CompressedProposal storage self = proposals[_proposalId];
500512
require(self.cachedState != ProposalState.Dropped, Errors.Governance__ProposalAlreadyDropped());
501513
require(getProposalState(_proposalId) == ProposalState.Droppable, Errors.Governance__ProposalCannotBeDropped());
502514

@@ -577,7 +589,7 @@ contract Governance is IGovernance {
577589
}
578590

579591
function getConfiguration() external view override(IGovernance) returns (Configuration memory) {
580-
return configuration;
592+
return configuration.decompress();
581593
}
582594

583595
/**
@@ -589,7 +601,7 @@ contract Governance is IGovernance {
589601
* @return The proposal.
590602
*/
591603
function getProposal(uint256 _proposalId) external view override(IGovernance) returns (Proposal memory) {
592-
return proposals[_proposalId];
604+
return proposals[_proposalId].decompress();
593605
}
594606

595607
/**
@@ -604,6 +616,19 @@ contract Governance is IGovernance {
604616
return withdrawals[_withdrawalId];
605617
}
606618

619+
/**
620+
* @notice Get a user's ballot for a specific proposal.
621+
*
622+
* @dev Returns the uncompressed Ballot struct for external callers.
623+
*
624+
* @param _proposalId The id of the proposal.
625+
* @param _user The address of the user.
626+
* @return The user's ballot with yea and nay votes.
627+
*/
628+
function getBallot(uint256 _proposalId, address _user) external view override(IGovernance) returns (Ballot memory) {
629+
return ballots[_proposalId][_user].decompress();
630+
}
631+
607632
/**
608633
* @notice Get the state of a proposal in the governance system
609634
*
@@ -648,7 +673,7 @@ contract Governance is IGovernance {
648673
function getProposalState(uint256 _proposalId) public view override(IGovernance) returns (ProposalState) {
649674
require(_proposalId < proposalCount, Errors.Governance__ProposalDoesNotExists(_proposalId));
650675

651-
Proposal storage self = proposals[_proposalId];
676+
CompressedProposal storage self = proposals[_proposalId];
652677

653678
// A proposal's state is "stable" after `execute` or `dropProposal` has been called on it.
654679
// In this case, the state of the proposal as returned by `getProposalState` is the same as the cached state,
@@ -735,14 +760,8 @@ contract Governance is IGovernance {
735760
function _propose(IPayload _proposal, address _proposer) internal returns (uint256) {
736761
uint256 proposalId = proposalCount++;
737762

738-
proposals[proposalId] = Proposal({
739-
config: configuration,
740-
cachedState: ProposalState.Pending,
741-
payload: _proposal,
742-
proposer: _proposer,
743-
creation: Timestamp.wrap(block.timestamp),
744-
summedBallot: Ballot({yea: 0, nay: 0})
745-
});
763+
proposals[proposalId] =
764+
CompressedProposalLib.create(_proposer, _proposal, Timestamp.wrap(block.timestamp), configuration);
746765

747766
emit Proposed(proposalId, address(_proposal));
748767

0 commit comments

Comments
 (0)