Skip to content

Commit

Permalink
add Camel impl
Browse files Browse the repository at this point in the history
  • Loading branch information
notV4l committed Jan 5, 2024
1 parent 4043d13 commit 79fddfd
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ mod erc20_balance_mock {
impl ERC20BalanceImpl =
erc20_balance_component::ERC20BalanceImpl<ContractState>;

#[abi(embed_v0)]
impl ERC20BalanceCamelImpl =
erc20_balance_component::ERC20BalanceCamelImpl<ContractState>;

impl ERC20AllowanceInternalImpl = erc20_allowance_component::InternalImpl<ContractState>;
impl ERC20BalanceInternalImpl = erc20_balance_component::InternalImpl<ContractState>;

Expand Down
74 changes: 55 additions & 19 deletions token/src/components/tests/token/erc20/test_erc20_balance.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use token::components::token::erc20::erc20_allowance::erc20_allowance_component:
};
use token::components::token::erc20::erc20_balance::{erc_20_balance_model, ERC20BalanceModel,};
use token::components::token::erc20::erc20_balance::erc20_balance_component::{
Transfer, ERC20BalanceImpl, InternalImpl as ERC20BalanceInternalImpl
Transfer, ERC20BalanceImpl, ERC20BalanceCamelImpl, InternalImpl as ERC20BalanceInternalImpl
};
use token::components::tests::mocks::erc20::erc20_balance_mock::{
erc20_balance_mock, IERC20BalanceMockDispatcher, IERC20BalanceMockDispatcherTrait
Expand All @@ -30,7 +30,7 @@ use debug::PrintTrait;
// events helpers
//

fn assert_eventtransfer_internal(
fn assert_event_transfer(
emitter: ContractAddress, from: ContractAddress, to: ContractAddress, value: u256
) {
let event = utils::pop_log::<Transfer>(emitter).unwrap();
Expand All @@ -39,10 +39,10 @@ fn assert_eventtransfer_internal(
assert(event.value == value, 'Invalid `value`');
}

fn assert_only_eventtransfer_internal(
fn assert_only_event_transfer(
emitter: ContractAddress, from: ContractAddress, to: ContractAddress, value: u256
) {
assert_eventtransfer_internal(emitter, from, to, value);
assert_event_transfer(emitter, from, to, value);
utils::assert_no_events_left(emitter);
}

Expand Down Expand Up @@ -71,6 +71,10 @@ fn test_erc20_balance_initialize() {
assert(state.erc20_balance.balance_of(ADMIN()) == 0, 'Should be 0');
assert(state.erc20_balance.balance_of(OWNER()) == 0, 'Should be 0');
assert(state.erc20_balance.balance_of(OTHER()) == 0, 'Should be 0');

assert(state.erc20_balance.balanceOf(ADMIN()) == 0, 'Should be 0');
assert(state.erc20_balance.balanceOf(OWNER()) == 0, 'Should be 0');
assert(state.erc20_balance.balanceOf(OTHER()) == 0, 'Should be 0');
}

//
Expand Down Expand Up @@ -126,12 +130,12 @@ fn test_erc20_balance_transfer_internal() {
state.erc20_balance.transfer_internal(ADMIN(), OTHER(), 100);
assert(state.erc20_balance.balance_of(ADMIN()) == 320, 'Should be 320');
assert(state.erc20_balance.balance_of(OTHER()) == 1100, 'Should be 1100');
assert_only_eventtransfer_internal(ZERO(), ADMIN(), OTHER(), 100);
assert_only_event_transfer(ZERO(), ADMIN(), OTHER(), 100);

state.erc20_balance.transfer_internal(OTHER(), ADMIN(), 1000);
assert(state.erc20_balance.balance_of(ADMIN()) == 1320, 'Should be 1320');
assert(state.erc20_balance.balance_of(OTHER()) == 100, 'Should be 100');
assert_only_eventtransfer_internal(ZERO(), OTHER(), ADMIN(), 1000);
assert_only_event_transfer(ZERO(), OTHER(), ADMIN(), 1000);
}

#[test]
Expand Down Expand Up @@ -189,7 +193,7 @@ fn setup() -> (IWorldDispatcher, IERC20BalanceMockDispatcher) {

#[test]
#[available_gas(40000000)]
fn test_transfer_internal_from() {
fn test_transfer_from() {
let (world, mut erc20_balance_mock) = setup();

utils::impersonate(OWNER());
Expand All @@ -202,17 +206,15 @@ fn test_transfer_internal_from() {
assert(erc20_balance_mock.transfer_from(OWNER(), RECIPIENT(), VALUE), 'Should return true');

assert_event_approval(erc20_balance_mock.contract_address, OWNER(), SPENDER(), 0);
assert_only_eventtransfer_internal(
erc20_balance_mock.contract_address, OWNER(), RECIPIENT(), VALUE
);
assert_only_event_transfer(erc20_balance_mock.contract_address, OWNER(), RECIPIENT(), VALUE);

// drop StoreSetRecord ERC20AllowanceModel
utils::drop_event(world.contract_address);
assert_event_approval(world.contract_address, OWNER(), SPENDER(), 0);
// drop StoreSetRecord ERC20BalanceModel x2
utils::drop_event(world.contract_address);
utils::drop_event(world.contract_address);
assert_only_eventtransfer_internal(world.contract_address, OWNER(), RECIPIENT(), VALUE);
assert_only_event_transfer(world.contract_address, OWNER(), RECIPIENT(), VALUE);

assert(erc20_balance_mock.balance_of(RECIPIENT()) == VALUE, 'Should eq amount');
assert(erc20_balance_mock.balance_of(OWNER()) == SUPPLY - VALUE, 'Should eq suppy - amount');
Expand All @@ -222,7 +224,7 @@ fn test_transfer_internal_from() {

#[test]
#[available_gas(25000000)]
fn test_transfer_internal_from_doesnt_consume_infinite_allowance() {
fn test_transfer_from_doesnt_consume_infinite_allowance() {
let (world, mut erc20_balance_mock) = setup();

utils::impersonate(OWNER());
Expand All @@ -234,14 +236,12 @@ fn test_transfer_internal_from_doesnt_consume_infinite_allowance() {
utils::impersonate(SPENDER());
erc20_balance_mock.transfer_from(OWNER(), RECIPIENT(), VALUE);

assert_only_eventtransfer_internal(
erc20_balance_mock.contract_address, OWNER(), RECIPIENT(), VALUE
);
assert_only_event_transfer(erc20_balance_mock.contract_address, OWNER(), RECIPIENT(), VALUE);

// drop StoreSetRecord ERC20BalanceModel x2
utils::drop_event(world.contract_address);
utils::drop_event(world.contract_address);
assert_only_eventtransfer_internal(world.contract_address, OWNER(), RECIPIENT(), VALUE);
assert_only_event_transfer(world.contract_address, OWNER(), RECIPIENT(), VALUE);

assert(
erc20_balance_mock.allowance(OWNER(), SPENDER()) == BoundedInt::max(),
Expand All @@ -253,7 +253,7 @@ fn test_transfer_internal_from_doesnt_consume_infinite_allowance() {
#[test]
#[available_gas(25000000)]
#[should_panic(expected: ('u256_sub Overflow', 'ENTRYPOINT_FAILED'))]
fn test_transfer_internal_from_greater_than_allowance() {
fn test_transfer_from_greater_than_allowance() {
let (world, mut erc20_balance_mock) = setup();

utils::impersonate(OWNER());
Expand All @@ -268,7 +268,7 @@ fn test_transfer_internal_from_greater_than_allowance() {
#[test]
#[available_gas(25000000)]
#[should_panic(expected: ('ERC20: transfer to 0', 'ENTRYPOINT_FAILED'))]
fn test_transfer_internal_from_to_zero_address() {
fn test_transfer_from_to_zero_address() {
let (world, mut erc20_balance_mock) = setup();

utils::impersonate(OWNER());
Expand All @@ -281,8 +281,44 @@ fn test_transfer_internal_from_to_zero_address() {
#[test]
#[available_gas(25000000)]
#[should_panic(expected: ('u256_sub Overflow', 'ENTRYPOINT_FAILED'))]
fn test_transfer_internal_from_from_zero_address() {
fn test_transfer_from_from_zero_address() {
let (world, mut erc20_balance_mock) = setup();

erc20_balance_mock.transfer_from(ZERO(), RECIPIENT(), VALUE);
}


//
// transferFrom
//

#[test]
#[available_gas(40000000)]
fn test_transferFrom() {
let (world, mut erc20_balance_mock) = setup();

utils::impersonate(OWNER());
erc20_balance_mock.approve(SPENDER(), VALUE);

utils::drop_all_events(erc20_balance_mock.contract_address);
utils::drop_all_events(world.contract_address);

utils::impersonate(SPENDER());
assert(erc20_balance_mock.transferFrom(OWNER(), RECIPIENT(), VALUE), 'Should return true');

assert_event_approval(erc20_balance_mock.contract_address, OWNER(), SPENDER(), 0);
assert_only_event_transfer(erc20_balance_mock.contract_address, OWNER(), RECIPIENT(), VALUE);

// drop StoreSetRecord ERC20AllowanceModel
utils::drop_event(world.contract_address);
assert_event_approval(world.contract_address, OWNER(), SPENDER(), 0);
// drop StoreSetRecord ERC20BalanceModel x2
utils::drop_event(world.contract_address);
utils::drop_event(world.contract_address);
assert_only_event_transfer(world.contract_address, OWNER(), RECIPIENT(), VALUE);

assert(erc20_balance_mock.balance_of(RECIPIENT()) == VALUE, 'Should eq amount');
assert(erc20_balance_mock.balance_of(OWNER()) == SUPPLY - VALUE, 'Should eq suppy - amount');
assert(erc20_balance_mock.allowance(OWNER(), SPENDER()) == 0, 'Should eq 0');
// assert(erc20_balance_mock.total_supply() == SUPPLY, 'Total supply should not change');
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use token::tests::constants::{NAME, SYMBOL, DECIMALS};

use token::components::token::erc20::erc20_metadata::{erc_20_metadata_model, ERC20MetadataModel,};
use token::components::token::erc20::erc20_metadata::erc20_metadata_component::{
ERC20MetadataImpl, ERC20MetadataTotalSupplyImpl, InternalImpl
ERC20MetadataImpl, ERC20MetadataTotalSupplyImpl, ERC20MetadataTotalSupplyCamelImpl, InternalImpl
};
use token::components::tests::mocks::erc20::erc20_metadata_mock::erc20_metadata_mock;
use token::components::tests::mocks::erc20::erc20_metadata_mock::erc20_metadata_mock::world_dispatcherContractMemberStateTrait;
Expand All @@ -31,6 +31,7 @@ fn test_erc20_metadata_initialize() {
assert(state.erc20_metadata.symbol() == SYMBOL, 'Should be SYMBOL');
assert(state.erc20_metadata.decimals() == DECIMALS, 'Should be 18');
assert(state.erc20_metadata.total_supply() == 0, 'Should be 0');
assert(state.erc20_metadata.totalSupply() == 0, 'Should be 0');
}

#[test]
Expand Down
33 changes: 33 additions & 0 deletions token/src/components/token/erc20/erc20_balance.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,23 @@ trait IERC20Balance<TState> {
) -> bool;
}

#[starknet::interface]
trait IERC20BalanceCamel<TState> {
fn balanceOf(self: @TState, account: ContractAddress) -> u256;
fn transferFrom(
ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
) -> bool;
}

///
/// ERC20Balance Component
///
#[starknet::component]
mod erc20_balance_component {
use super::ERC20BalanceModel;
use super::IERC20Balance;
use super::IERC20BalanceCamel;

use starknet::ContractAddress;
use starknet::{get_contract_address, get_caller_address};
use dojo::world::{
Expand Down Expand Up @@ -97,6 +107,29 @@ mod erc20_balance_component {
}
}

#[embeddable_as(ERC20BalanceCamelImpl)]
impl ERC20BalanceCamel<
TContractState,
+HasComponent<TContractState>,
+IWorldProvider<TContractState>,
impl ERC20Allowance: erc20_allowance_comp::HasComponent<TContractState>,
+Drop<TContractState>,
> of IERC20BalanceCamel<ComponentState<TContractState>> {
fn balanceOf(self: @ComponentState<TContractState>, account: ContractAddress) -> u256 {
self.balance_of(account)
}

fn transferFrom(
ref self: ComponentState<TContractState>,
sender: ContractAddress,
recipient: ContractAddress,
amount: u256
) -> bool {
self.transfer_from(sender, recipient, amount)
}
}


#[generate_trait]
impl InternalImpl<
TContractState,
Expand Down
18 changes: 18 additions & 0 deletions token/src/components/token/erc20/erc20_metadata.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ trait IERC20MetadataTotalSupply<TState> {
fn total_supply(self: @TState) -> u256;
}

#[starknet::interface]
trait IERC20MetadataTotalSupplyCamel<TState> {
fn totalSupply(self: @TState) -> u256;
}

///
/// ERC20Metadata Component
///
Expand All @@ -38,6 +43,7 @@ mod erc20_metadata_component {
use super::ERC20MetadataModel;
use super::IERC20Metadata;
use super::IERC20MetadataTotalSupply;
use super::IERC20MetadataTotalSupplyCamel;

use starknet::get_contract_address;
use dojo::world::{
Expand Down Expand Up @@ -77,6 +83,18 @@ mod erc20_metadata_component {
}
}

#[embeddable_as(ERC20MetadataTotalSupplyCamelImpl)]
impl ERC20MetadataTotalSupplyCamel<
TContractState,
+HasComponent<TContractState>,
+IWorldProvider<TContractState>,
+Drop<TContractState>,
> of IERC20MetadataTotalSupplyCamel<ComponentState<TContractState>> {
fn totalSupply(self: @ComponentState<TContractState>) -> u256 {
self.total_supply()
}
}


#[generate_trait]
impl InternalImpl<
Expand Down
52 changes: 34 additions & 18 deletions token/src/presets/erc20/bridgeable.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,56 @@ use dojo::world::IWorldDispatcher;

#[starknet::interface]
trait IERC20BridgeablePreset<TState> {
// IERC20
// IWorldProvider
fn world(self: @TState,) -> IWorldDispatcher;

// IUpgradeable
fn upgrade(ref self: TState, new_class_hash: ClassHash);

// IERC20Metadata
fn decimals(self: @TState,) -> u8;
fn name(self: @TState,) -> felt252;
fn symbol(self: @TState,) -> felt252;

// IERC20MetadataTotalSupply
fn total_supply(self: @TState,) -> u256;

// IERC20MetadataTotalSupplyCamel
fn totalSupply(self: @TState,) -> u256;

// IERC20Balance
fn balance_of(self: @TState, account: ContractAddress) -> u256;
fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool;
fn transfer_from(
ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
) -> bool;
fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;

// IERC20CamelOnly
fn totalSupply(self: @TState,) -> u256;
// IERC20BalanceCamel
fn balanceOf(self: @TState, account: ContractAddress) -> u256;
fn transferFrom(
ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256
) -> bool;

// IERC20Metadata
fn name(self: @TState,) -> felt252;
fn symbol(self: @TState,) -> felt252;
fn decimals(self: @TState,) -> u8;
// IERC20Allowance
fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256;
fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool;

// IERC20SafeAllowance
fn increase_allowance(ref self: TState, spender: ContractAddress, added_value: u256) -> bool;
fn decrease_allowance(
ref self: TState, spender: ContractAddress, subtracted_value: u256
) -> bool;
fn increase_allowance(ref self: TState, spender: ContractAddress, added_value: u256) -> bool;

// IERC20SafeAllowanceCamel
fn increaseAllowance(ref self: TState, spender: ContractAddress, addedValue: u256) -> bool;
fn decreaseAllowance(ref self: TState, spender: ContractAddress, subtractedValue: u256) -> bool;
fn increaseAllowance(ref self: TState, spender: ContractAddress, addedValue: u256) -> bool;

// IERC20Bridgeable
fn burn(ref self: TState, account: ContractAddress, amount: u256);
fn l2_bridge_address(self: @TState,) -> ContractAddress;
fn mint(ref self: TState, recipient: ContractAddress, amount: u256);
fn burn(ref self: TState, account: ContractAddress, amount: u256);

// IWorldProvider
fn world(self: @TState,) -> IWorldDispatcher;

// IUpgradeable
fn upgrade(ref self: TState, new_class_hash: ClassHash);

// WITHOUT INTERFACE !!!
fn initializer(
ref self: TState,
name: felt252,
Expand All @@ -54,6 +61,7 @@ trait IERC20BridgeablePreset<TState> {
recipient: ContractAddress,
l2_bridge_address: ContractAddress
);
fn dojo_resource(self: @TState,) -> felt252;
}


Expand Down Expand Up @@ -132,10 +140,18 @@ mod ERC20Bridgeable {
impl ERC20MetadataTotalSupplyImpl =
erc20_metadata_component::ERC20MetadataTotalSupplyImpl<ContractState>;

#[abi(embed_v0)]
impl ERC20MetadataTotalSupplyCamelImpl =
erc20_metadata_component::ERC20MetadataTotalSupplyCamelImpl<ContractState>;

#[abi(embed_v0)]
impl ERC20BalanceImpl =
erc20_balance_component::ERC20BalanceImpl<ContractState>;

#[abi(embed_v0)]
impl ERC20BalanceCamelImpl =
erc20_balance_component::ERC20BalanceCamelImpl<ContractState>;

#[abi(embed_v0)]
impl ERC20AllowanceImpl =
erc20_allowance_component::ERC20AllowanceImpl<ContractState>;
Expand Down
Loading

0 comments on commit 79fddfd

Please sign in to comment.