diff --git a/contracts/flash_loan_provider/Cargo.toml b/contracts/flash_loan_provider/Cargo.toml new file mode 100644 index 000000000..5fcda13ba --- /dev/null +++ b/contracts/flash_loan_provider/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "flash-loan-provider" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +soroban-sdk = "28.0.0" + +[dev-dependencies] +soroban-sdk = { version = "28.0.0", features = ["testutils"] } diff --git a/contracts/flash_loan_provider/src/lib.rs b/contracts/flash_loan_provider/src/lib.rs new file mode 100644 index 000000000..86ce8c3ea --- /dev/null +++ b/contracts/flash_loan_provider/src/lib.rs @@ -0,0 +1,42 @@ +#![no_std] + +use soroban_sdk::{contract, contracterror, contractimpl, panic_with_error, Address, Env, token}; + +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum FlashLoanError { + InvalidAmount = 1, + NotRepaid = 2, + AlreadyInitialized = 3, + NotInitialized = 4, +} + +#[contract] +pub struct FlashLoanProvider; + +#[contractimpl] +impl FlashLoanProvider { + pub fn initialize(env: Env, admin: Address, token: Address, fee_bps: i128) { + if env.storage().instance().has(&("admin")) { + panic_with_error!(&env, FlashLoanError::AlreadyInitialized); + } + env.storage().instance().set(&("admin"), &admin); + env.storage().instance().set(&("token"), &token); + env.storage().instance().set(&("fee_bps"), &fee_bps); + } + + pub fn flash_loan(env: Env, borrower: Address, amount: i128) -> i128 { + if amount <= 0 { + panic_with_error!(&env, FlashLoanError::InvalidAmount); + } + let token_addr: Address = env.storage().instance().get(&("token")).unwrap(); + let fee_bps: i128 = env.storage().instance().get(&("fee_bps")).unwrap_or(10); + let token = token::Client::new(&env, &token_addr); + let contract_addr = env.current_contract_address(); + token.transfer(&contract_addr, &borrower, &amount); + let fee = (amount * fee_bps) / 10_000; + let repay = amount + fee; + token.transfer(&borrower, &contract_addr, &repay); + repay + } +} diff --git a/contracts/yield_farming/Cargo.toml b/contracts/yield_farming/Cargo.toml new file mode 100644 index 000000000..517915e56 --- /dev/null +++ b/contracts/yield_farming/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "yield-farming" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +soroban-sdk = "28.0.0" + +[dev-dependencies] +soroban-sdk = { version = "28.0.0", features = ["testutils"] } diff --git a/contracts/yield_farming/src/lib.rs b/contracts/yield_farming/src/lib.rs new file mode 100644 index 000000000..5709c61d3 --- /dev/null +++ b/contracts/yield_farming/src/lib.rs @@ -0,0 +1,31 @@ +#![no_std] + +use soroban_sdk::{contract, contractimpl, Address, Env, token}; + +#[contract] +pub struct YieldFarmingPool; + +#[contractimpl] +impl YieldFarmingPool { + pub fn initialize(env: Env, admin: Address, staking_token: Address, reward_token: Address, reward_rate: i128) { + env.storage().instance().set(&("admin"), &admin); + env.storage().instance().set(&("staking_token"), &staking_token); + env.storage().instance().set(&("reward_token"), &reward_token); + env.storage().instance().set(&("reward_rate"), &reward_rate); + env.storage().instance().set(&("total_staked"), &0i128); + } + + pub fn stake(env: Env, user: Address, amount: i128) { + let staking_token_addr: Address = env.storage().instance().get(&("staking_token")).unwrap(); + let staking_token = token::Client::new(&env, &staking_token_addr); + staking_token.transfer(&user, &env.current_contract_address(), &amount); + let total: i128 = env.storage().instance().get(&("total_staked")).unwrap_or(0); + env.storage().instance().set(&("total_staked"), &(total + amount)); + } + + pub fn get_reward_per_token(env: Env) -> i128 { + let total: i128 = env.storage().instance().get(&("total_staked")).unwrap_or(0); + let rate: i128 = env.storage().instance().get(&("reward_rate")).unwrap_or(1); + if total == 0 { 0 } else { rate * 1000 / total } + } +} diff --git a/frontend/src/components/WasmDecompilerInspector.tsx b/frontend/src/components/WasmDecompilerInspector.tsx new file mode 100644 index 000000000..93ea59f04 --- /dev/null +++ b/frontend/src/components/WasmDecompilerInspector.tsx @@ -0,0 +1,53 @@ +"use client"; + +import { useState } from "react"; + +export function WasmDecompilerInspector() { + const [file, setFile] = useState(null); + const [disassembly, setDisassembly] = useState(""); + const [analyzing, setAnalyzing] = useState(false); + + const handleFileChange = (e: React.ChangeEvent) => { + if (e.target.files?.[0]) { + setFile(e.target.files[0]); + } + }; + + const analyze = async () => { + if (!file) return; + setAnalyzing(true); + try { + // Mock disassembly - would use actual WASM decompiler + const mockDisasm = [ + "00000000: 0061 736d 0100 0000 0106 017f 027f 037f .asm............", + "00000010: 0130 0000 0000 0201 0444 4d45 4d4f 0003 .0.......DMEMO..", + "00000020: 0001 0004 0001 0000 0005 0301 0001 0006 ................", + "00000030: 1501 027f 0080 0080 8000 000b 0701 000a ................", + ].join("\n"); + setDisassembly(mockDisasm); + } finally { + setAnalyzing(false); + } + }; + + return ( +
+

WASM Decompiler & Disassembly Inspector

+
+ + +
+ {disassembly && ( +
+          {disassembly}
+        
+ )} +
+ ); +} diff --git a/frontend/src/components/__tests__/WasmDecompilerInspector.test.tsx b/frontend/src/components/__tests__/WasmDecompilerInspector.test.tsx new file mode 100644 index 000000000..dfc7c1a70 --- /dev/null +++ b/frontend/src/components/__tests__/WasmDecompilerInspector.test.tsx @@ -0,0 +1,9 @@ +import { render, screen } from "@testing-library/react"; +import { WasmDecompilerInspector } from "../WasmDecompilerInspector"; + +describe("WasmDecompilerInspector", () => { + it("renders decompiler interface", () => { + render(); + expect(screen.getByText(/WASM Decompiler/i)).toBeInTheDocument(); + }); +});