Skip to content

Commit

Permalink
Remove deprecated LegacyMap (#2608)
Browse files Browse the repository at this point in the history
<!-- Reference any GitHub issues resolved by this PR -->

Closes #2598

## Introduced changes

<!-- A brief description of the changes -->

- Replace `LegacyMap` storage mapping with `Map`

## Checklist

<!-- Make sure all of these are complete -->

- [x] Linked relevant issue
- [x] Updated relevant documentation
- [x] Added relevant tests
- [x] Performed self-review of the code
- [x] Added changes to `CHANGELOG.md`

---------

Co-authored-by: Franciszek Job <[email protected]>
  • Loading branch information
sprtd and franciszekjob authored Oct 30, 2024
1 parent 370c3ef commit 647483a
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 63 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
#[starknet::contract]
mod MapSimpleValueSimpleKey {
use starknet::{
storage::{StoragePointerWriteAccess, StorageMapReadAccess, StoragePathEntry, Map}
};
#[storage]
struct Storage {
values: LegacyMap<felt252, felt252>,
values: Map<felt252, felt252>,
}

#[external(v0)]
fn insert(ref self: ContractState, key: felt252, value: felt252) {
self.values.write(key, value);
self.values.entry(key).write(value);
}

#[external(v0)]
fn read(self: @ContractState, key: felt252) -> felt252 {
self.values.read(key)
self.values.entry(key).read()
}
}
30 changes: 17 additions & 13 deletions crates/forge/tests/data/component_macros/src/oz_ac_component.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
/// The SRC5 component allows contracts to expose the interfaces they implement.
#[starknet::component]
mod SRC5Component {
use starknet::ContractAddress;
use starknet::{
storage::{StoragePointerWriteAccess, StorageMapReadAccess, StoragePathEntry, Map},
ContractAddress
};

const ISRC5_ID: felt252 = 0x3f918d17e5ee77373b56385708f855659a07f75997f365cf87748628532a055;

Expand All @@ -15,7 +18,7 @@ mod SRC5Component {

#[storage]
struct Storage {
SRC5_supported_interfaces: LegacyMap<felt252, bool>
SRC5_supported_interfaces: Map<felt252, bool>
}

mod Errors {
Expand All @@ -33,7 +36,7 @@ mod SRC5Component {
if interface_id == ISRC5_ID {
return true;
}
self.SRC5_supported_interfaces.read(interface_id)
self.SRC5_supported_interfaces.entry(interface_id).read()
}
}

Expand All @@ -43,21 +46,21 @@ mod SRC5Component {
> of InternalTrait<TContractState> {
/// Registers the given interface as supported by the contract.
fn register_interface(ref self: ComponentState<TContractState>, interface_id: felt252) {
self.SRC5_supported_interfaces.write(interface_id, true);
self.SRC5_supported_interfaces.entry(interface_id).write(true);
}

/// Deregisters the given interface as supported by the contract.
fn deregister_interface(ref self: ComponentState<TContractState>, interface_id: felt252) {
assert(interface_id != ISRC5_ID, Errors::INVALID_ID);
self.SRC5_supported_interfaces.write(interface_id, false);
self.SRC5_supported_interfaces.entry(interface_id).write(true);
}
}
}


#[starknet::component]
mod AccessControlComponent {
use starknet::ContractAddress;
use starknet::{storage::{StoragePointerWriteAccess, StoragePathEntry, Map}, ContractAddress};
use starknet::get_caller_address;
use super::SRC5Component;
use super::SRC5Component::InternalTrait as SRC5InternalTrait;
Expand All @@ -74,8 +77,8 @@ mod AccessControlComponent {

#[storage]
struct Storage {
AccessControl_role_admin: LegacyMap<felt252, felt252>,
AccessControl_role_member: LegacyMap<(felt252, ContractAddress), bool>,
AccessControl_role_admin: Map<felt252, felt252>,
AccessControl_role_member: Map<(felt252, ContractAddress), bool>,
}

#[event]
Expand Down Expand Up @@ -136,12 +139,12 @@ mod AccessControlComponent {
fn has_role(
self: @ComponentState<TContractState>, role: felt252, account: ContractAddress
) -> bool {
self.AccessControl_role_member.read((role, account))
self.AccessControl_role_member.entry((role, account)).read()
}

/// Returns the admin role that controls `role`.
fn get_role_admin(self: @ComponentState<TContractState>, role: felt252) -> felt252 {
self.AccessControl_role_admin.read(role)
self.AccessControl_role_admin.entry(role).read()
}

/// Grants `role` to `account`.
Expand Down Expand Up @@ -228,7 +231,7 @@ mod AccessControlComponent {
) {
if !self.has_role(role, account) {
let caller: ContractAddress = get_caller_address();
self.AccessControl_role_member.write((role, account), true);
self.AccessControl_role_member.entry((role, account)).write(true);
self.emit(RoleGranted { role, account, sender: caller });
}
}
Expand All @@ -243,7 +246,7 @@ mod AccessControlComponent {
) {
if self.has_role(role, account) {
let caller: ContractAddress = get_caller_address();
self.AccessControl_role_member.write((role, account), false);
self.AccessControl_role_member.entry((role, account)).write(false);
self.emit(RoleRevoked { role, account, sender: caller });
}
}
Expand All @@ -255,8 +258,9 @@ mod AccessControlComponent {
ref self: ComponentState<TContractState>, role: felt252, admin_role: felt252
) {
let previous_admin_role: felt252 = self.get_role_admin(role);
self.AccessControl_role_admin.write(role, admin_role);
self.AccessControl_role_admin.entry(role).write(admin_role);
self.emit(RoleAdminChanged { role, previous_admin_role, new_admin_role: admin_role });
}
}
}

34 changes: 19 additions & 15 deletions crates/forge/tests/data/contracts/erc20.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,23 @@ trait IERC20<TContractState> {

#[starknet::contract]
mod ERC20 {
use starknet::{
contract_address_const, get_caller_address, ContractAddress,
storage::{
StoragePointerWriteAccess, StorageMapReadAccess,
StoragePathEntry, Map
},
};
use zeroable::Zeroable;
use starknet::get_caller_address;
use starknet::contract_address_const;
use starknet::ContractAddress;

#[storage]
struct Storage {
name: felt252,
symbol: felt252,
decimals: u8,
total_supply: u256,
balances: LegacyMap::<ContractAddress, u256>,
allowances: LegacyMap::<(ContractAddress, ContractAddress), u256>,
balances: Map<ContractAddress, u256>,
allowances: Map<(ContractAddress, ContractAddress), u256>,
}

#[event]
Expand Down Expand Up @@ -69,7 +73,7 @@ mod ERC20 {
self.decimals.write(decimals_);
assert(!recipient.is_zero(), 'ERC20: mint to the 0 address');
self.total_supply.write(initial_supply);
self.balances.write(recipient, initial_supply);
self.balances.entry(recipient).write(initial_supply);
self
.emit(
Event::Transfer(
Expand Down Expand Up @@ -99,13 +103,13 @@ mod ERC20 {
}

fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {
self.balances.read(account)
self.balances.entry(account).read()
}

fn allowance(
self: @ContractState, owner: ContractAddress, spender: ContractAddress
) -> u256 {
self.allowances.read((owner, spender))
self.allowances.entry((owner, spender)).read()
}

fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) {
Expand Down Expand Up @@ -135,7 +139,7 @@ mod ERC20 {
let caller = get_caller_address();
self
.approve_helper(
caller, spender, self.allowances.read((caller, spender)) + added_value
caller, spender, self.allowances.entry((caller, spender)).read() + added_value
);
}

Expand All @@ -145,7 +149,7 @@ mod ERC20 {
let caller = get_caller_address();
self
.approve_helper(
caller, spender, self.allowances.read((caller, spender)) - subtracted_value
caller, spender, self.allowances.entry((caller, spender)).read() - subtracted_value
);
}
}
Expand All @@ -160,15 +164,15 @@ mod ERC20 {
) {
assert(!sender.is_zero(), 'ERC20: transfer from 0');
assert(!recipient.is_zero(), 'ERC20: transfer to 0');
self.balances.write(sender, self.balances.read(sender) - amount);
self.balances.write(recipient, self.balances.read(recipient) + amount);
self.balances.entry(sender).write(self.balances.entry(sender).read() - amount);
self.balances.entry(recipient).write(self.balances.entry(recipient).read() + amount);
self.emit(Event::Transfer(Transfer { from: sender, to: recipient, value: amount }));
}

fn spend_allowance(
ref self: ContractState, owner: ContractAddress, spender: ContractAddress, amount: u256
) {
let current_allowance = self.allowances.read((owner, spender));
let current_allowance = self.allowances.entry((owner, spender)).read();
let ONES_MASK = 0xffffffffffffffffffffffffffffffff_u128;
let is_unlimited_allowance = current_allowance.low == ONES_MASK
&& current_allowance.high == ONES_MASK;
Expand All @@ -181,8 +185,8 @@ mod ERC20 {
ref self: ContractState, owner: ContractAddress, spender: ContractAddress, amount: u256
) {
assert(!spender.is_zero(), 'ERC20: approve from 0');
self.allowances.write((owner, spender), amount);
self.allowances.entry((owner, spender)).write(amount);
self.emit(Event::Approval(Approval { owner, spender, value: amount }));
}
}
}
}
32 changes: 17 additions & 15 deletions crates/forge/tests/data/erc20_package/src/erc20.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ trait IERC20<TContractState> {

#[starknet::contract]
mod ERC20 {
use starknet::{
contract_address_const, get_caller_address, ContractAddress,
storage::{StoragePointerWriteAccess, StorageMapReadAccess, StoragePathEntry, Map},
};
use zeroable::Zeroable;
use starknet::get_caller_address;
use starknet::contract_address_const;
use starknet::ContractAddress;

#[storage]
struct Storage {
name: felt252,
symbol: felt252,
decimals: u8,
total_supply: u256,
balances: LegacyMap::<ContractAddress, u256>,
allowances: LegacyMap::<(ContractAddress, ContractAddress), u256>,
balances: Map<ContractAddress, u256>,
allowances: Map<(ContractAddress, ContractAddress), u256>,
}

#[event]
Expand Down Expand Up @@ -69,7 +69,7 @@ mod ERC20 {
self.decimals.write(decimals_);
assert(!recipient.is_zero(), 'ERC20: mint to the 0 address');
self.total_supply.write(initial_supply);
self.balances.write(recipient, initial_supply);
self.balances.entry(recipient).write(initial_supply);
self
.emit(
Event::Transfer(
Expand Down Expand Up @@ -99,13 +99,13 @@ mod ERC20 {
}

fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {
self.balances.read(account)
self.balances.entry(account).read()
}

fn allowance(
self: @ContractState, owner: ContractAddress, spender: ContractAddress
) -> u256 {
self.allowances.read((owner, spender))
self.allowances.entry((owner, spender)).read()
}

fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) {
Expand Down Expand Up @@ -135,7 +135,7 @@ mod ERC20 {
let caller = get_caller_address();
self
.approve_helper(
caller, spender, self.allowances.read((caller, spender)) + added_value
caller, spender, self.allowances.entry((caller, spender)).read() + added_value
);
}

Expand All @@ -145,7 +145,9 @@ mod ERC20 {
let caller = get_caller_address();
self
.approve_helper(
caller, spender, self.allowances.read((caller, spender)) - subtracted_value
caller,
spender,
self.allowances.entry((caller, spender)).read() - subtracted_value
);
}
}
Expand All @@ -160,15 +162,15 @@ mod ERC20 {
) {
assert(!sender.is_zero(), 'ERC20: transfer from 0');
assert(!recipient.is_zero(), 'ERC20: transfer to 0');
self.balances.write(sender, self.balances.read(sender) - amount);
self.balances.write(recipient, self.balances.read(recipient) + amount);
self.balances.entry(sender).write(self.balances.entry(sender).read() - amount);
self.balances.entry(recipient).write(self.balances.entry(recipient).read() + amount);
self.emit(Event::Transfer(Transfer { from: sender, to: recipient, value: amount }));
}

fn spend_allowance(
ref self: ContractState, owner: ContractAddress, spender: ContractAddress, amount: u256
) {
let current_allowance = self.allowances.read((owner, spender));
let current_allowance = self.allowances.entry((owner, spender)).read();
let ONES_MASK = 0xffffffffffffffffffffffffffffffff_u128;
let is_unlimited_allowance = current_allowance.low == ONES_MASK
&& current_allowance.high == ONES_MASK;
Expand All @@ -181,7 +183,7 @@ mod ERC20 {
ref self: ContractState, owner: ContractAddress, spender: ContractAddress, amount: u256
) {
assert(!spender.is_zero(), 'ERC20: approve from 0');
self.allowances.write((owner, spender), amount);
self.allowances.entry((owner, spender)).write(amount);
self.emit(Event::Approval(Approval { owner, spender, value: amount }));
}
}
Expand Down
1 change: 0 additions & 1 deletion crates/forge/tests/e2e/running.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1061,7 +1061,6 @@ fn detailed_resources_flag() {
memory holes: [..]
builtins: ([..])
syscalls: ([..])
Tests: 1 passed, 0 failed, 0 skipped, 0 ignored, 0 filtered out
"},
);
Expand Down
4 changes: 3 additions & 1 deletion crates/forge/tests/integration/test_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,8 @@ fn storage_access_default_values() {
r"
#[starknet::contract]
mod Contract {
use starknet::storage::{
StoragePointerWriteAccess, StorageMapReadAccess, StoragePathEntry, Map };
#[derive(starknet::Store, Drop)]
struct CustomStruct {
a: felt252,
Expand All @@ -415,7 +417,7 @@ fn storage_access_default_values() {
#[storage]
struct Storage {
balance: felt252,
legacy_map: LegacyMap<felt252, felt252>,
legacy_map: Map<felt252, felt252>,
custom_struct: CustomStruct,
}
}
Expand Down
11 changes: 7 additions & 4 deletions crates/sncast/tests/data/contracts/map/src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,22 @@ trait IMap<TMapState> {

#[starknet::contract]
mod Map {
use starknet::{
storage::{StoragePointerWriteAccess, StorageMapReadAccess, StoragePathEntry, Map}
};
#[storage]
struct Storage {
storage: LegacyMap::<felt252, felt252>,
storage: Map<felt252, felt252>,
}

#[abi(embed_v0)]
impl Map of super::IMap<ContractState> {
impl MapImpl of super::IMap<ContractState> {
fn put(ref self: ContractState, key: felt252, value: felt252) {
self.storage.write(key, value);
self.storage.entry(key).write(value);
}

fn get(self: @ContractState, key: felt252) -> felt252 {
self.storage.read(key)
self.storage.entry(key).read()
}
}
}
Loading

0 comments on commit 647483a

Please sign in to comment.