Skip to content

Commit

Permalink
Merge pull request #41 from armaanansari121/fix/send_transaction
Browse files Browse the repository at this point in the history
Fixed send_transaction function
  • Loading branch information
PoulavBhowmick03 authored Jan 24, 2025
2 parents bb2ad97 + a2e4a4b commit 79c75c5
Show file tree
Hide file tree
Showing 5 changed files with 313 additions and 193 deletions.
1 change: 1 addition & 0 deletions contracts/.tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
scarb 2.9.1
135 changes: 135 additions & 0 deletions contracts/Scarb.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,138 @@ version = 1
[[package]]
name = "contracts"
version = "0.1.0"
dependencies = [
"openzeppelin",
"snforge_std",
]

[[package]]
name = "openzeppelin"
version = "0.20.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:05fd9365be85a4a3e878135d5c52229f760b3861ce4ed314cb1e75b178b553da"
dependencies = [
"openzeppelin_access",
"openzeppelin_account",
"openzeppelin_finance",
"openzeppelin_governance",
"openzeppelin_introspection",
"openzeppelin_merkle_tree",
"openzeppelin_presets",
"openzeppelin_security",
"openzeppelin_token",
"openzeppelin_upgrades",
"openzeppelin_utils",
]

[[package]]
name = "openzeppelin_access"
version = "0.20.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:7734901a0ca7a7065e69416fea615dd1dc586c8dc9e76c032f25ee62e8b2a06c"
dependencies = [
"openzeppelin_introspection",
]

[[package]]
name = "openzeppelin_account"
version = "0.20.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:1aa3a71e2f40f66f98d96aa9bf9f361f53db0fd20fa83ef7df04426a3c3a926a"
dependencies = [
"openzeppelin_introspection",
"openzeppelin_utils",
]

[[package]]
name = "openzeppelin_finance"
version = "0.20.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:f0c507fbff955e4180ea3fa17949c0ff85518c40101f4948948d9d9a74143d6c"
dependencies = [
"openzeppelin_access",
"openzeppelin_token",
]

[[package]]
name = "openzeppelin_governance"
version = "0.20.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:c0fb60fad716413d537fabd5fcbb2c499ca6beb95af5f0d1699955ecec4c6f63"
dependencies = [
"openzeppelin_access",
"openzeppelin_account",
"openzeppelin_introspection",
"openzeppelin_token",
"openzeppelin_utils",
]

[[package]]
name = "openzeppelin_introspection"
version = "0.20.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:13e04a2190684e6804229a77a6c56de7d033db8b9ef519e5e8dee400a70d8a3d"

[[package]]
name = "openzeppelin_merkle_tree"
version = "0.20.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:039608900e92f3dcf479bf53a49a1fd76452acd97eb86e390d1eb92cacdaf3af"

[[package]]
name = "openzeppelin_presets"
version = "0.20.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:5c07a8de32e5d9abe33988c7927eaa8b5f83bc29dc77302d9c8c44c898611042"
dependencies = [
"openzeppelin_access",
"openzeppelin_account",
"openzeppelin_finance",
"openzeppelin_introspection",
"openzeppelin_token",
"openzeppelin_upgrades",
"openzeppelin_utils",
]

[[package]]
name = "openzeppelin_security"
version = "0.20.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:27155597019ecf971c48d7bfb07fa58cdc146d5297745570071732abca17f19f"

[[package]]
name = "openzeppelin_token"
version = "0.20.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:4452f449dc6c1ea97cf69d1d9182749abd40e85bd826cd79652c06a627eafd91"
dependencies = [
"openzeppelin_access",
"openzeppelin_account",
"openzeppelin_introspection",
"openzeppelin_utils",
]

[[package]]
name = "openzeppelin_upgrades"
version = "0.20.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:15fdd63f6b50a0fda7b3f8f434120aaf7637bcdfe6fd8d275ad57343d5ede5e1"

[[package]]
name = "openzeppelin_utils"
version = "0.20.0"
source = "registry+https://scarbs.xyz/"
checksum = "sha256:44f32d242af1e43982decc49c563e613a9b67ade552f5c3d5cde504e92f74607"

[[package]]
name = "snforge_scarb_plugin"
version = "0.33.0"
source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.33.0#221b1dbff42d650e9855afd4283508da8f8cacba"

[[package]]
name = "snforge_std"
version = "0.33.0"
source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.33.0#221b1dbff42d650e9855afd4283508da8f8cacba"
dependencies = [
"snforge_scarb_plugin",
]
7 changes: 5 additions & 2 deletions contracts/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ edition = "2024_07"
# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html

[dependencies]
starknet = "2.8.2"
starknet = "2.9.1"
openzeppelin = "0.20.0"

[dev-dependencies]
cairo_test = "2.7.0"
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.33.0" }
cairo_test = "2.9.1"
assert_macros = "2.9.1"

[[target.starknet-contract]]
casm = true
Expand Down
192 changes: 1 addition & 191 deletions contracts/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,191 +1 @@
use starknet::{
ContractAddress, get_caller_address, get_block_timestamp, get_contract_address,
contract_address_const, ClassHash,
};
use core::serde::Serde;

