Skip to content

Commit d0b8a87

Browse files
authored
chore: sync changes (#21)
## Summary - Sync changes
2 parents 6f80624 + 88d0c8a commit d0b8a87

13 files changed

Lines changed: 614 additions & 78 deletions

File tree

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ This project uses Protocol Buffers for consensus and node communication (except
1010

1111
- `make buf-lint` - Lint protobuf files to ensure they follow best practices
1212
- `make buf-format` - Format protobuf files (this is included in `make lint`)
13-
- `make buf-breaking` - Check for breaking changes against the master branch
13+
- `make buf-breaking` - Check for breaking changes against the main branch
1414

1515
### Before Committing Changes
1616

17-
If you modify any `.proto` files, always run `make buf-lint` and `make buf-breaking` to ensure your changes don't introduce linting issues or breaking changes. The `buf-breaking` command compares your changes against the master branch to detect any backwards-incompatible modifications. Breaking changes should be carefully reviewed and documented as they can impact existing deployments.
17+
If you modify any `.proto` files, always run `make buf-lint` and `make buf-breaking` to ensure your changes don't introduce linting issues or breaking changes. The `buf-breaking` command compares your changes against the main branch to detect any backwards-incompatible modifications. Breaking changes should be carefully reviewed and documented as they can impact existing deployments.
1818

1919
### CI
2020

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ git config fetch.recurseSubmodules on-demand
5454

5555
### Prerequisites
5656

57+
- [Rust](https://rustup.rs/)
58+
- [Docker](https://docs.docker.com/get-started/get-docker/)
5759
- [Node.js](https://nodejs.org/)
5860
- [Foundry](https://getfoundry.sh/)
5961
- [Hardhat](https://hardhat.org/)
@@ -178,7 +180,7 @@ For more details, see our [Contributing Guide](CONTRIBUTING.md).
178180
## Resources
179181

180182
- [Arc Network](https://www.arc.network/) - Official Arc Network website
181-
- [Arc Documentation](https://www.arc.network/) - Official Arc developer documentation
183+
- [Arc Documentation](https://docs.arc.network/) - Official Arc developer documentation
182184
- [Reth](https://github.com/paradigmxyz/reth) - The underlying execution layer framework
183185
- [Malachite](https://github.com/circlefin/malachite) - BFT consensus engine
184186
- [Local Documentation](docs/) - Implementation guides and references

crates/evm/src/handler.rs

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,9 @@ where
8989
let beneficiary = ctx.block().beneficiary();
9090
let basefee = ctx.block().basefee() as u128;
9191
let effective_gas_price = ctx.tx().effective_gas_price(basefee);
92-
let gas_used = exec_result.gas().used() as u128;
92+
let gas_used = exec_result.gas().used();
9393

94-
// Calculate total fee (base fee + priority fee) instead of just priority fee
95-
let total_fee_amount = U256::from(effective_gas_price * gas_used);
94+
let total_fee_amount = U256::from(effective_gas_price) * U256::from(gas_used);
9695

9796
// Transfer the total fee to the beneficiary (both base fee and priority fee)
9897
evm.ctx_mut()
@@ -505,6 +504,62 @@ mod tests {
505504
);
506505
}
507506

507+
#[test]
508+
fn test_reward_beneficiary_large_values_no_overflow() {
509+
let beneficiary = address!("1100000000000000000000000000000000000011");
510+
let caller = address!("2200000000000000000000000000000000000022");
511+
// Values that would overflow u128 when multiplied: (u128::MAX / 1000) * 2000 > u128::MAX
512+
let gas_price = u128::MAX / 1000;
513+
let gas_used = 2000u64;
514+
515+
let db: CacheDB<EmptyDBTyped<Infallible>> = CacheDB::new(EmptyDB::default());
516+
let mut evm = Context::mainnet().with_db(db).build_mainnet();
517+
518+
evm.block.beneficiary = beneficiary;
519+
evm.block.basefee = 0;
520+
evm.tx.caller = caller;
521+
evm.tx.gas_price = gas_price;
522+
523+
let interpreter_result = InterpreterResult::new(
524+
InstructionResult::Return,
525+
alloy_primitives::Bytes::new(),
526+
Gas::new_spent(gas_used),
527+
);
528+
let call_outcome = CallOutcome::new(interpreter_result, 0..0);
529+
let mut exec_result = FrameResult::Call(call_outcome);
530+
531+
let initial_balance = evm
532+
.journaled_state
533+
.load_account(beneficiary)
534+
.unwrap()
535+
.info
536+
.balance;
537+
538+
let handler: ArcEvmHandler<_, EVMError<Infallible>> =
539+
ArcEvmHandler::new(ArcHardforkFlags::default());
540+
let result = handler.reward_beneficiary(&mut evm, &mut exec_result);
541+
542+
assert!(
543+
result.is_ok(),
544+
"reward_beneficiary should succeed with large values"
545+
);
546+
547+
let expected_fee = U256::from(gas_price) * U256::from(gas_used);
548+
549+
let final_balance = evm
550+
.journaled_state
551+
.load_account(beneficiary)
552+
.unwrap()
553+
.info
554+
.balance;
555+
let balance_increase = final_balance - initial_balance;
556+
557+
assert_eq!(
558+
balance_increase, expected_fee,
559+
"Beneficiary should receive correct fee even with large values that would overflow u128"
560+
);
561+
}
562+
508563
#[derive(Debug)]
509564
struct BlocklistTestCase {
510565
name: &'static str,

crates/precompiles/src/native_coin_authority.rs

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,11 @@ stateful!(run_native_coin_authority, precompile_input, hardfork_flags; {
246246
&mut gas_counter,
247247
)?;
248248

249+
// Reject minting to zero address (Zero5+)
250+
if hardfork_flags.is_active(ArcHardfork::Zero5) && args.to == Address::ZERO {
251+
return Err(PrecompileErrorOrRevert::new_reverted(gas_counter, ERR_ZERO_ADDRESS));
252+
}
253+
249254
// Check blocklist
250255
if is_blocklisted(&mut precompile_input.internals, args.to, &mut gas_counter, hardfork_flags)? {
251256
return Err(PrecompileErrorOrRevert::new_reverted(gas_counter, ERR_BLOCKED_ADDRESS));
@@ -351,6 +356,11 @@ stateful!(run_native_coin_authority, precompile_input, hardfork_flags; {
351356
&mut gas_counter,
352357
)?;
353358

359+
// Reject burning from zero address (Zero5+)
360+
if hardfork_flags.is_active(ArcHardfork::Zero5) && args.from == Address::ZERO {
361+
return Err(PrecompileErrorOrRevert::new_reverted(gas_counter, ERR_ZERO_ADDRESS));
362+
}
363+
354364
// Check blocklist
355365
if is_blocklisted(&mut precompile_input.internals, args.from, &mut gas_counter, hardfork_flags)? {
356366
return Err(PrecompileErrorOrRevert::new_reverted(gas_counter, ERR_BLOCKED_ADDRESS));
@@ -1034,6 +1044,29 @@ mod tests {
10341044
bytecode_address: NATIVE_COIN_AUTHORITY_ADDRESS,
10351045
..Default::default()
10361046
},
1047+
// No auth SLOAD, zero-address check precedes blocklist SLOADs
1048+
NativeCoinAuthorityTest {
1049+
name: "mint() to zero address reverts (Zero5+)",
1050+
caller: ALLOWED_CALLER_ADDRESS,
1051+
calldata: INativeCoinAuthority::mintCall {
1052+
to: Address::ZERO,
1053+
amount: U256::from(1),
1054+
}
1055+
.abi_encode()
1056+
.into(),
1057+
gas_limit: MINT_GAS_COST,
1058+
pre_zero5_gas_limit: None,
1059+
expected_revert_str: Some(ERR_ZERO_ADDRESS),
1060+
expected_result: InstructionResult::Revert,
1061+
return_data: None,
1062+
blocklisted_addresses: None,
1063+
gas_used: 0,
1064+
pre_zero5_gas_used: None,
1065+
target_address: NATIVE_COIN_AUTHORITY_ADDRESS,
1066+
bytecode_address: NATIVE_COIN_AUTHORITY_ADDRESS,
1067+
eip7708_only: true,
1068+
..Default::default()
1069+
},
10371070
// No auth SLOAD, reverts immediately
10381071
NativeCoinAuthorityTest {
10391072
name: "burn() with unauthorized caller reverts",
@@ -1210,6 +1243,29 @@ mod tests {
12101243
bytecode_address: NATIVE_COIN_AUTHORITY_ADDRESS,
12111244
..Default::default()
12121245
},
1246+
// No auth SLOAD, zero-address check precedes blocklist SLOADs
1247+
NativeCoinAuthorityTest {
1248+
name: "burn() from zero address reverts (Zero5+)",
1249+
caller: ALLOWED_CALLER_ADDRESS,
1250+
calldata: INativeCoinAuthority::burnCall {
1251+
from: Address::ZERO,
1252+
amount: U256::from(1),
1253+
}
1254+
.abi_encode()
1255+
.into(),
1256+
gas_limit: BURN_GAS_COST,
1257+
pre_zero5_gas_limit: None,
1258+
expected_revert_str: Some(ERR_ZERO_ADDRESS),
1259+
expected_result: InstructionResult::Revert,
1260+
return_data: None,
1261+
blocklisted_addresses: None,
1262+
gas_used: 0,
1263+
pre_zero5_gas_used: None,
1264+
target_address: NATIVE_COIN_AUTHORITY_ADDRESS,
1265+
bytecode_address: NATIVE_COIN_AUTHORITY_ADDRESS,
1266+
eip7708_only: true,
1267+
..Default::default()
1268+
},
12131269
// No auth SLOAD, reverts immediately
12141270
NativeCoinAuthorityTest {
12151271
name: "transfer() with unauthorized caller reverts",
@@ -1342,7 +1398,7 @@ mod tests {
13421398
bytecode_address: ADDRESS_B,
13431399
..Default::default()
13441400
},
1345-
// Zero address checks (Zero5+) happen before blocklist SLOADs, so gas_used = 0
1401+
// No auth SLOAD, zero-address check precedes blocklist SLOADs
13461402
NativeCoinAuthorityTest {
13471403
name: "transfer() to zero address reverts (Zero5+)",
13481404
caller: ALLOWED_CALLER_ADDRESS,
@@ -1360,7 +1416,7 @@ mod tests {
13601416
return_data: None,
13611417
blocklisted_addresses: None,
13621418
gas_used: 0,
1363-
pre_zero5_gas_used: Some(PRECOMPILE_SLOAD_GAS_COST),
1419+
pre_zero5_gas_used: None,
13641420
target_address: NATIVE_COIN_AUTHORITY_ADDRESS,
13651421
bytecode_address: NATIVE_COIN_AUTHORITY_ADDRESS,
13661422
eip7708_only: true,
@@ -1383,7 +1439,7 @@ mod tests {
13831439
return_data: None,
13841440
blocklisted_addresses: None,
13851441
gas_used: 0,
1386-
pre_zero5_gas_used: Some(PRECOMPILE_SLOAD_GAS_COST),
1442+
pre_zero5_gas_used: None,
13871443
target_address: NATIVE_COIN_AUTHORITY_ADDRESS,
13881444
bytecode_address: NATIVE_COIN_AUTHORITY_ADDRESS,
13891445
eip7708_only: true,
@@ -1406,7 +1462,7 @@ mod tests {
14061462
return_data: None,
14071463
blocklisted_addresses: None,
14081464
gas_used: 0,
1409-
pre_zero5_gas_used: Some(PRECOMPILE_SLOAD_GAS_COST),
1465+
pre_zero5_gas_used: None,
14101466
target_address: NATIVE_COIN_AUTHORITY_ADDRESS,
14111467
bytecode_address: NATIVE_COIN_AUTHORITY_ADDRESS,
14121468
eip7708_only: true,

crates/quake/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,34 @@ The workflow runs **10 parallel jobs** (matrix indices 0–9). Each job computes
742742

743743
PRs labeled `test-random` will also trigger this workflow.
744744

745+
### The `clean` command
746+
747+
By default, `clean` removes all node data and configuration. The following flags control what is removed:
748+
749+
| Flag | Short | Description |
750+
|------|-------|-------------|
751+
| `--all` | `-a` | Remove everything, including monitoring services and their data. Cannot be combined with other flags. |
752+
| `--monitoring` | `-m` | Stop monitoring services and remove their data only. |
753+
| `--data` | `-d` | Remove only execution and consensus layer data, preserving configuration. Cannot be combined with `--execution-data` or `--consensus-data`. |
754+
| `--execution-data` | `-x` | Remove only execution layer (Reth) data. Cannot be combined with `--data` or `--consensus-data`. |
755+
| `--consensus-data` | `-c` | Remove only consensus layer (Malachite) data. Cannot be combined with `--data` or `--execution-data`. |
756+
757+
```bash
758+
# Remove node data only (keep config, monitoring intact)
759+
./quake clean --data
760+
761+
# Remove only execution layer data
762+
./quake clean --execution-data
763+
764+
# Remove only consensus layer data
765+
./quake clean --consensus-data
766+
767+
# Remove node data and monitoring
768+
./quake clean --data --monitoring
769+
770+
# Remove everything including monitoring
771+
./quake clean --all
772+
```
745773

746774
## Manifest File Format
747775

0 commit comments

Comments
 (0)