Skip to content

Commit a34ff5e

Browse files
authored
chore: minor misc solidity changes (#16859)
Please read [contributing guidelines](CONTRIBUTING.md) and remove this line. For audit-related pull requests, please use the [audit PR template](?expand=1&template=audit.md).
2 parents d154453 + e87438b commit a34ff5e

File tree

8 files changed

+109
-72
lines changed

8 files changed

+109
-72
lines changed

l1-contracts/src/core/libraries/Errors.sol

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ library Errors {
9191
error Rollup__InvalidFirstEpochProof();
9292
error Rollup__InvalidCoinbase();
9393
error Rollup__StaleTempBlockLog(uint256 blockNumber, uint256 pendingBlockNumber, uint256 size);
94+
error Rollup__NoBlobsInBlock();
9495

9596
// ProposedHeaderLib
9697
error HeaderLib__InvalidHeaderSize(uint256 expected, uint256 actual); // 0xf3ccb247
@@ -176,6 +177,8 @@ library Errors {
176177
// RewardBooster
177178
error RewardBooster__OnlyRollup(address caller);
178179

180+
error RewardLib__InvalidSequencerBps();
181+
179182
// TallySlashingProposer
180183
error TallySlashingProposer__InvalidSignature();
181184
error TallySlashingProposer__InvalidVoteLength(uint256 expected, uint256 actual);

l1-contracts/src/core/libraries/crypto/MerkleLib.sol

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -53,64 +53,4 @@ library MerkleLib {
5353
require(indexAtHeight == 0, Errors.MerkleLib__InvalidIndexForPathLength());
5454
require(subtreeRoot == _expectedRoot, Errors.MerkleLib__InvalidRoot(_expectedRoot, subtreeRoot, _leaf, _index));
5555
}
56-
57-
/**
58-
* @notice Computes the root for a binary Merkle-tree given the leafs.
59-
* @dev Uses sha256.
60-
* @param _leafs - The 32 bytes leafs to build the tree of.
61-
* @return The root of the Merkle tree.
62-
*/
63-
function computeRoot(bytes32[] memory _leafs) internal pure returns (bytes32) {
64-
// @todo Must pad the tree
65-
uint256 treeDepth = 0;
66-
while (2 ** treeDepth < _leafs.length) {
67-
treeDepth++;
68-
}
69-
uint256 treeSize = 2 ** treeDepth;
70-
assembly {
71-
mstore(_leafs, treeSize)
72-
}
73-
74-
for (uint256 i = 0; i < treeDepth; i++) {
75-
for (uint256 j = 0; j < treeSize; j += 2) {
76-
_leafs[j / 2] = Hash.sha256ToField(bytes.concat(_leafs[j], _leafs[j + 1]));
77-
}
78-
treeSize /= 2;
79-
}
80-
81-
return _leafs[0];
82-
}
83-
84-
/**
85-
* @notice Computes the root for a binary unbalanced Merkle-tree given the leaves.
86-
* @dev Filled in greedily with subtrees. Useful for outHash tree.
87-
* @param _leaves - The 32 bytes leafs to build the tree of.
88-
* @return The root of the Merkle tree.
89-
*/
90-
function computeUnbalancedRoot(bytes32[] memory _leaves) internal pure returns (bytes32) {
91-
// e.g. an unbalanced tree of 7 txs will contain subtrees of 4, 2, and 1 tx(s) = 111
92-
// e.g. an unbalanced tree of 9 txs will contain subtrees of 8 and 1 tx(s) = 1001
93-
// We collect the roots of each subtree
94-
bytes32 root;
95-
uint256 currentSubtreeSize = 1;
96-
uint256 numTxs = _leaves.length;
97-
// We must calculate the smaller rightmost subtrees first, hence starting at 1
98-
while (numTxs != 0) {
99-
// If size & txs == 0, the subtree doesn't exist for this number of txs
100-
if (currentSubtreeSize & numTxs == 0) {
101-
currentSubtreeSize <<= 1;
102-
continue;
103-
}
104-
bytes32[] memory leavesInSubtree = new bytes32[](currentSubtreeSize);
105-
uint256 start = numTxs - currentSubtreeSize;
106-
for (uint256 i = start; i < numTxs; i++) {
107-
leavesInSubtree[i - start] = _leaves[i];
108-
}
109-
bytes32 subtreeRoot = computeRoot(leavesInSubtree);
110-
root = numTxs == _leaves.length ? subtreeRoot : Hash.sha256ToField(bytes.concat(subtreeRoot, root));
111-
numTxs -= currentSubtreeSize;
112-
currentSubtreeSize <<= 1;
113-
}
114-
return root;
115-
}
11656
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ library BlobLib {
105105
// We cannot input the incorrect number of blobs below, as the blobsHash
106106
// and epoch proof verification will fail.
107107
uint8 numBlobs = uint8(_blobsInput[0]);
108+
require(numBlobs > 0, Errors.Rollup__NoBlobsInBlock());
108109
blobHashes = new bytes32[](numBlobs);
109110
blobCommitments = new bytes[](numBlobs);
110111
bytes32 blobHash;

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ library RewardLib {
7777
address public constant BURN_ADDRESS = address(bytes20("CUAUHXICALLI"));
7878

7979
function setConfig(RewardConfig memory _config) internal {
80+
require(Bps.unwrap(_config.sequencerBps) <= 10_000, Errors.RewardLib__InvalidSequencerBps());
8081
RewardStorage storage rewardStorage = getStorage();
8182
rewardStorage.config = _config;
8283
}
@@ -86,8 +87,11 @@ library RewardLib {
8687

8788
RollupStore storage rollupStore = STFLib.getStorage();
8889
uint256 amount = rewardStorage.sequencerRewards[_sequencer];
89-
rewardStorage.sequencerRewards[_sequencer] = 0;
90-
rollupStore.config.feeAsset.transfer(_sequencer, amount);
90+
91+
if (amount > 0) {
92+
rewardStorage.sequencerRewards[_sequencer] = 0;
93+
rollupStore.config.feeAsset.safeTransfer(_sequencer, amount);
94+
}
9195

9296
return amount;
9397
}
@@ -119,7 +123,7 @@ library RewardLib {
119123
}
120124
}
121125

122-
rollupStore.config.feeAsset.transfer(_prover, accumulatedRewards);
126+
rollupStore.config.feeAsset.safeTransfer(_prover, accumulatedRewards);
123127

124128
return accumulatedRewards;
125129
}
@@ -215,7 +219,7 @@ library RewardLib {
215219
}
216220

217221
if (t.totalBurn > 0) {
218-
rollupStore.config.feeAsset.transfer(BURN_ADDRESS, t.totalBurn);
222+
rollupStore.config.feeAsset.safeTransfer(BURN_ADDRESS, t.totalBurn);
219223
}
220224
}
221225
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ library StakingLib {
193193
delete store.exits[_attester];
194194

195195
store.gse.finalizeWithdraw(exit.withdrawalId);
196-
store.stakingAsset.transfer(exit.recipientOrWithdrawer, exit.amount);
196+
store.stakingAsset.safeTransfer(exit.recipientOrWithdrawer, exit.amount);
197197

198198
emit IStakingCore.WithdrawFinalized(_attester, exit.recipientOrWithdrawer, exit.amount);
199199
}
@@ -297,7 +297,7 @@ library StakingLib {
297297
require(!store.exits[_attester].exists, Errors.Staking__AlreadyExiting(_attester));
298298
uint256 amount = store.gse.ACTIVATION_THRESHOLD();
299299

300-
store.stakingAsset.transferFrom(msg.sender, address(this), amount);
300+
store.stakingAsset.safeTransferFrom(msg.sender, address(this), amount);
301301
store.entryQueue.enqueue(
302302
_attester, _withdrawer, _publicKeyInG1, _publicKeyInG2, _proofOfPossession, _moveWithLatestRollup
303303
);
@@ -369,7 +369,7 @@ library StakingLib {
369369
// where someone could drain the queue without making any deposits.
370370
// We can safely assume data.length == 0 means out of gas since we only call trusted GSE contract.
371371
require(data.length > 0, Errors.Staking__DepositOutOfGas());
372-
store.stakingAsset.transfer(args.withdrawer, amount);
372+
store.stakingAsset.safeTransfer(args.withdrawer, amount);
373373
emit IStakingCore.FailedDeposit(
374374
args.attester, args.withdrawer, args.publicKeyInG1, args.publicKeyInG2, args.proofOfPossession
375375
);

l1-contracts/src/governance/GSE.sol

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {BN254Lib, G1Point, G2Point} from "@aztec/shared/libraries/BN254Lib.sol";
1414
import {Timestamp} from "@aztec/shared/libraries/TimeMath.sol";
1515
import {Ownable} from "@oz/access/Ownable.sol";
1616
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
17+
import {SafeERC20} from "@oz/token/ERC20/utils/SafeERC20.sol";
1718
import {SafeCast} from "@oz/utils/math/SafeCast.sol";
1819
import {Checkpoints} from "@oz/utils/structs/Checkpoints.sol";
1920

@@ -121,6 +122,7 @@ contract GSECore is IGSECore, Ownable {
121122
using SafeCast for uint224;
122123
using Checkpoints for Checkpoints.Trace224;
123124
using DepositDelegationLib for DepositAndDelegationAccounting;
125+
using SafeERC20 for IERC20;
124126

125127
/**
126128
* Create a special "bonus" address for use by the latest rollup.
@@ -336,7 +338,7 @@ contract GSECore is IGSECore, Ownable {
336338
delegation.delegate(recipientInstance, _attester, recipientInstance);
337339
delegation.increaseBalance(recipientInstance, _attester, ACTIVATION_THRESHOLD);
338340

339-
ASSET.transferFrom(msg.sender, address(this), ACTIVATION_THRESHOLD);
341+
ASSET.safeTransferFrom(msg.sender, address(this), ACTIVATION_THRESHOLD);
340342

341343
Governance gov = getGovernance();
342344
ASSET.approve(address(gov), ACTIVATION_THRESHOLD);
@@ -469,7 +471,7 @@ contract GSECore is IGSECore, Ownable {
469471
Governance gov = getGovernance();
470472
uint256 amount = gov.getConfiguration().proposeConfig.lockAmount;
471473

472-
ASSET.transferFrom(msg.sender, address(this), amount);
474+
ASSET.safeTransferFrom(msg.sender, address(this), amount);
473475
ASSET.approve(address(gov), amount);
474476

475477
gov.deposit(address(this), amount);

l1-contracts/test/Rollup.t.sol

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,7 @@ contract RollupTest is RollupBase {
681681
function testRevertInvalidTimestamp() public setUpFor("empty_block_1") {
682682
DecoderBase.Data memory data = load("empty_block_1").block;
683683
ProposedHeader memory header = data.header;
684+
vm.blobhashes(this.getBlobHashes(data.blobCommitments));
684685
bytes32 archive = data.archive;
685686

686687
Timestamp realTs = header.timestamp;
@@ -704,7 +705,7 @@ contract RollupTest is RollupBase {
704705
AttestationLibHelper.packAttestations(attestations),
705706
signers,
706707
attestationsAndSignersSignature,
707-
new bytes(144)
708+
data.blobCommitments
708709
);
709710
}
710711

@@ -720,6 +721,8 @@ contract RollupTest is RollupBase {
720721
// Tweak the coinbase.
721722
header.coinbase = address(0);
722723

724+
bytes32[] memory blobHashes = this.getBlobHashes(data.blobCommitments);
725+
vm.blobhashes(blobHashes);
723726
skipBlobCheck(address(rollup));
724727
vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidCoinbase.selector));
725728
ProposeArgs memory args = ProposeArgs({
@@ -733,7 +736,7 @@ contract RollupTest is RollupBase {
733736
AttestationLibHelper.packAttestations(attestations),
734737
signers,
735738
attestationsAndSignersSignature,
736-
new bytes(144)
739+
data.blobCommitments
737740
);
738741
}
739742

@@ -777,6 +780,33 @@ contract RollupTest is RollupBase {
777780
_submitEpochProof(1, 1, blockLog.archive, data.archive, blobProofInputs, address(0));
778781
}
779782

783+
function testNoBlob() public setUpFor("empty_block_1") {
784+
DecoderBase.Data memory data = load("empty_block_1").block;
785+
ProposedHeader memory header = data.header;
786+
bytes32 archive = data.archive;
787+
788+
Timestamp realTs = header.timestamp;
789+
790+
vm.warp(max(block.timestamp, Timestamp.unwrap(realTs)));
791+
792+
header.gasFees.feePerL2Gas = uint128(rollup.getManaBaseFeeAt(Timestamp.wrap(block.timestamp), true));
793+
794+
vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__NoBlobsInBlock.selector));
795+
ProposeArgs memory args = ProposeArgs({
796+
header: header,
797+
archive: archive,
798+
stateReference: EMPTY_STATE_REFERENCE,
799+
oracleInput: OracleInput(0)
800+
});
801+
rollup.propose(
802+
args,
803+
AttestationLibHelper.packAttestations(attestations),
804+
signers,
805+
attestationsAndSignersSignature,
806+
new bytes(144)
807+
);
808+
}
809+
780810
function testTooManyBlocks() public setUpFor("mixed_block_1") {
781811
_proposeBlock("mixed_block_1", 1);
782812
DecoderBase.Data memory data = load("mixed_block_1").block;

l1-contracts/test/merkle/helpers/MerkleLibHelper.sol

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Copyright 2024 Aztec Labs.
33
pragma solidity >=0.8.27;
44

5+
import {Hash} from "@aztec/core/libraries/crypto/Hash.sol";
56
import {MerkleLib} from "@aztec/core/libraries/crypto/MerkleLib.sol";
67

78
// A wrapper used to be able to "call" library functions, instead of "jumping" to them, allowing forge to catch the
@@ -55,7 +56,63 @@ contract MerkleLibHelper {
5556
return (min, max);
5657
}
5758

59+
/**
60+
* @notice Computes the root for a binary unbalanced Merkle-tree given the leaves.
61+
* @dev Filled in greedily with subtrees. Useful for outHash tree.
62+
* @param _leaves - The 32 bytes leafs to build the tree of.
63+
* @return The root of the Merkle tree.
64+
*/
5865
function computeUnbalancedRoot(bytes32[] memory _leaves) external pure returns (bytes32) {
59-
return MerkleLib.computeUnbalancedRoot(_leaves);
66+
// e.g. an unbalanced tree of 7 txs will contain subtrees of 4, 2, and 1 tx(s) = 111
67+
// e.g. an unbalanced tree of 9 txs will contain subtrees of 8 and 1 tx(s) = 1001
68+
// We collect the roots of each subtree
69+
bytes32 root;
70+
uint256 currentSubtreeSize = 1;
71+
uint256 numTxs = _leaves.length;
72+
// We must calculate the smaller rightmost subtrees first, hence starting at 1
73+
while (numTxs != 0) {
74+
// If size & txs == 0, the subtree doesn't exist for this number of txs
75+
if (currentSubtreeSize & numTxs == 0) {
76+
currentSubtreeSize <<= 1;
77+
continue;
78+
}
79+
bytes32[] memory leavesInSubtree = new bytes32[](currentSubtreeSize);
80+
uint256 start = numTxs - currentSubtreeSize;
81+
for (uint256 i = start; i < numTxs; i++) {
82+
leavesInSubtree[i - start] = _leaves[i];
83+
}
84+
bytes32 subtreeRoot = computeRoot(leavesInSubtree);
85+
root = numTxs == _leaves.length ? subtreeRoot : Hash.sha256ToField(bytes.concat(subtreeRoot, root));
86+
numTxs -= currentSubtreeSize;
87+
currentSubtreeSize <<= 1;
88+
}
89+
return root;
90+
}
91+
92+
/**
93+
* @notice Computes the root for a binary Merkle-tree given the leafs.
94+
* @dev Uses sha256.
95+
* @param _leafs - The 32 bytes leafs to build the tree of.
96+
* @return The root of the Merkle tree.
97+
*/
98+
function computeRoot(bytes32[] memory _leafs) internal pure returns (bytes32) {
99+
// @todo Must pad the tree
100+
uint256 treeDepth = 0;
101+
while (2 ** treeDepth < _leafs.length) {
102+
treeDepth++;
103+
}
104+
uint256 treeSize = 2 ** treeDepth;
105+
assembly {
106+
mstore(_leafs, treeSize)
107+
}
108+
109+
for (uint256 i = 0; i < treeDepth; i++) {
110+
for (uint256 j = 0; j < treeSize; j += 2) {
111+
_leafs[j / 2] = Hash.sha256ToField(bytes.concat(_leafs[j], _leafs[j + 1]));
112+
}
113+
treeSize /= 2;
114+
}
115+
116+
return _leafs[0];
60117
}
61118
}

0 commit comments

Comments
 (0)