Skip to content

Commit

Permalink
fix: check retrun values of ERC20 transfer & transferFrom functions
Browse files Browse the repository at this point in the history
  • Loading branch information
irisdv committed May 21, 2024
1 parent 02d547b commit e6d9997
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 3 deletions.
3 changes: 2 additions & 1 deletion src/naming/internal.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,9 @@ impl InternalImpl of InternalTrait {
};

// pay the price
IERC20CamelDispatcher { contract_address: erc20 }
let has_payed = IERC20CamelDispatcher { contract_address: erc20 }
.transferFrom(get_caller_address(), get_contract_address(), discounted_price);
assert(has_payed, 'payment failed');
// add sponsor commission if eligible
if sponsor.into() != 0 {
IReferralDispatcher { contract_address: self._referral_contract.read() }
Expand Down
3 changes: 2 additions & 1 deletion src/naming/main.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -732,8 +732,9 @@ mod Naming {
assert(get_caller_address() == self._admin_address.read(), 'you are not admin');
let balance = IERC20CamelDispatcher { contract_address: erc20 }
.balanceOf(get_contract_address());
IERC20CamelDispatcher { contract_address: erc20 }
let has_claimed = IERC20CamelDispatcher { contract_address: erc20 }
.transfer(get_caller_address(), balance);
assert(has_claimed, 'Claim failed');
}

fn set_discount(ref self: ContractState, discount_id: felt252, discount: Discount) {
Expand Down
71 changes: 71 additions & 0 deletions src/tests/naming/common.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,74 @@ fn deploy_stark() -> IERC20CamelDispatcher {
let stark = utils::deploy(ERC20::TEST_CLASS_HASH, array![]);
IERC20CamelDispatcher { contract_address: stark }
}

fn deploy_with_erc20_fail() -> (IERC20CamelDispatcher, IPricingDispatcher, IIdentityDispatcher, INamingDispatcher) {
//erc20
let eth = utils::deploy(ERC20Fail::TEST_CLASS_HASH, array![]);

// pricing
let pricing = utils::deploy(Pricing::TEST_CLASS_HASH, array![eth.into()]);

// identity
let identity = utils::deploy(Identity::TEST_CLASS_HASH, array![0x123, 0, 0, 0]);

// naming
let admin = 0x123;
let address = utils::deploy(
Naming::TEST_CLASS_HASH, array![identity.into(), pricing.into(), 0, admin]
);

(
IERC20CamelDispatcher { contract_address: eth },
IPricingDispatcher { contract_address: pricing },
IIdentityDispatcher { contract_address: identity },
INamingDispatcher { contract_address: address }
)
}

#[starknet::contract]
mod ERC20Fail {
use starknet::ContractAddress;
use openzeppelin::token::erc20::erc20::ERC20Component::InternalTrait as ERC20InternalTrait;
use openzeppelin::{
token::erc20::{ERC20Component, dual20::DualCaseERC20Impl, ERC20HooksEmptyImpl}
};

component!(path: ERC20Component, storage: erc20, event: ERC20Event);

#[abi(embed_v0)]
impl ERC20Impl = ERC20Component::ERC20Impl<ContractState>;
impl ERC20CamelOnlyImpl = ERC20Component::ERC20CamelOnlyImpl<ContractState>;
impl ERC20InternalImpl = ERC20Component::InternalImpl<ContractState>;

#[constructor]
fn constructor(ref self: ContractState) {
self.erc20.initializer("ether", "ETH");
let target = starknet::contract_address_const::<0x123>();
self.erc20._mint(target, 0x100000000000000000000000000000000);
}

#[storage]
struct Storage {
#[substorage(v0)]
erc20: ERC20Component::Storage,
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
#[flat]
ERC20Event: ERC20Component::Event,
}

#[abi(per_item)]
#[generate_trait]
impl ExternalImpl of ExternalTrait {
#[external(v0)]
fn transferFrom(
ref self: ContractState, sender: ContractAddress, recipient: ContractAddress, amount: u256
) -> bool {
false
}
}
}
28 changes: 27 additions & 1 deletion src/tests/naming/test_abuses.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use naming::interface::naming::{INamingDispatcher, INamingDispatcherTrait};
use naming::interface::pricing::{IPricingDispatcher, IPricingDispatcherTrait};
use naming::naming::main::Naming;
use naming::pricing::Pricing;
use super::common::deploy;
use super::common::{deploy, deploy_with_erc20_fail};

#[test]
#[available_gas(2000000000)]
Expand Down Expand Up @@ -298,3 +298,29 @@ fn test_use_reset_subdomains() {
naming.transfer_domain(subsubdomain2, 4);
}

#[test]
#[available_gas(2000000000)]
#[should_panic(expected: ('payment failed', 'ENTRYPOINT_FAILED'))]
fn test_transfer_from_returns_false() {
// setup
let (eth, pricing, identity, naming) = deploy_with_erc20_fail();
let alpha = contract_address_const::<0x123>();

// we mint the id
set_contract_address(alpha);
identity.mint(1);

set_contract_address(alpha);
let aller: felt252 = 35683102;

// we check how much a domain costs
let (_, price) = pricing.compute_buy_price(5, 365);

// we allow the naming to take our money
eth.approve(naming.contract_address, price);

// we buy with no resolver, no sponsor, no discount and empty metadata
// in pay_domain transferFrom will return false
naming
.buy(1, aller, 365, ContractAddressZeroable::zero(), ContractAddressZeroable::zero(), 0, 0);
}

0 comments on commit e6d9997

Please sign in to comment.