ab_system_contract_address_allocator/
lib.rs1#![no_std]
2
3use ab_contracts_common::env::Env;
4use ab_contracts_common::{Address, ContractError, ShardIndex};
5use ab_contracts_io_type::trivial_type::TrivialType;
6use ab_contracts_macros::contract;
7
8#[derive(Debug, Copy, Clone, TrivialType)]
9#[repr(C)]
10pub struct AddressAllocator {
11 pub next_address: u128,
13 pub max_address: u128,
15}
16
17#[contract]
18impl AddressAllocator {
19 #[init]
21 pub fn new(#[env] env: &Env<'_>) -> Self {
22 let shard_index = env.shard_index();
23
24 let expected_self_address =
25 u128::from(shard_index.to_u32()) * ShardIndex::MAX_ADDRESSES_PER_SHARD.get();
26 debug_assert_eq!(
27 env.own_address(),
28 Address::from(expected_self_address),
29 "Unexpected allocator address"
30 );
31
32 Self {
33 next_address: expected_self_address + 1,
34 max_address: expected_self_address + ShardIndex::MAX_ADDRESSES_PER_SHARD.get() - 1,
35 }
36 }
37
38 #[update]
42 pub fn allocate_address(&mut self, #[env] env: &mut Env<'_>) -> Result<Address, ContractError> {
43 if env.caller() != Address::SYSTEM_CODE {
44 return Err(ContractError::Forbidden);
45 }
46
47 let next_address = self.next_address;
48 if next_address >= self.max_address {
49 return Err(ContractError::Forbidden);
51 }
52
53 self.next_address += 1;
54 Ok(Address::from(next_address))
55 }
56}