Skip to content

Commit c0792db

Browse files
committed
fix: address tmnt 150
1 parent 89225c6 commit c0792db

File tree

5 files changed

+109
-12
lines changed

5 files changed

+109
-12
lines changed

l1-contracts/gas_benchmark.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
|----------------------|---------|---------|---------------|--------------|
3030
| propose | 206,977 | 226,338 | 2,852 | 45,632 |
3131
| submitEpochRootProof | 679,690 | 701,700 | 5,092 | 81,472 |
32-
| aggregate3 | 256,679 | 286,474 | - | - |
32+
| aggregate3 | 256,810 | 286,606 | - | - |
3333
| setupEpoch | 38,145 | 327,074 | - | - |
3434

3535
**Avg Gas Cost per Second**: 1,229.6 gas/second
@@ -65,7 +65,7 @@
6565
|----------------------|---------|---------|---------------|--------------|
6666
| propose | 334,025 | 351,385 | 4,580 | 73,280 |
6767
| submitEpochRootProof | 895,025 | 933,081 | 6,308 | 100,928 |
68-
| aggregate3 | 386,141 | 411,884 | - | - |
68+
| aggregate3 | 386,274 | 412,016 | - | - |
6969
| setupEpoch | 49,728 | 542,190 | - | - |
7070

7171
**Avg Gas Cost per Second**: 10,875.5 gas/second

l1-contracts/gas_benchmark_results.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@
5555
},
5656
"aggregate3": {
5757
"calls": 100,
58-
"min": 243742,
59-
"mean": 256679,
60-
"median": 253598,
61-
"max": 286474
58+
"min": 243874,
59+
"mean": 256810,
60+
"median": 253736,
61+
"max": 286606
6262
}
6363
}
6464
},
@@ -118,10 +118,10 @@
118118
},
119119
"aggregate3": {
120120
"calls": 100,
121-
"min": 362550,
122-
"mean": 386141,
123-
"median": 384626,
124-
"max": 411884
121+
"min": 362682,
122+
"mean": 386274,
123+
"median": 384758,
124+
"max": 412016
125125
}
126126
}
127127
}

l1-contracts/src/governance/proposer/EmpireBase.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ abstract contract EmpireBase is EIP712, IEmpire {
292292
require(
293293
currentSlot > round.lastSignalSlot.decompress(), Errors.GovernanceProposer__SignalAlreadyCastForSlot(currentSlot)
294294
);
295+
round.lastSignalSlot = currentSlot.compress();
295296

296297
address signaler = selection.getCurrentProposer();
297298

@@ -306,7 +307,6 @@ abstract contract EmpireBase is EIP712, IEmpire {
306307
}
307308

308309
round.signalCount[_payload] += 1;
309-
round.lastSignalSlot = currentSlot.compress();
310310

311311
// @todo We can optimise here for gas by storing some of it packed with the payloadWithMostSignals.
312312
if (

l1-contracts/test/governance/governance-proposer/mocks/Fakerollup.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ contract Fakerollup {
4747
return TimeLib.getStorage().proofSubmissionEpochs;
4848
}
4949

50-
function getCurrentProposer() external view returns (address) {
50+
function getCurrentProposer() external virtual returns (address) {
5151
return proposer;
5252
}
5353

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity >=0.8.27;
3+
4+
import {GovernanceProposerBase} from "../Base.t.sol";
5+
import {GovernanceProposer} from "@aztec/governance/proposer/GovernanceProposer.sol";
6+
7+
import {IPayload} from "@aztec/governance/interfaces/IPayload.sol";
8+
import {Slot, Timestamp} from "@aztec/core/libraries/TimeLib.sol";
9+
import {Fakerollup} from "../mocks/Fakerollup.sol";
10+
import {IRollup} from "@aztec/core/interfaces/IRollup.sol";
11+
import {Signature} from "@aztec/shared/libraries/SignatureLib.sol";
12+
import {MessageHashUtils} from "@oz/utils/cryptography/MessageHashUtils.sol";
13+
import {Errors} from "@aztec/governance/libraries/Errors.sol";
14+
15+
contract MaliciousRollup is Fakerollup {
16+
uint256 public numberOfRounds;
17+
GovernanceProposer public governanceProposer;
18+
IPayload public proposal;
19+
20+
function maliciousValues(uint256 _numberOfRounds, GovernanceProposer _governanceProposer, IPayload _proposal)
21+
external
22+
{
23+
numberOfRounds = _numberOfRounds;
24+
governanceProposer = _governanceProposer;
25+
proposal = _proposal;
26+
}
27+
28+
function commenceAttack() external {
29+
governanceProposer.signal(proposal);
30+
}
31+
32+
function getCurrentProposer() external override returns (address) {
33+
if (numberOfRounds <= 1) {
34+
return address(this);
35+
}
36+
37+
numberOfRounds--;
38+
39+
governanceProposer.signal(proposal);
40+
41+
return address(this);
42+
}
43+
}
44+
45+
// https://linear.app/aztec-labs/issue/TMNT-150/spearbit-gov-finding-2-potential-reentrancy-with-malicious-rollup
46+
contract TestTmnt150 is GovernanceProposerBase {
47+
using MessageHashUtils for bytes32;
48+
49+
IPayload internal proposal = IPayload(address(0xdeadbeef));
50+
address internal proposer = address(0);
51+
MaliciousRollup internal rollup1;
52+
53+
uint256 internal privateKey = 0x1234567890;
54+
Signature internal signature;
55+
56+
function setUp() public override {
57+
super.setUp();
58+
}
59+
60+
function test_reentry() external {
61+
rollup1 = new MaliciousRollup();
62+
63+
proposer = vm.addr(privateKey);
64+
rollup1.setProposer(proposer);
65+
66+
vm.prank(registry.getGovernance());
67+
registry.addRollup(IRollup(address(rollup1)));
68+
vm.warp(Timestamp.unwrap(rollup1.getTimestampForSlot(Slot.wrap(1))));
69+
70+
// Create a signature for the proposer
71+
uint256 round = governanceProposer.getCurrentRound();
72+
signature = createSignature(privateKey, address(proposal), round);
73+
74+
rollup1.maliciousValues(5, governanceProposer, proposal);
75+
76+
assertEq(governanceProposer.signalCount(address(rollup1), 0, proposal), 0, "invalid number of votes");
77+
78+
vm.expectRevert(abi.encodeWithSelector(Errors.GovernanceProposer__SignalAlreadyCastForSlot.selector, 1));
79+
80+
rollup1.commenceAttack();
81+
82+
assertEq(governanceProposer.signalCount(address(rollup1), 0, proposal), 0, "invalid number of votes");
83+
}
84+
85+
function createSignature(uint256 _privateKey, address _payload, uint256 _round)
86+
internal
87+
view
88+
returns (Signature memory)
89+
{
90+
address signer = vm.addr(_privateKey);
91+
bytes32 digest = governanceProposer.getSignalSignatureDigest(IPayload(_payload), signer, _round);
92+
93+
(uint8 v, bytes32 r, bytes32 s) = vm.sign(_privateKey, digest);
94+
95+
return Signature({v: v, r: r, s: s});
96+
}
97+
}

0 commit comments

Comments
 (0)