#[derive(Drop, Copy, starknet::Store, Serde)]
pub struct User {
pub username: felt252,
pub joined: u64,
pub has_membership: bool,
pub membership_expiration: u64,
}

#[starknet::interface]
pub trait IStarkfinder<TContractState> {
fn register(ref self: TContractState, account: ContractAddress, username: felt252);
fn get_user(self: @TContractState, account: ContractAddress) -> User;
fn send_transaction(ref self: TContractState, to: ContractAddress, amount: u128);
fn set_admin_wallet(ref self: TContractState, new_admin_wallet: ContractAddress);
}

#[starknet::interface]
pub trait IERC20<TContractState> {
fn balance_of(self: @TContractState, account: ContractAddress) -> u256;
fn allowance(self: @TContractState, owner: ContractAddress, spender: ContractAddress) -> u256;
fn transfer(ref self: TContractState, recipient: ContractAddress, amount: u256);
fn transferFrom(
ref self: TContractState, sender: ContractAddress, recipient: ContractAddress, amount: u256
);
}


#[starknet::contract]
mod starkfinder {
use super::{User, IERC20, IERC20Dispatcher, IERC20DispatcherTrait};
use starknet::{
ContractAddress, get_block_timestamp, get_caller_address, get_contract_address,
contract_address_const,
};
use core::starknet::storage::{
StoragePointerReadAccess, StoragePointerWriteAccess, Map, StoragePathEntry,
};
use core::serde::Serde;

const TRANSACTION_FEE_PERCENTAGE: u128 = 100;// 1%
const FEE_BASIS_POINTS: u128 = 10000;

#[storage]
struct Storage {
users: Map<ContractAddress, User>,
admin_wallet: ContractAddress,
token_address: ContractAddress,
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
TransactionExecuted: TransactionExecuted,
UserRegistered: UserRegistered,
AdminWalletChanged: AdminWalletChanged,
}

#[derive(Drop, starknet::Event)]
struct TransactionExecuted {
from: ContractAddress,
to: ContractAddress,
amount: u128,
fee: u128,
timestamp: u64,
}

#[derive(Drop, starknet::Event)]
struct UserRegistered {
user: ContractAddress,
username: felt252,
timestamp: u64,
}

#[derive(Drop, starknet::Event)]
struct AdminWalletChanged {
previous_admin: ContractAddress,
new_admin: ContractAddress,
timestamp: u64,
}

#[constructor]
fn constructor(
ref self: ContractState, admin_wallet: ContractAddress, token_address: ContractAddress
) {
self.admin_wallet.write(admin_wallet);
self.token_address.write(token_address);
}

#[abi(embed_v0)]
impl IStarkfinderImpl of super::IStarkfinder<ContractState> {
//register account of the user.
fn register(ref self: ContractState, account: ContractAddress, username: felt252) {
let caller_address = get_caller_address();
assert(account == caller_address, 'Register your own acc');

//create a new user
let user = User {
username: username,
joined: get_block_timestamp(),
has_membership: false,
membership_expiration: 0,
};
self.users.entry(account).write(user);

// Emit
self
.emit(
Event::UserRegistered(
UserRegistered {
user: account, username: username, timestamp: get_block_timestamp(),
}
)
);
}

// Send txn
fn send_transaction(ref self: ContractState, to: ContractAddress, amount: u128) {

let caller_address = get_caller_address();

//read the user data
let user = self.users.entry(caller_address).read();
//user is registered?
assert(user.joined != 0_u64, 'Caller is not a registered user');

let fee = (amount * TRANSACTION_FEE_PERCENTAGE) / FEE_BASIS_POINTS;
let total_amount = amount + fee;

let eth_contract = IERC20Dispatcher { contract_address: self.token_address.read() };

//caller's balance
let caller_balance = eth_contract.balance_of(caller_address);
let total_amount_u256 = total_amount.into();
assert(caller_balance >= total_amount_u256, 'Insufficient balance');

//allowance
let allowance = eth_contract.allowance(caller_address, get_contract_address());
assert(allowance >= total_amount_u256, 'Insufficient allowance');

// Execute transfers
// Transfer main amount to recipient
eth_contract.transferFrom(caller_address, to, amount.into());

// Transfer fee to admin wallet
eth_contract.transferFrom(caller_address, self.admin_wallet.read(), fee.into());

// Emit transaction event
self
.emit(
Event::TransactionExecuted(
TransactionExecuted {
from: caller_address, to, amount, fee, timestamp: get_block_timestamp(),
}
)
);

}

//user information
fn get_user(self: @ContractState, account: ContractAddress) -> User {
self.users.entry(account).read()
}

/// Updates the admin wallet address
fn set_admin_wallet(ref self: ContractState, new_admin_wallet: ContractAddress) {
let caller_address = get_caller_address();
let current_admin_wallet = self.admin_wallet.read();
assert(caller_address == current_admin_wallet, 'Only admin privilege');

// Emit
self
.emit(
Event::AdminWalletChanged(
AdminWalletChanged {
previous_admin: current_admin_wallet,
new_admin: new_admin_wallet,
timestamp: get_block_timestamp(),
}
)
);

self.admin_wallet.write(new_admin_wallet);
}
}
}
mod starkfinder;
Loading

0 comments on commit 79c75c5

Please sign in to comment.