From bcac541d73bd3bf055330932f9baf72eeb152f06 Mon Sep 17 00:00:00 2001 From: "Nwele Uchenna (developeruche)" Date: Fri, 12 Jan 2024 00:47:08 +0100 Subject: [PATCH] mod: added awesome defi ink --- .DS_Store | Bin 0 -> 10244 bytes ink-awesome-defi/.DS_Store | Bin 0 -> 6148 bytes ink-awesome-defi/README.md | 15 + .../synthetix-staking-reward/.DS_Store | Bin 0 -> 6148 bytes .../synthetix-staking-reward/.gitignore | 1 + .../synthetix-staking-reward/Cargo.toml | 33 ++ .../synthetix-staking-reward/contracts.rs | 3 + .../contracts/.DS_Store | Bin 0 -> 6148 bytes .../contracts/Cargo.toml | 39 +++ .../contracts/controllers/mod.rs | 1 + .../contracts/controllers/staking_reward.rs | 80 +++++ .../contracts/global.rs | 4 + .../contracts/modules/.DS_Store | Bin 0 -> 6148 bytes .../contracts/modules/psp22_lp/.DS_Store | Bin 0 -> 6148 bytes .../contracts/modules/psp22_lp/.gitignore | 9 + .../contracts/modules/psp22_lp/Cargo.toml | 31 ++ .../contracts/modules/psp22_lp/psp22_lp.rs | 64 ++++ .../modules/staking_reward/.DS_Store | Bin 0 -> 6148 bytes .../modules/staking_reward/.gitignore | 9 + .../modules/staking_reward/Cargo.toml | 41 +++ .../modules/staking_reward/staking_reward.rs | 216 +++++++++++++ .../contracts/providers/.DS_Store | Bin 0 -> 6148 bytes .../contracts/providers/common/database.rs | 2 + .../contracts/providers/common/errors.rs | 45 +++ .../contracts/providers/common/mod.rs | 2 + .../contracts/providers/data/mod.rs | 1 + .../providers/data/staking_reward.rs | 46 +++ .../contracts/providers/deployables/mod.rs | 1 + .../providers/deployables/staking_reward.rs | 277 +++++++++++++++++ .../contracts/providers/mod.rs | 3 + .../uniswap-v2-core-ink/.DS_Store | Bin 0 -> 6148 bytes .../uniswap-v2-core-ink/.gitignore | 1 + .../uniswap-v2-core-ink/Cargo.toml | 34 +++ .../uniswap-v2-core-ink/contracts.rs | 3 + .../uniswap-v2-core-ink/contracts/.DS_Store | Bin 0 -> 6148 bytes .../uniswap-v2-core-ink/contracts/Cargo.toml | 39 +++ .../contracts/controllers/factory.rs | 25 ++ .../contracts/controllers/mod.rs | 2 + .../contracts/controllers/pair.rs | 51 ++++ .../uniswap-v2-core-ink/contracts/global.rs | 4 + .../contracts/modules/.DS_Store | Bin 0 -> 6148 bytes .../contracts/modules/factory/.DS_Store | Bin 0 -> 6148 bytes .../contracts/modules/factory/.gitignore | 9 + .../contracts/modules/factory/Cargo.toml | 35 +++ .../contracts/modules/factory/factory.rs | 97 ++++++ .../contracts/modules/pair/.DS_Store | Bin 0 -> 6148 bytes .../contracts/modules/pair/.gitignore | 9 + .../contracts/modules/pair/Cargo.toml | 41 +++ .../contracts/modules/pair/pair.rs | 200 ++++++++++++ .../contracts/modules/psp22_lp/.DS_Store | Bin 0 -> 6148 bytes .../contracts/modules/psp22_lp/.gitignore | 9 + .../contracts/modules/psp22_lp/Cargo.toml | 31 ++ .../contracts/modules/psp22_lp/psp22_lp.rs | 64 ++++ .../contracts/providers/common/database.rs | 2 + .../contracts/providers/common/errors.rs | 48 +++ .../contracts/providers/common/mod.rs | 2 + .../contracts/providers/data/factory.rs | 31 ++ .../contracts/providers/data/mod.rs | 2 + .../contracts/providers/data/pair.rs | 116 +++++++ .../providers/deployables/factory.rs | 37 +++ .../contracts/providers/deployables/mod.rs | 2 + .../contracts/providers/deployables/pair.rs | 284 ++++++++++++++++++ .../contracts/providers/mod.rs | 3 + 63 files changed, 2104 insertions(+) create mode 100644 .DS_Store create mode 100644 ink-awesome-defi/.DS_Store create mode 100644 ink-awesome-defi/README.md create mode 100644 ink-awesome-defi/synthetix-staking-reward/.DS_Store create mode 100644 ink-awesome-defi/synthetix-staking-reward/.gitignore create mode 100644 ink-awesome-defi/synthetix-staking-reward/Cargo.toml create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts.rs create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/.DS_Store create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/Cargo.toml create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/controllers/mod.rs create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/controllers/staking_reward.rs create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/global.rs create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/modules/.DS_Store create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/.DS_Store create mode 100755 ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/.gitignore create mode 100755 ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/Cargo.toml create mode 100755 ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/psp22_lp.rs create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/.DS_Store create mode 100755 ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/.gitignore create mode 100755 ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/Cargo.toml create mode 100755 ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/staking_reward.rs create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/providers/.DS_Store create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/providers/common/database.rs create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/providers/common/errors.rs create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/providers/common/mod.rs create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/providers/data/mod.rs create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/providers/data/staking_reward.rs create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/providers/deployables/mod.rs create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/providers/deployables/staking_reward.rs create mode 100644 ink-awesome-defi/synthetix-staking-reward/contracts/providers/mod.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/.DS_Store create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/.gitignore create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/Cargo.toml create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/.DS_Store create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/Cargo.toml create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/controllers/factory.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/controllers/mod.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/controllers/pair.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/global.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/.DS_Store create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/factory/.DS_Store create mode 100755 ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/factory/.gitignore create mode 100755 ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/factory/Cargo.toml create mode 100755 ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/factory/factory.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/pair/.DS_Store create mode 100755 ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/pair/.gitignore create mode 100755 ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/pair/Cargo.toml create mode 100755 ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/pair/pair.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/.DS_Store create mode 100755 ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/.gitignore create mode 100755 ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/Cargo.toml create mode 100755 ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/psp22_lp.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/common/database.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/common/errors.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/common/mod.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/data/factory.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/data/mod.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/data/pair.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/deployables/factory.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/deployables/mod.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/deployables/pair.rs create mode 100644 ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/mod.rs diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..35a90142dcc02757296ce65935af37ac78ec9c30 GIT binary patch literal 10244 zcmeHNO>ZMb5UqBy>j};VFG~a$&`5CL5CRPJBa1=^pjexLvQh`gL`UyAu&nN7MeENGKu!DrJ2W zw%25KsaWF>9i;2H1?cm_NJo&nFm|A7I#vsr?gk^b%(@Cygs7CQT+WTusRK8?1%O;fvo3hXK0sr_T()vKH&R1k)9fBp4psRULm4=}52+5> z%H`Zh0~clBqVk?qzC%&Eci=*;E~;guzk3Ee17!xdci)z-bYvotvwt6>t%rR)ck~^J zaSderG){ZnIPC((h4vVA_a9yGB=QO@McDrjp}Q+T!Y0lF3Ygyun9YU#hKyyZ&kiD5 zaB=Fb0`3jqc+${EkD2Z@(SDi}h@p(o7NaHqu3+ugg0M-`1+b);{WWblg6B8@xC^)N~y5;PpVqH_y0ADDvc>>Kb(p zo;osvK34?ip#hc$=s$9ORN$%doi*~6`0i{n%2(tc-BBD(vS#y7RaslVcfT4`gIe%y z`*}KRXPs<1IqHnR=BF>xH1589?sUJ52D8)p>rc`o>qN<5tN~Gf0F`gPijsahJ4&ZX zf1cyA{y0a^7r+mTSRJu;&yOtZj5!CsPqa5Z?f-Hsm_x?{`cKq8t_E;F z>D9tK$oE6xouFB^eb_>;9BY3yRx@s6H{==t;$%8aJ%mc zR!Si&X^w53ZRm^;&t#2xtb_MHe;<^YD)IyFo%~kC`-xeRD>EssCbH>hKSB;IM&!yq z8R3qVMdI-fo&nE*XTUSy8MuQCteG)~HOLeE1i#_$|96lXKV;9q-C;njAGeQ>FkWt~ zmldA1hp6A9vQTesq=w+8kK-ZraXdcoIQ~6U>NY7^@Z8Gf+(@*b{O5lRF#nljT5c#9+JY|yL9b4#rf#70qPWf>hhC!49@^qckx7IVt&!v?!5DOI zKc?4yNq?t#v%7&fZXqR5irImgw>z^l@;-TYwL~QP)A$8Zn}{4JW8(qLZ-nElOR{D> zO`uRU-q9Xy(J96I>C$NHunbrR{x=4A?Y8Iu>voq0bZ!00qbQXTqP#WiLbrY?L5rwE z1zk`^C7sX+HlcIcgs-HK#^_~qjDC(-1y9cV!9u<7cdZvy#l-x+AJHUDiqi9binaB| zz57k4>1;TkgA-W=Wmry&ewcsc-l3Ffbkz={_sOUlwjaNhSs5nTC|3zdJi?GqACfGV zRbNiCxKO!)4md5RHEefgv!2)My05(6yz9<+_h(3a%3{&pc1S`5A4)9+6b+Z>o1OUSwZ9MdtOl zdCMv*!uc&{dxL3EwsKqpiUL$iXn75{H_`28>}_zbQ0$BAoYb^to zfkg(^b+^su|K6YP|BFesXBn^ztP}&HF$e~IOv#+BOOxZX)`fn7vhcWCqe_7>$FXYg dQQUzlLCoa_&^K6Xga=|j1QZR{SO)$n1D66I(7gZv literal 0 HcmV?d00001 diff --git a/ink-awesome-defi/README.md b/ink-awesome-defi/README.md new file mode 100644 index 00000000..3e833b1a --- /dev/null +++ b/ink-awesome-defi/README.md @@ -0,0 +1,15 @@ +# Ink! Awesome DeFi + + +This is a Repo of Notable Smart contracts re-writen in Ink! domain (pallet-smart-contract) specific lanaguage. it outlines how production worthy smart contract should be built and structured. Smart contracts within this repo utilizes the awesome [Openbrush](https://openbrush.brushfam.io/) library of smart contract and utilities. This repo contains; + +1. Uniswap V2 Ink! Implementation. +2. Synthetix staking reward contract +3. Uniswap V3 still in the works (it complicated math libs got me lazy. Ticks 😒) + + +My hopes for this Repo is for it to be a good resource for engineers/teams looking to build production worth smart contracts and wish other awesome developers would build into this repo other more complicated smart contracts making this Repo more useful to a wider range of teams in the polkaDeFI space. + + +## Want to contribute? +My buddy [Ayo](https://github.com/Adebara123), built a [template](https://github.com/Adebara123/Ink-Contract-Template) which I used to build these smart contracts and I would be employing you contributor to use that also. diff --git a/ink-awesome-defi/synthetix-staking-reward/.DS_Store b/ink-awesome-defi/synthetix-staking-reward/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..330dd1945c5070e1e78a28599e15ada18aaa9001 GIT binary patch literal 6148 zcmeHKK~LK-6n-upBx6WDfW!sK(ykR`qaYzJp}=9+W!etg)FrfH5g|rNN)J_~oVOpd z>wd}p&h|aqptWJ@ZJLIk^!z>B?{kvRi5(M>=#Pglh&n{%!5LdViU*AQ*&EifEvrDG z$56CO87aD;t46kK_!kx6xqC{d6jMQ$n7RA;dzGn+BvT3c`Q{@ z=i36u$9thDrwZ4K5m!{sGsMnvMlvaH?0tPtZnCtjg5ZZ}t+b!4u6b+Ty7w{qtR_(v zSL3oD7w@_DMyV{hi{s>NI+_eRo2M$T;xr!>nvf1hNcr$C&4+5zSL1wGYHnmYJm2#N zo$cwg7xcRFAn47ya(eVK=*r&y;cVu6ThI57Uk|Rb>s)nWa5cBUMbEL)4Vr>vTFkz@bLlyRjAq*Yu(&mL0YlDVP!X7?^y|S<; z6rrz<@uf~D5gK%*Q@|-OufU3_c6k3k|MU5Op5$sy0jI!!rGRLkMQ43HlHFSy56640 tgnxpwab9iko`OJc#mMEYcpI(_?UDmvXt6ek7MS}H&@#BfDezYn_ys+5glYf) literal 0 HcmV?d00001 diff --git a/ink-awesome-defi/synthetix-staking-reward/.gitignore b/ink-awesome-defi/synthetix-staking-reward/.gitignore new file mode 100644 index 00000000..c41cc9e3 --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/.gitignore @@ -0,0 +1 @@ +/target \ No newline at end of file diff --git a/ink-awesome-defi/synthetix-staking-reward/Cargo.toml b/ink-awesome-defi/synthetix-staking-reward/Cargo.toml new file mode 100644 index 00000000..9b92544b --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "contracts" +version = "0.1.0" +authors = ["developreuche "] +edition = "2021" + +[dependencies] +ink = { version = "4.2.1", default-features = false } + +openbrush = { git = "https://github.com/727-Ventures/openbrush-contracts", version = "4.0.0-beta.1", default-features = false, features = ["psp22","ownable","access_control", "psp34", "reentrancy_guard", "pausable"] } +psp22_lp = { path = "contracts/modules/psp22_lp", default-features = false } +staking_reward = { path = "contracts/modules/staking_reward", default-features = false } +global = {path = "contracts", default-features = false} +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } + +[dev-dependencies] +ink_e2e = "4.2.0" + +[lib] +path = "contracts.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", + + "openbrush/std", +] +ink-as-dependency = [] +e2e-tests = [] diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts.rs b/ink-awesome-defi/synthetix-staking-reward/contracts.rs new file mode 100644 index 00000000..58233ec9 --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts.rs @@ -0,0 +1,3 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +pub use global; \ No newline at end of file diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/.DS_Store b/ink-awesome-defi/synthetix-staking-reward/contracts/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..78e19c687d209dd56ef48acd6b86a9067f0cf117 GIT binary patch literal 6148 zcmeH~L2uJA6vv;pLX%ZUJ%F?eQY5a`2vCsFE}EA~9KH4~T|D6Op&b0w29Ib! zCx|Yv+DoX!Zw9YwWqtj-taMq;?O5N^xy-9N48Mz=-QJCxeXs8gy!Y`(wT$beUR0B$ ze9KR-l#=O%pQNwz*>XC(eWZ#y$%|R36Y^|^kautLB2&wWS`=BOb7Rxt`JO)=?ypwk za6AeghvW4qSUr6hj)L){C+oHE-MM%F@a6QAJS)^^J!=x!=d|6jdLdunT*Kr%E(@uO zQ$%pK56%+IQZSd`-JvG#BI+{hKK4^Z87(yB7GuF9{~>xy*tQsSn9lWkcuqMuZFm#K zj}|4LIvHC+YQxN0w17gJeV0An1DrVmj({U@nE>w(0SaqmwK1x<4pjOI0PUe!8+`s; z;GDo}WVJDh9+)txP?IX`6+@VGv"] +edition = "2021" + +[dependencies] +ink = { version = "4.2.0", default-features = false } + +openbrush = { git = "https://github.com/727-Ventures/openbrush-contracts", version = "4.0.0-beta.1", default-features = false, features = ["psp22","ownable","access_control", "psp34", "reentrancy_guard", "pausable"]} + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } +sp-arithmetic = { version = "15", default-features = false } + +[dev-dependencies] +ink_e2e = "4.2.0" + +[lib] +path = "global.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", + + "openbrush/std", + "sp-arithmetic/std", +] +ink-as-dependency = [] +e2e-tests = [] + +[profile.dev] +overflow-checks = false + +[profile.release] +overflow-checks = false \ No newline at end of file diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/controllers/mod.rs b/ink-awesome-defi/synthetix-staking-reward/contracts/controllers/mod.rs new file mode 100644 index 00000000..3b1d20f9 --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/controllers/mod.rs @@ -0,0 +1 @@ +pub mod staking_reward; \ No newline at end of file diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/controllers/staking_reward.rs b/ink-awesome-defi/synthetix-staking-reward/contracts/controllers/staking_reward.rs new file mode 100644 index 00000000..6206f39b --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/controllers/staking_reward.rs @@ -0,0 +1,80 @@ + +use openbrush::traits::AccountId; +use openbrush::traits::Balance; +use crate::providers::common::errors::StakingRewardsErrors; + + + +#[openbrush::wrapper] +pub type StakingRewardRef = dyn StakingRewardController; + +#[openbrush::trait_definition] +pub trait StakingRewardController { + #[ink(message)] + fn get_reward_token(&self) -> AccountId; + + #[ink(message)] + fn get_staked_token(&self) -> AccountId; + + #[ink(message)] + fn get_reward_rate(&self) -> Balance; + + #[ink(message)] + fn get_period_finish(&self) -> Balance; + + #[ink(message)] + fn get_reward_duration(&self) -> Balance; + + #[ink(message)] + fn get_last_update_time(&self) -> Balance; + + #[ink(message)] + fn get_reward_per_token_stored(&self) -> Balance; + + #[ink(message)] + fn get_user_reward_per_token_paid(&self, _account: AccountId) -> Balance; + + #[ink(message)] + fn get_rewards(&self, _account: AccountId) -> Balance; + + #[ink(message)] + fn total_supply(&self) -> Balance; + + #[ink(message)] + fn balance_of(&self, _account: AccountId) -> Balance; + + #[ink(message)] + fn last_time_reward_applicable(&self) -> Balance; + + #[ink(message)] + fn reward_per_token(&self) -> Balance; + + #[ink(message)] + fn earned(&self, _account: AccountId) -> Balance; + + #[ink(message)] + fn get_reward_for_duration(&self) -> Balance; + + + + #[ink(message)] + fn stake(&mut self, _amount: Balance) -> Result<(), StakingRewardsErrors>; + + #[ink(message)] + fn withdraw(&mut self, _amount: Balance) -> Result<(), StakingRewardsErrors>; + + #[ink(message)] + fn get_reward(&mut self) -> Result<(), StakingRewardsErrors>; + + #[ink(message)] + fn exit(&mut self) -> Result<(), StakingRewardsErrors>; + + #[ink(message)] + fn notify_reward_amount(&mut self, _reward: Balance) -> Result<(), StakingRewardsErrors>; + + #[ink(message)] + fn recover_erc20(&mut self, _token: AccountId, _amount: Balance) -> Result<(), StakingRewardsErrors>; + + #[ink(message)] + fn set_reward_duration(&mut self, _duration: Balance) -> Result<(), StakingRewardsErrors>; +} \ No newline at end of file diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/global.rs b/ink-awesome-defi/synthetix-staking-reward/contracts/global.rs new file mode 100644 index 00000000..26a14f59 --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/global.rs @@ -0,0 +1,4 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +pub mod controllers; +pub mod providers; \ No newline at end of file diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/modules/.DS_Store b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..4378fcb3ba0ff5cf07bb9223ca60be6422129e1a GIT binary patch literal 6148 zcmeHK&u`N(6n@^y<}!hL0BIK_OI#}mr65gQvN8@_34+5wB_Y*_7UC*NmqS%4XZVNs zOZa!T@7dnQ$k>rhlVA1x+3!bef0FG!A`+8D`iy8mL=wu_yNl)$VLxj})|_PnD9krT zG^L#8Z*%>%6YUM20nflqV}Q@Dq&Zd45q@XqH_3GZA1(&*2>9gKh*^FoK544Ci~p6( z^Q@|a;I~*?@7>whl$&x(evZEBCaU9lQBC4+Q9kv!>f%rcHh6dkw2L3ApCq#X$82|tP literal 0 HcmV?d00001 diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/.DS_Store b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ee9c024ff056a4d8e159a0be998f86ddeea37bd2 GIT binary patch literal 6148 zcmeHKyG{c^3>=db5ouD=Ang}Kf-hJlp`hjifPh4E=%NJr>+(7IL>NDaI1XA0up@hR zy`J0L6z5$4vUq*G0A>ItbVckn3{BV72X+z}MX_hJnBxU4p3w}dzfUOl6ieJ=izhOV z{OhKDSU2sO>-y&o^!b|^N5B*t?C6*L-Ey}LnOp4oEII$eGHQlYAQeajQh`+9Un{_# ztu~oDW=sWAfmGnAfPNneU9kpsj`rzb(Br$Vj}_H8wz~we#JmP}j$EOMQ;ANMxMGOY znJ-aS13O2jLu_Y0Cw7*&p@{9ye6ey!b>Q2GywQny5KvvxQi0!4 F;2nr1D5C%X literal 0 HcmV?d00001 diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/.gitignore b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/.gitignore new file mode 100755 index 00000000..8de8f877 --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/Cargo.toml b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/Cargo.toml new file mode 100755 index 00000000..672d68fb --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "psp22_lp" +version = "0.1.0" +authors = ["developeruche "] +edition = "2021" + +[dependencies] +ink = { version = "4.2.0", default-features = false } +openbrush = { git = "https://github.com/727-Ventures/openbrush-contracts", version = "4.0.0-beta.1", default-features = false, features = ["psp22","ownable","access_control", "psp34", "reentrancy_guard", "pausable"] } +global = {path = "./../../", default-features = false} + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } + +[dev-dependencies] +ink_e2e = "4.2.0" + +[lib] +path = "psp22_lp.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", + + "openbrush/std", +] +ink-as-dependency = [] +e2e-tests = [] diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/psp22_lp.rs b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/psp22_lp.rs new file mode 100755 index 00000000..d44e567c --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/psp22_lp/psp22_lp.rs @@ -0,0 +1,64 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + + + + + +#[openbrush::implementation(PSP22, PSP22Permit, Nonces, PSP22Mintable, Ownable, PSP22Metadata)] +#[openbrush::contract] +pub mod psp22_permit { + use openbrush::{traits::Storage, modifiers}; + + + #[ink(storage)] + #[derive(Default, Storage)] + pub struct PSP22Lp { + #[storage_field] + psp22: psp22::Data, + #[storage_field] + metadata: metadata::Data, + #[storage_field] + ownable: ownable::Data, + #[storage_field] + nonces: nonces::Data, + #[storage_field] + psp22_permit: psp22::extensions::permit::Data, + + } + + + #[default_impl(PSP22Mintable)] + #[modifiers(only_owner)] + fn mint(&mut self) {} + + + + + + + impl PSP22Lp { + #[ink(constructor)] + pub fn new(total_supply: Balance, name: Option, symbol: Option, decimal: u8) -> Self { + let mut instance = Self::default(); + let caller = instance.env().caller(); + + instance.metadata.name.set(&name); + instance.metadata.symbol.set(&symbol); + instance.metadata.decimals.set(&decimal); + + ownable::Internal::_init_with_owner(&mut instance, Self::env().caller()); + psp22::Internal::_mint_to(&mut instance, caller, total_supply).expect("Should mint total_supply"); + + + instance + } + + + + #[ink(message)] + pub fn burn(&mut self, _amount: Balance) -> Result<(), PSP22Error> { + let caller = self.env().caller(); + psp22::Internal::_burn_from(self, caller, _amount) + } + } +} diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/.DS_Store b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a0ef4a6ab8f917c5c9af3d0de03c5330d6404c05 GIT binary patch literal 6148 zcmeHKOG*Pl5PhXt1l`1)8=+4S@CIXy3)db%O(G&09Y`W>=SCh;UwsVBI6FZ^s-XK- zx_&(m(%l6>X0NMrU;<#wp(v^hh%OJB4#N46D3+ta6g3(wu^veD7ngMJN4Ug2HhARD z_xr!Do8_Wz7PKol7aY?M6KegK9V4Gn_hR0AF(=q!$4YBF;f2+1S@QvJR(r+D8*IB7 z+^yffQ}5csamS&eeyu7L>YYabf9N@K eYDTvg)#+CSwvL)b*Daiw4*?@2r)1z482AKTB{*sT literal 0 HcmV?d00001 diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/.gitignore b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/.gitignore new file mode 100755 index 00000000..8de8f877 --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/Cargo.toml b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/Cargo.toml new file mode 100755 index 00000000..9c88266d --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "staking_reward" +version = "0.1.0" +authors = ["developeruche "] +edition = "2021" + +[dependencies] +ink = { version = "4.2.0", default-features = false } + +openbrush = { git = "https://github.com/727-Ventures/openbrush-contracts", version = "4.0.0-beta.1", default-features = false , features = ["psp22","ownable","access_control", "psp34", "reentrancy_guard", "pausable"]} +global = {path = "./../../", default-features = false} + + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } + +[dev-dependencies] +ink_e2e = "4.2.0" + +[lib] +path = "staking_reward.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", + + "openbrush/std", + "global/std" +] +ink-as-dependency = [] +e2e-tests = [] + + +[profile.dev] +overflow-checks = false + +[profile.release] +overflow-checks = false \ No newline at end of file diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/staking_reward.rs b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/staking_reward.rs new file mode 100755 index 00000000..2594b131 --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/modules/staking_reward/staking_reward.rs @@ -0,0 +1,216 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + + + +#[ink::contract] +mod staking_reward { + use ink::prelude::vec::Vec; + use global::providers::common::errors::StakingRewardsErrors; + use global::providers::data::staking_reward::StakingStorage; + use global::controllers::staking_reward::stakingrewardcontroller_external::StakingRewardController; + use global::providers::deployables::staking_reward::StakingRewardImpl; + use openbrush::contracts::ownable; + use openbrush::traits::Storage; + use global::controllers::staking_reward::stakingrewardcontroller_external; + + + + // ====================================== + // Storage + // ====================================== + #[ink(storage)] + #[derive(Default, Storage)] + pub struct StakingReward { + #[storage_field] + pub staking_state: StakingStorage, + #[storage_field] + ownable: ownable::Data, + } + + + + // ====================================== + // Events + // ====================================== + #[ink(event)] + pub struct Staked { + #[ink(topic)] + caller:AccountId, + amount: Balance, + } + + #[ink(event)] + pub struct Withdraw { + #[ink(topic)] + caller:AccountId, + amount: Balance, + } + + #[ink(event)] + pub struct RewardPaid { + #[ink(topic)] + caller:AccountId, + reward: Balance, + } + + #[ink(event)] + pub struct RewardNotified { + reward: Balance, + } + + #[ink(event)] + pub struct DurationUpdate { + duration: Balance, + } + + + + + impl StakingRewardImpl for StakingReward {} + + + impl StakingRewardController for StakingReward { + #[ink(message)] + fn total_supply(&self) -> Balance { + StakingRewardImpl::total_supply(self) + } + + #[ink(message)] + fn get_reward_token(&self) -> AccountId { + StakingRewardImpl::get_reward_token(self) + } + + #[ink(message)] + fn get_staked_token(&self) -> AccountId { + StakingRewardImpl::get_staked_token(self) + } + + #[ink(message)] + fn get_reward_rate(&self) -> Balance { + StakingRewardImpl::get_reward_rate(self) + } + + #[ink(message)] + fn get_period_finish(&self) -> Balance { + StakingRewardImpl::get_period_finish(self) + } + + #[ink(message)] + fn get_reward_duration(&self) -> Balance { + StakingRewardImpl::get_reward_duration(self) + } + + #[ink(message)] + fn get_last_update_time(&self) -> Balance { + StakingRewardImpl::get_last_update_time(self) + } + + #[ink(message)] + fn get_reward_per_token_stored(&self) -> Balance { + StakingRewardImpl::get_reward_per_token_stored(self) + } + + #[ink(message)] + fn get_user_reward_per_token_paid(&self, _account: AccountId) -> Balance { + StakingRewardImpl::get_user_reward_per_token_paid(self, _account) + } + + #[ink(message)] + fn get_rewards(&self, _account: AccountId) -> Balance { + StakingRewardImpl::get_rewards(self, _account) + } + + #[ink(message)] + fn balance_of(&self, _account: AccountId) -> Balance { + StakingRewardImpl::balance_of(self, _account) + } + + #[ink(message)] + fn last_time_reward_applicable(&self) -> Balance { + StakingRewardImpl::last_time_reward_applicable(self) + } + + #[ink(message)] + fn reward_per_token(&self) -> Balance { + StakingRewardImpl::reward_per_token(self) + } + + #[ink(message)] + fn earned(&self, _account: AccountId) -> Balance { + StakingRewardImpl::earned(self, _account) + } + + #[ink(message)] + fn get_reward_for_duration(&self) -> Balance { + StakingRewardImpl::get_reward_for_duration(self) + } + + + + + + #[ink(message)] + fn stake(&mut self, _amount: Balance) -> Result<(), StakingRewardsErrors> { + StakingRewardImpl::stake(self, _amount) + } + + #[ink(message)] + fn withdraw(&mut self, _amount: Balance) -> Result<(), StakingRewardsErrors> { + StakingRewardImpl::withdraw(self, _amount) + } + + #[ink(message)] + fn get_reward(&mut self) -> Result<(), StakingRewardsErrors> { + StakingRewardImpl::get_reward(self) + } + + #[ink(message)] + fn exit(&mut self) -> Result<(), StakingRewardsErrors> { + StakingRewardImpl::exit(self) + } + + #[ink(message)] + fn notify_reward_amount(&mut self, _reward: Balance) -> Result<(), StakingRewardsErrors> { + StakingRewardImpl::notify_reward_amount(self, _reward) + } + + #[ink(message)] + fn recover_erc20(&mut self, _token: AccountId, _amount: Balance) -> Result<(), StakingRewardsErrors> { + StakingRewardImpl::recover_erc20(self, _token, _amount) + } + + #[ink(message)] + fn set_reward_duration(&mut self, _duration: Balance) -> Result<(), StakingRewardsErrors> { + StakingRewardImpl::set_reward_duration(self, _duration) + } + } + + + + + + + + + + + + + impl StakingReward { + + #[ink(constructor)] + pub fn new(_owner: AccountId, _reward_token: AccountId, _staked_token: AccountId) -> Self { + let mut instance = Self::default(); + + + instance.staking_state.admin = _owner; + instance.staking_state.staked_token = _staked_token; + instance.staking_state.reward_token = _reward_token; + + + instance + } + + } + +} \ No newline at end of file diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/providers/.DS_Store b/ink-awesome-defi/synthetix-staking-reward/contracts/providers/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..482eb7c2c7c1338917370942395bb23918461cfa GIT binary patch literal 6148 zcmeHKL5tHs6n@jK-IOBqps*KVz-w8fRzbYPx*oh5(Su4&HbH~gOleY!ltRw>W4!uH z{5$%+nOSM9-WHMNz3}FndGo%RG_Vzou>AGI{wf>ea%A#(<@Vn|A z^sfvKgTr7HyoukNb=)M)s-7jwSKNATOqrh7lk`QAujk`yk4@DiMU^itp~!Niynb0! znOV=ws>*81ja^4D42JXZ(PlFZrxSfIoNgz2^WaW6(bK#4x7%TG{pPKQ&*mS>v&ww7 zcTEcKr?smd&*2LyooD(OFRRj2?+|BBpE63Qp=9U1W?jC*cXb&dFQ)~S(C`x&DQY>@ zU6#7>8*5-S&*+$zd%1jPyEC9ECJKlGqQC_y;J=B%=z_+RVMGB@;PNQI-vJw_f|hv for StakingRewardsErrors { + fn from(error: OwnableError) -> Self { + StakingRewardsErrors::OwnableError(error) + } +} + +impl From for StakingRewardsErrors { + fn from(error: ReentrancyGuardError) -> Self { + StakingRewardsErrors::ReentrancyGuardError(error) + } +} \ No newline at end of file diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/providers/common/mod.rs b/ink-awesome-defi/synthetix-staking-reward/contracts/providers/common/mod.rs new file mode 100644 index 00000000..51412cb8 --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/providers/common/mod.rs @@ -0,0 +1,2 @@ +pub mod database; +pub mod errors; \ No newline at end of file diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/providers/data/mod.rs b/ink-awesome-defi/synthetix-staking-reward/contracts/providers/data/mod.rs new file mode 100644 index 00000000..3b1d20f9 --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/providers/data/mod.rs @@ -0,0 +1 @@ +pub mod staking_reward; \ No newline at end of file diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/providers/data/staking_reward.rs b/ink-awesome-defi/synthetix-staking-reward/contracts/providers/data/staking_reward.rs new file mode 100644 index 00000000..b8e5bd3c --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/providers/data/staking_reward.rs @@ -0,0 +1,46 @@ +use ink::storage::Mapping; +use openbrush::traits::AccountId; +use ink::prelude::vec::Vec; +use openbrush::traits::Balance; + + + +#[derive(Debug)] +#[openbrush::storage_item(STAKING_REWARD_STORAGE_LOCATION)] +pub struct StakingStorage { + pub admin: AccountId, + pub staked_token: AccountId, + pub reward_token: AccountId, + pub period_to_finish: Balance, + pub reward_rate: Balance, + pub reward_duration: Balance, + pub last_updated_time: Balance, + pub reward_per_token_stored: Balance, + pub user_reward_per_token: Mapping, + pub rewards: Mapping, + pub total_supply: Balance, + pub balances: Mapping, +} + + + +impl Default for StakingStorage { + fn default() -> Self { + Self { + admin: AccountId::from([0x0; 32]), + staked_token: AccountId::from([0x0; 32]), + reward_token: AccountId::from([0x0; 32]), + period_to_finish: Default::default(), + reward_rate: Default::default(), + reward_duration: Default::default(), + last_updated_time: Default::default(), + reward_per_token_stored: Default::default(), + user_reward_per_token: Default::default(), + rewards: Default::default(), + total_supply: Default::default(), + balances: Default::default(), + } + } +} + + diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/providers/deployables/mod.rs b/ink-awesome-defi/synthetix-staking-reward/contracts/providers/deployables/mod.rs new file mode 100644 index 00000000..3b1d20f9 --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/providers/deployables/mod.rs @@ -0,0 +1 @@ +pub mod staking_reward; \ No newline at end of file diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/providers/deployables/staking_reward.rs b/ink-awesome-defi/synthetix-staking-reward/contracts/providers/deployables/staking_reward.rs new file mode 100644 index 00000000..02e7ec1d --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/providers/deployables/staking_reward.rs @@ -0,0 +1,277 @@ +use core::cell::RefCell; +use openbrush::{traits::{Storage, AccountId}, contracts::ownable::OwnableError}; +use crate::providers::{data::staking_reward::StakingStorage, common::errors::StakingRewardsErrors}; +use openbrush::traits::Balance; +use openbrush::{contracts::{psp22::{psp22, extensions::metadata::PSP22MetadataImpl}, traits::psp22::PSP22Ref}}; +use ink::prelude::vec::Vec; +use openbrush::modifier_definition; + + + + + +pub trait StakingRewardImpl: + Storage +{ + // ====================================== + // Mutating functions + // ====================================== + fn stake(&mut self, _amount: Balance) -> Result<(), StakingRewardsErrors> { + let state = self.data::(); + let caller = Self::env().caller(); + if _amount <= 0 { + return Err(StakingRewardsErrors::InvalidAmount); + } + + state.total_supply += _amount; + let current_balance = state.balances.get(&caller).unwrap_or(0u128); + state.balances.insert(caller, &(current_balance + _amount)); + + PSP22Ref::transfer_from(&state.staked_token, caller, Self::env().account_id(), _amount, Vec::::new()).map_err(|_| StakingRewardsErrors::TokenTransferFailed)?; + Ok(()) + } + + fn withdraw(&mut self, _amount: Balance) -> Result<(), StakingRewardsErrors> { + let state = self.data::(); + let caller = Self::env().caller(); + if _amount <= 0 { + return Err(StakingRewardsErrors::InvalidAmount); + } + + state.total_supply -= _amount; + let current_balance = state.balances.get(&caller).unwrap_or(0u128); + state.balances.insert(caller, &(current_balance - _amount)); + + PSP22Ref::transfer(&state.staked_token, caller, _amount, Vec::::new()).map_err(|_| StakingRewardsErrors::TokenTransferFailed)?; + Ok(()) + } + + fn get_reward(&mut self) -> Result<(), StakingRewardsErrors> { + let state = self.data::(); + let caller = Self::env().caller(); + + + let reward = state.rewards.get(&caller).unwrap_or(0u128); + + if reward <= 0 { + return Err(StakingRewardsErrors::InvalidAmount); + } + + state.rewards.insert(caller, &0u128); + PSP22Ref::transfer(&state.reward_token, caller, reward, Vec::::new()).map_err(|_| StakingRewardsErrors::TokenTransferFailed)?; + Ok(()) + } + + fn exit(&mut self) -> Result<(), StakingRewardsErrors> { + let state = self.data::(); + let caller = Self::env().caller(); + + let amount = state.balances.get(&caller).unwrap_or(0u128); + self.withdraw(amount)?; + self.get_reward()?; + Ok(()) + } + + + + + + + fn notify_reward_amount(&mut self, _reward: Balance) -> Result<(), StakingRewardsErrors> { + let state = self.data::(); + let caller = Self::env().caller(); + + // remove this whe you plug in the modifer + if caller != state.admin { + return Err(StakingRewardsErrors::NotAdmin); + } + + if _reward <= 0 { + return Err(StakingRewardsErrors::InvalidAmount); + } + + let block_timestamp = Self::env().block_timestamp() as u128; + if block_timestamp >= state.period_to_finish { + state.reward_rate = _reward / state.reward_duration; + } else { + let remaining = state.period_to_finish - block_timestamp; + let leftover = remaining * state.reward_rate; + state.reward_rate = (_reward + leftover) / state.reward_duration; + } + + + let balance = PSP22Ref::balance_of(&state.reward_token, Self::env().account_id()); + + if state.reward_rate > balance / state.reward_duration { + return Err(StakingRewardsErrors::ProviderRewardIsToLarge); + } + state.last_updated_time = block_timestamp; + state.period_to_finish = block_timestamp + state.reward_duration; + + Ok(()) + } + + + fn recover_erc20(&mut self, _token: AccountId, _amount: Balance) -> Result<(), StakingRewardsErrors> { + let state = self.data::(); + let caller = Self::env().caller(); + + // remove this whe you plug in the modifer + if caller != state.admin { + return Err(StakingRewardsErrors::NotAdmin); + } + + if state.reward_token == _token { + return Err(StakingRewardsErrors::CannotWithdrawRewardToken); + } + + if state.staked_token == _token { + return Err(StakingRewardsErrors::CannotWithdrawStakedToken); + } + + if _amount <= 0 { + return Err(StakingRewardsErrors::InvalidAmount); + } + + PSP22Ref::transfer(&state.reward_token, caller, _amount, Vec::::new()).map_err(|_| StakingRewardsErrors::TokenTransferFailed)?; + Ok(()) + } + + fn set_reward_duration(&mut self, _duration: Balance) -> Result<(), StakingRewardsErrors> { + let state = self.data::(); + let caller = Self::env().caller(); + + // remove this whe you plug in the modifer + if caller != state.admin { + return Err(StakingRewardsErrors::NotAdmin); + } + + if _duration <= 0 { + return Err(StakingRewardsErrors::InvalidAmount); + } + + if (Self::env().block_timestamp() as u128) < state.period_to_finish { + return Err(StakingRewardsErrors::StakingStillInProgress); + } + + state.reward_duration = _duration; + Ok(()) + } + + + + + + + + + + // ====================================== + // View functions + // ====================================== + fn get_reward_token(&self) -> AccountId { + self.data::().reward_token + } + + fn get_staked_token(&self) -> AccountId { + self.data::().staked_token + } + + fn get_reward_rate(&self) -> Balance { + self.data::().reward_rate + } + + fn get_period_finish(&self) -> Balance { + self.data::().period_to_finish + } + + fn get_reward_duration(&self) -> Balance { + self.data::().reward_duration + } + + fn get_last_update_time(&self) -> Balance { + self.data::().last_updated_time + } + + fn get_reward_per_token_stored(&self) -> Balance { + self.data::().reward_per_token_stored + } + + fn get_user_reward_per_token_paid(&self, _account: AccountId) -> Balance { + self.data::().user_reward_per_token.get(&_account).unwrap_or(0u128).clone() + } + + fn get_rewards(&self, _account: AccountId) -> Balance { + self.data::().rewards.get(&_account).unwrap_or(0u128).clone() + } + + fn total_supply(&self) -> Balance { + self.data::().total_supply + } + + fn balance_of(&self, _account: AccountId) -> Balance { + self.data::().balances.get(&_account).unwrap_or(0u128).clone() + } + + fn last_time_reward_applicable(&self) -> Balance { + let state = self.data::(); + let block_timestamp = Self::env().block_timestamp() as u128; + block_timestamp.min(state.period_to_finish) + } + + fn reward_per_token(&self) -> Balance { + let state = self.data::(); + if state.total_supply == 0 { + state.reward_per_token_stored + } else { + state.reward_per_token_stored + (self.last_time_reward_applicable() - state.last_updated_time) * state.reward_rate * 10u128.pow(18) / state.total_supply + } + } + + fn earned(&self, _account: AccountId) -> Balance { + let state = self.data::(); + let user_reward_per_token_paid = state.user_reward_per_token.get(&_account).unwrap_or(0u128).clone(); + let reward_per_token = self.reward_per_token(); + let balance_of = self.balance_of(_account); + let earned = balance_of * (reward_per_token - user_reward_per_token_paid) / 10u128.pow(18) + state.rewards.get(&_account).unwrap_or(0u128); + + earned + } + + fn get_reward_for_duration(&self) -> Balance { + let state = self.data::(); + state.reward_rate * state.reward_duration + } + + fn get_caller(&self) -> AccountId { + Self::env().caller() + } +} + + + + + +// ====================================== +// Modifers +// ====================================== +//TODO: move this logic into the trait... modifer_definition! macro does not accept abr data +// #[modifier_definition] +// pub fn update_reward(instance: &mut T, body: F, is_address_zero: bool) -> Result +// where T: Storage + StakingRewardImpl, F: FnOnce(&mut T) -> Result, E: From +// { + +// let instance_ = RefCell::new(instance); +// let mut instance_1 = instance_.borrow_mut(); +// let state = instance_1.data::(); +// let reward_per_token = StakingRewardImpl::reward_per_token(instance); +// let last_updated_time = StakingRewardImpl::last_time_reward_applicable(instance); + +// if is_address_zero { +// let current_earned = StakingRewardImpl::earned(instance, instance.get_caller()); +// state.rewards.insert(instance.get_caller(), ¤t_earned); +// state.user_reward_per_token.insert(instance.get_caller(), &reward_per_token); +// } + +// body(instance) +// } diff --git a/ink-awesome-defi/synthetix-staking-reward/contracts/providers/mod.rs b/ink-awesome-defi/synthetix-staking-reward/contracts/providers/mod.rs new file mode 100644 index 00000000..770cc004 --- /dev/null +++ b/ink-awesome-defi/synthetix-staking-reward/contracts/providers/mod.rs @@ -0,0 +1,3 @@ +pub mod data; +pub mod deployables; +pub mod common; \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/.DS_Store b/ink-awesome-defi/uniswap-v2-core-ink/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..61bfbbbfbc20dd4af27ec8bf656284f99c743286 GIT binary patch literal 6148 zcmeHK&rjPh6n=(|rof~gK;kmV(ykTDST||fB@}kpb(yxqHgyTDSVV|XlF~y}DQEa& zxbm0mf7xmKo^23KK)WF{{G{ja`NwD1pKCiNA~BeZUJ`YQ$b&PsR*~FdT+iOHC0o)4 z3f+gIZAwYe0Ub43y8@?xQ{bT~zP9mJ`MQO}3NE`0lsHbiw! z3Fa}SHO@ti)4{o*D5DZ%MTko(78&B%zZvngII+L$GCoO@qV)Y=VrjYcWTox3y*2N9 z_)|^8GAbv1fYGHNqhGyK`&6Qb!u4XmIRMzzUU2BW1vq!6d{eOCEk5&OU zai@S&;4TIDe2{R)z+z=kA00^a69Cvku{Ol~xxgH0F|b$}L=8+BD$r1cePRehN4d1^ z0*jSFLnmP$AHt3->"] +edition = "2021" + +[dependencies] +ink = { version = "4.2.1", default-features = false } + +openbrush = { git = "https://github.com/727-Ventures/openbrush-contracts", version = "4.0.0-beta.1", default-features = false, features = ["psp22","ownable","access_control", "psp34", "reentrancy_guard", "pausable"] } +psp22_lp = { path = "contracts/modules/psp22_lp", default-features = false } +pair = { path = "contracts/modules/pair", default-features = false } +factory = { path = "contracts/modules/factory", default-features = false } +global = {path = "contracts", default-features = false} +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } + +[dev-dependencies] +ink_e2e = "4.2.0" + +[lib] +path = "contracts.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", + + "openbrush/std", +] +ink-as-dependency = [] +e2e-tests = [] diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts.rs new file mode 100644 index 00000000..58233ec9 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts.rs @@ -0,0 +1,3 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +pub use global; \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/.DS_Store b/ink-awesome-defi/uniswap-v2-core-ink/contracts/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..cb6234f191c0f08269e8f5f88ae573d7f1a98799 GIT binary patch literal 6148 zcmeHKO>fgc5S>i}v5Am!0I3%wOI)L3ARwV$Oj-`TVnh!G1-p)l#nv0yPIHJN`3ygX zE5C&Q!l}I3-B#2t91)^B(d^rgd0y=sXV*(aV!F&86OD+-gERJg6xSG!vv;g#dj>$E zpP^`nYEpDcvJ>q({zU~icXw!y5-RBgnY+y2fmFw-R4K;!<#-9-IoF07(U6W2T_D>f zP~ta7t!lBpwpc#qkcdw)pTt}phIr6o4Dc=~%4n%)Xgyzi`Ezu-sup$)-_nK5t2zw7 zi{4iM*6o2e@P^*|_@i3Iby6>@X;L0>>y1(}y{ISY+kC#7jqdHKqE7N+UTQ*~%@OkM zFfTH-nyO`yRhk={0nhjR*=T#co`jQe@GP8c#=-i6$EvABg%jcW63u3OEIBxB_<1 z@rE~C2e*8ufK#BW0Phb0oH4T47}Q$_3Vj6t_R*~kb^csrPGB*z*cikJOc*NAP=&o> z2t!AIVB;c-jX^^vVJ{!T&MfQ=Md;b_{6L43hzz>YDc}^is=$_Mj`;k4_51t(Rg!Bt z1)Ku^l>(x_AMa1GBzv}Y7RP680RI4I"] +edition = "2021" + +[dependencies] +ink = { version = "4.2.0", default-features = false } + +openbrush = { git = "https://github.com/727-Ventures/openbrush-contracts", version = "4.0.0-beta.1", default-features = false, features = ["psp22","ownable","access_control", "psp34", "reentrancy_guard", "pausable"]} + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } +sp-arithmetic = { version = "15", default-features = false } + +[dev-dependencies] +ink_e2e = "4.2.0" + +[lib] +path = "global.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", + + "openbrush/std", + "sp-arithmetic/std", +] +ink-as-dependency = [] +e2e-tests = [] + +[profile.dev] +overflow-checks = false + +[profile.release] +overflow-checks = false \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/controllers/factory.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/controllers/factory.rs new file mode 100644 index 00000000..42c6f377 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/controllers/factory.rs @@ -0,0 +1,25 @@ + +use openbrush::traits::AccountId; + +use crate::providers::common::errors::UniswapV2Errors; + + + +#[openbrush::wrapper] +pub type FactoryRef = dyn FactoryController; + +#[openbrush::trait_definition] +pub trait FactoryController { + // this function would set the address that receives the protocol fee + #[ink(message)] + fn set_fee_to(&mut self, _fee_to: AccountId) -> Result<(), UniswapV2Errors>; + + // this function is used the updated the address that can call the set_fee_to function + #[ink(message)] + fn set_fee_to_setter(&mut self, _fee_to_setter: AccountId) -> Result<(), UniswapV2Errors>; + + // this function is used to set the pair code hash (this is handy for upgrades) + #[ink(message)] + fn set_pair_code_hash(&mut self, _pair_code_hash: [u8; 32]) -> Result<(), UniswapV2Errors>; + +} \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/controllers/mod.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/controllers/mod.rs new file mode 100644 index 00000000..67469793 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/controllers/mod.rs @@ -0,0 +1,2 @@ +pub mod pair; +pub mod factory; \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/controllers/pair.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/controllers/pair.rs new file mode 100644 index 00000000..f932a004 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/controllers/pair.rs @@ -0,0 +1,51 @@ +use ink::primitives::AccountId; +use openbrush::traits::Balance; + +use crate::providers::common::errors::UniswapV2Errors; +use openbrush::contracts::traits::psp22::*; + + +#[openbrush::wrapper] +pub type PairRef = dyn PairController + PSP22; + +#[openbrush::trait_definition] +pub trait PairController { + + #[ink(message)] + fn initialize(&mut self, _token0: AccountId, _token1: AccountId); + + #[ink(message)] + fn mint(&mut self, _to: AccountId) -> Result<(), UniswapV2Errors>; + + #[ink(message)] + fn burn(&mut self, _to: AccountId) -> Result<(), UniswapV2Errors>; + + #[ink(message)] + fn swap(&mut self, _amount0: Balance, _amount1: Balance, _to: AccountId) -> Result<(), UniswapV2Errors>; + + #[ink(message)] + fn skim(&mut self, _to: AccountId) -> Result<(), UniswapV2Errors>; + + #[ink(message)] + fn sync(&mut self) -> Result<(), UniswapV2Errors>; + + + + #[ink(message)] + fn token_0(&self) -> AccountId; + + #[ink(message)] + fn token_1(&self) -> AccountId; + + #[ink(message)] + fn factory(&self) -> AccountId; + + #[ink(message)] + fn price0_cumulative_last(&self) -> u128; + + #[ink(message)] + fn price1_cumulative_last(&self) -> u128; + + #[ink(message)] + fn get_reserves(&self) -> (u128, u128, u128); +} \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/global.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/global.rs new file mode 100644 index 00000000..26a14f59 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/global.rs @@ -0,0 +1,4 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +pub mod controllers; +pub mod providers; \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/.DS_Store b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..4de4b0728275c0a7b278d1efe0a85c3064c8e2ac GIT binary patch literal 6148 zcmeH~!H&}~5QfLQfx4`adH`uJNS3%(5SD_3xP-DC_DT>O0F`80AR@$7l2W0nQqJ%& zTzQgxo!x(IZ?$dU3RUH)#=qm4N#jq79TSll&c+XjdPF4QticU5e=v@-w`|XibfLoB zLsLoLPjY>l=B;c$;0bsF+eU!j-41=EgifiZEAOvP5#eRw8T{V4G4xv5>Aaezxyk;W zPV=m)!|+V(?FZMccVtH%$oKJQJ&)_8o>jx7e9Kp_w9eDZev-b}(NO|`rE5>?0)U#q-ncCO}WLI`ay~D*~5Dxn4Q8-xk)#Axf*jIyxkC)4?ynXln z)0d+!`PV}KFwac_Ym~8@PA}yrIvWhW#buG};u9iV70?ufGAixbwqo-Ov8!xWc{@U7 zHJ=S05&f zk<-SiSvt^|BLFnOurc)cqk(Ib)5vLK6%m-QrBGWc+z~_Aa*QjN7ddUL+Hw-^@FCnk z3wJ^h=HGFDWztDRR(h{?)?mFJfOof zcYfIaZPV7mymPG%uS1SpjySqjS}KqV zqynixD)5sE@Xl77pF3us3Zw$5z(D~$9}1gd71%r4(ZSA20OE|pX7u&Bteg^91@?}N z(8Q@kr%IF<;&hIe$g2W-N2f!g_>frnyLb^>o%0two0{hJ>d@#99s&HJ=g5TxJzmsjUKQ9o U>MS~LbYeaPOpxqSfnQMI3;XOfh5!Hn literal 0 HcmV?d00001 diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/factory/.gitignore b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/factory/.gitignore new file mode 100755 index 00000000..8de8f877 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/factory/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/factory/Cargo.toml b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/factory/Cargo.toml new file mode 100755 index 00000000..38e13334 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/factory/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "factory" +version = "0.1.0" +authors = ["developeruche "] +edition = "2021" + +[dependencies] +ink = { version = "4.2.0", default-features = false } + +openbrush = { git = "https://github.com/727-Ventures/openbrush-contracts", version = "4.0.0-beta.1", default-features = false , features = ["psp22","ownable","access_control", "psp34", "reentrancy_guard", "pausable"]} +global = {path = "./../../", default-features = false} +pair ={ path = "../pair" , default-features = false, features = ["ink-as-dependency"]} + + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } + +[dev-dependencies] +ink_e2e = "4.2.0" + +[lib] +path = "factory.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", + + "openbrush/std", + "global/std" +] +ink-as-dependency = [] +e2e-tests = [] diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/factory/factory.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/factory/factory.rs new file mode 100755 index 00000000..e2751774 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/factory/factory.rs @@ -0,0 +1,97 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + + + +#[ink::contract] +mod factory { + use ink::prelude::vec::Vec; + use global::providers::common::errors::UniswapV2Errors; + use global::providers::data::factory::FactoryStorage; + // use global::controllers::factory::factorycontroller_external; + // use global::controllers::factory::FactoryController; + use global::controllers::factory::factorycontroller_external::FactoryController; + use global::providers::deployables::factory::FactoryImpl; + use openbrush::traits::Storage; + use pair::pair::PairRef; + use ink::ToAccountId; + + + + #[ink(storage)] + #[derive(Default, Storage)] + pub struct Factory { + #[storage_field] + pub factory_state: FactoryStorage, + + } + + impl FactoryImpl for Factory {} + + + impl FactoryController for Factory { + #[ink(message)] + fn set_fee_to(&mut self, _fee_to: AccountId) -> Result<(), UniswapV2Errors> { + FactoryImpl::set_fee_to(self, _fee_to) + } + + #[ink(message)] + fn set_fee_to_setter(&mut self, _fee_to_setter: AccountId) -> Result<(), UniswapV2Errors> { + FactoryImpl::set_fee_to_setter(self, _fee_to_setter) + } + + #[ink(message)] + fn set_pair_code_hash(&mut self, _pair_code_hash: [u8; 32]) -> Result<(), UniswapV2Errors> { + FactoryImpl::set_pair_code_hash(self, _pair_code_hash) + } + } + + impl Factory { + + #[ink(constructor)] + pub fn new(pair_code_hash: [u8; 32]) -> Self { + let mut instance = Self::default(); + + instance.factory_state.fee_to_setter = Some(Self::env().caller()); + instance.factory_state.pair_code_hash = pair_code_hash; + + + instance + } + + + + + #[ink(message)] + pub fn create_pair(&mut self, token_a: AccountId, token_b: AccountId, salt_bytes: Vec) -> Result { + let pair = self.factory_state.get_pair.get(&(token_a, token_b)); + if pair.is_some() { + return Err(UniswapV2Errors::PairAlreadyExists); + } + + let pair = self.factory_state.get_pair.get(&(token_b, token_a)); + if pair.is_some() { + return Err(UniswapV2Errors::PairAlreadyExists); + } + + let hash = self.factory_state.pair_code_hash; + + let pair = PairRef::new(token_a, token_b) + .endowment(0) + .code_hash(hash.into()) + .salt_bytes(&salt_bytes) + .instantiate(); + + let pair_addr = pair.to_account_id(); + + self.factory_state.get_pair.insert(&(token_a, token_b), &pair_addr); + self.factory_state.get_pair.insert(&(token_b, token_a), &pair_addr); + + self.factory_state.all_pairs.push(pair_addr); + + Ok(pair_addr) + } + + + } + +} \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/pair/.DS_Store b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/pair/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..2926f511368a582ed7be471f60b205cb7ba61262 GIT binary patch literal 6148 zcmeHK!Ab)`3{A9P(MykBg!zI6|6r{3;MpJ0RuFMzrPcfXk)NpVC9$yU9z{eFNM4#r zW@aCBW+EcGe7ipvS%}CSN>n-%!tmtKK_njn)#m7=kybj{$kW6`e=)?pAIqiO$yOe) z^Zov>+itUNyEVp1&IPpjFo8F&c}3;3w4<8$QO%LOV4X*-)IfK`Y&{!gbCr~2AQ?yo zl7VF4=NZ7AO_`rKrcDNtfn;FM0MCa4CDy>+(T)xnYXN{WgiYY{xy+gpSOa@Uj6l>& zfnKW7VyKrRULvms_KsdI8qJ5s%3sZk+Ul6USh{F+Oq&cO149Pb`$87H|F7_unQZbc zB~3Dr4E$FHbhf%#E%9}6w|@Ih-n9jK3#BlxrvrgMcm&`F&yiCb^zlL;c{Q+i"] +edition = "2021" + +[dependencies] +ink = { version = "4.2.0", default-features = false } + +openbrush = { git = "https://github.com/727-Ventures/openbrush-contracts", version = "4.0.0-beta.1", default-features = false , features = ["psp22","ownable","access_control", "psp34", "reentrancy_guard", "pausable"]} +global = {path = "./../../", default-features = false} + + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } + +[dev-dependencies] +ink_e2e = "4.2.0" + +[lib] +path = "pair.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", + + "openbrush/std", + "global/std" +] +ink-as-dependency = [] +e2e-tests = [] + + +[profile.dev] +overflow-checks = false + +[profile.release] +overflow-checks = false \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/pair/pair.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/pair/pair.rs new file mode 100755 index 00000000..a65c1128 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/pair/pair.rs @@ -0,0 +1,200 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + + + +#[openbrush::implementation(PSP22, PSP22Permit, Nonces, Ownable, PSP22Metadata)] +#[openbrush::contract] +pub mod pair { + + use global::providers::common::errors::UniswapV2Errors; + use global::providers::data::pair::set_factory; + use global::providers::{data::pair::PairStorage, deployables::pair::PairImpl}; + use global::controllers::pair::PairController; + use openbrush::traits::{Hash as HashType, String}; + use openbrush::{traits::Storage, contracts::reentrancy_guard}; + use global::controllers::pair::paircontroller_external; + use openbrush::modifiers; + use crate::pair::reentrancy_guard::non_reentrant; + + + // ========================================= + // Storage + // ========================================= + #[ink(storage)] + #[derive(Default, Storage)] + pub struct Pair { + #[storage_field] + psp22: psp22::Data, + #[storage_field] + metadata: metadata::Data, + #[storage_field] + ownable: ownable::Data, + #[storage_field] + nonces: nonces::Data, + #[storage_field] + psp22_permit: psp22::extensions::permit::Data, + #[storage_field] + pub guard: reentrancy_guard::Data, + #[storage_field] + pub pool_state: PairStorage, + } + + + // ========================================= + // Overriding PSP22 Functions + // ========================================= + + + + + // ========================================= + // Events + // ========================================= + #[ink(event)] + pub struct Mint { + #[ink(topic)] + pub sender: AccountId, + pub amount1: Balance, + pub amount2: Balance, + } + + #[ink(event)] + pub struct Burn { + #[ink(topic)] + pub sender: AccountId, + pub amount1: Balance, + pub amount2: Balance, + #[ink(topic)] + pub to: AccountId, + } + + #[ink(event)] + pub struct Swap { + #[ink(topic)] + pub sender: AccountId, + pub amount0_in: Balance, + pub amount1_in: Balance, + pub amount0_out: Balance, + pub amount1_out: Balance, + #[ink(topic)] + pub to: AccountId, + } + + #[ink(event)] + pub struct Sync { + pub reserve0: Balance, + pub reserve1: Balance, + } + + + + + impl PairImpl for Pair {} + + + + + + impl PairController for Pair { + // ========================================= + // View Functions + // ========================================= + #[ink(message)] + fn token_0(&self) -> AccountId { + PairImpl::token_0(self) + } + + #[ink(message)] + fn token_1(&self) -> AccountId { + PairImpl::token_1(self) + } + + #[ink(message)] + fn factory(&self) -> AccountId { + PairImpl::factory(self) + } + + #[ink(message)] + fn price0_cumulative_last(&self) -> u128 { + PairImpl::price0_cumulative_last(self) + } + + #[ink(message)] + fn price1_cumulative_last(&self) -> u128 { + PairImpl::price1_cumulative_last(self) + } + + #[ink(message)] + fn get_reserves(&self) -> (u128, u128, u128) { + PairImpl::get_reserves(self) + } + + + + + // ========================================= + // Write Functions + // ========================================= + #[ink(message)] + fn initialize(&mut self, _token0: AccountId, _token1: AccountId) { + PairImpl::initialize(self, _token0, _token1); + } + + #[ink(message)] + #[modifiers(non_reentrant)] + fn mint(&mut self, _to: AccountId) -> Result<(), UniswapV2Errors> { + PairImpl::mint(self, _to) + } + + #[ink(message)] + #[modifiers(non_reentrant)] + fn burn(&mut self, _to: AccountId) -> Result<(), UniswapV2Errors> { + PairImpl::burn(self, _to) + } + + #[ink(message)] + #[modifiers(non_reentrant)] + fn swap(&mut self, _amount0: Balance, _amount1: Balance, _to: AccountId) -> Result<(), UniswapV2Errors> { + PairImpl::swap(self, _amount0, _amount1, _to) + } + + #[ink(message)] + #[modifiers(non_reentrant)] + fn skim(&mut self, _to: AccountId) -> Result<(), UniswapV2Errors> { + PairImpl::skim(self, _to) + } + + #[ink(message)] + #[modifiers(non_reentrant)] + fn sync(&mut self) -> Result<(), UniswapV2Errors> { + PairImpl::sync(self) + } + } + + + impl Pair { + #[ink(constructor)] + pub fn new(token_a: AccountId, token_b: AccountId) -> Self { + let mut instance = Self::default(); + let caller = instance.env().caller(); + + instance.metadata.name.set(&Some(String::from("Uniswap V2"))); + instance.metadata.symbol.set(&Some(String::from("UNI-V2"))); + instance.metadata.decimals.set(&18); + + ownable::Internal::_init_with_owner(&mut instance, caller); + + set_factory(&mut instance, Self::env().account_id()); + + PairImpl::initialize(&mut instance, token_a, token_b); + instance + } + + + #[ink(message)] + pub fn get_code_hash(&mut self) -> HashType { + self.env().own_code_hash().unwrap() + } + } + +} \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/.DS_Store b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ee9c024ff056a4d8e159a0be998f86ddeea37bd2 GIT binary patch literal 6148 zcmeHKyG{c^3>=db5ouD=Ang}Kf-hJlp`hjifPh4E=%NJr>+(7IL>NDaI1XA0up@hR zy`J0L6z5$4vUq*G0A>ItbVckn3{BV72X+z}MX_hJnBxU4p3w}dzfUOl6ieJ=izhOV z{OhKDSU2sO>-y&o^!b|^N5B*t?C6*L-Ey}LnOp4oEII$eGHQlYAQeajQh`+9Un{_# ztu~oDW=sWAfmGnAfPNneU9kpsj`rzb(Br$Vj}_H8wz~we#JmP}j$EOMQ;ANMxMGOY znJ-aS13O2jLu_Y0Cw7*&p@{9ye6ey!b>Q2GywQny5KvvxQi0!4 F;2nr1D5C%X literal 0 HcmV?d00001 diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/.gitignore b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/.gitignore new file mode 100755 index 00000000..8de8f877 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/Cargo.toml b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/Cargo.toml new file mode 100755 index 00000000..672d68fb --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "psp22_lp" +version = "0.1.0" +authors = ["developeruche "] +edition = "2021" + +[dependencies] +ink = { version = "4.2.0", default-features = false } +openbrush = { git = "https://github.com/727-Ventures/openbrush-contracts", version = "4.0.0-beta.1", default-features = false, features = ["psp22","ownable","access_control", "psp34", "reentrancy_guard", "pausable"] } +global = {path = "./../../", default-features = false} + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } + +[dev-dependencies] +ink_e2e = "4.2.0" + +[lib] +path = "psp22_lp.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", + + "openbrush/std", +] +ink-as-dependency = [] +e2e-tests = [] diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/psp22_lp.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/psp22_lp.rs new file mode 100755 index 00000000..d44e567c --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/modules/psp22_lp/psp22_lp.rs @@ -0,0 +1,64 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + + + + + +#[openbrush::implementation(PSP22, PSP22Permit, Nonces, PSP22Mintable, Ownable, PSP22Metadata)] +#[openbrush::contract] +pub mod psp22_permit { + use openbrush::{traits::Storage, modifiers}; + + + #[ink(storage)] + #[derive(Default, Storage)] + pub struct PSP22Lp { + #[storage_field] + psp22: psp22::Data, + #[storage_field] + metadata: metadata::Data, + #[storage_field] + ownable: ownable::Data, + #[storage_field] + nonces: nonces::Data, + #[storage_field] + psp22_permit: psp22::extensions::permit::Data, + + } + + + #[default_impl(PSP22Mintable)] + #[modifiers(only_owner)] + fn mint(&mut self) {} + + + + + + + impl PSP22Lp { + #[ink(constructor)] + pub fn new(total_supply: Balance, name: Option, symbol: Option, decimal: u8) -> Self { + let mut instance = Self::default(); + let caller = instance.env().caller(); + + instance.metadata.name.set(&name); + instance.metadata.symbol.set(&symbol); + instance.metadata.decimals.set(&decimal); + + ownable::Internal::_init_with_owner(&mut instance, Self::env().caller()); + psp22::Internal::_mint_to(&mut instance, caller, total_supply).expect("Should mint total_supply"); + + + instance + } + + + + #[ink(message)] + pub fn burn(&mut self, _amount: Balance) -> Result<(), PSP22Error> { + let caller = self.env().caller(); + psp22::Internal::_burn_from(self, caller, _amount) + } + } +} diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/common/database.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/common/database.rs new file mode 100644 index 00000000..8f84ed21 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/common/database.rs @@ -0,0 +1,2 @@ +pub const CONTRACT_1_STATE: u32 = openbrush::storage_unique_key!(contract_1_state); +pub const FACTORY_STORAGE_LOCATION: u32 = openbrush::storage_unique_key!(factory_storage_location); \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/common/errors.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/common/errors.rs new file mode 100644 index 00000000..5eb5fde4 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/common/errors.rs @@ -0,0 +1,48 @@ +use openbrush:: + contracts::traits::{ + ownable::*, + psp22::PSP22Error, + errors::ReentrancyGuardError, + }; + + + + + + +#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum UniswapV2Errors { + PSP22Error(PSP22Error), + OwnableError(OwnableError), + ReentrancyGuardError(ReentrancyGuardError), + InsufficientLiquidityMinted, + InsufficientLiquidityBurned, + InsufficientAmountOut, + InvalidToAddress, + ConstantProductError, + InvalidPairAddress, + PairAlreadyExists +} + + + + +// implementing error conversion utils +impl From for UniswapV2Errors { + fn from(error: PSP22Error) -> Self { + UniswapV2Errors::PSP22Error(error) + } +} + +impl From for UniswapV2Errors { + fn from(error: OwnableError) -> Self { + UniswapV2Errors::OwnableError(error) + } +} + +impl From for UniswapV2Errors { + fn from(error: ReentrancyGuardError) -> Self { + UniswapV2Errors::ReentrancyGuardError(error) + } +} \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/common/mod.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/common/mod.rs new file mode 100644 index 00000000..51412cb8 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/common/mod.rs @@ -0,0 +1,2 @@ +pub mod database; +pub mod errors; \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/data/factory.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/data/factory.rs new file mode 100644 index 00000000..7fb2e226 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/data/factory.rs @@ -0,0 +1,31 @@ +use ink::storage::Mapping; +use openbrush::traits::AccountId; +use ink::prelude::vec::Vec; + + + +#[derive(Debug)] +#[openbrush::storage_item(FACTORY_STORAGE_LOCATION)] +pub struct FactoryStorage { + pub fee_to: Option, + pub fee_to_setter: Option, + pub get_pair: Mapping<(AccountId, AccountId), AccountId>, + pub all_pairs: Vec, + pub pair_code_hash: [u8; 32], +} + + + +impl Default for FactoryStorage { + fn default() -> Self { + Self { + fee_to: Default::default(), + fee_to_setter: Default::default(), + get_pair: Default::default(), + all_pairs: Default::default(), + pair_code_hash: Default::default(), + } + } +} + + diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/data/mod.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/data/mod.rs new file mode 100644 index 00000000..67469793 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/data/mod.rs @@ -0,0 +1,2 @@ +pub mod pair; +pub mod factory; \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/data/pair.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/data/pair.rs new file mode 100644 index 00000000..60bffc16 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/data/pair.rs @@ -0,0 +1,116 @@ +use openbrush::traits::{ AccountId, Balance, Storage }; + + +#[derive(Debug, Clone, Copy)] +#[openbrush::storage_item(PAIR_STORAGE_LOCATION)] +pub struct PairStorage { + pub minimum_liquidity: Balance, + pub factory: AccountId, + pub token_0: AccountId, + pub token_1: AccountId, + pub reserve_0: Balance, + pub reserve_1: Balance, + pub block_timestamp_last: Balance, + pub price0_cumulative_last: Balance, + pub price1_cumulative_last: Balance, + pub k_last: Balance, +} + + +impl Default for PairStorage { + fn default() -> Self { + Self { + minimum_liquidity: Balance::from(1000u32), + factory: AccountId::from([0u8; 32]), + token_0: AccountId::from([0u8; 32]), + token_1: AccountId::from([0u8; 32]), + reserve_0: Balance::default(), + reserve_1: Balance::default(), + block_timestamp_last: Balance::default(), + price0_cumulative_last: Balance::default(), + price1_cumulative_last: Balance::default(), + k_last: Balance::default(), + } + } +} + + + + +// implementing utils functions for accessing storage (this makes life abit easier) +pub fn get_minimum_liquidity(instance: &T) -> Balance where T: Storage { + instance.data::().minimum_liquidity +} + +pub fn get_factory(instance: &T) -> AccountId where T: Storage { + instance.data::().factory +} + +pub fn set_factory(instance: &mut T, factory: AccountId) where T: Storage { + instance.data::().factory = factory; +} + +pub fn get_token_0(instance: &T) -> AccountId where T: Storage { + instance.data::().token_0 +} + +pub fn set_token_0(instance: &mut T, token_0: AccountId) where T: Storage { + instance.data::().token_0 = token_0; +} + +pub fn get_token_1(instance: &T) -> AccountId where T: Storage { + instance.data::().token_1 +} + +pub fn set_token_1(instance: &mut T, token_1: AccountId) where T: Storage { + instance.data::().token_1 = token_1; +} + +pub fn get_reserve_0(instance: &T) -> Balance where T: Storage { + instance.data::().reserve_0 +} + +pub fn set_reserve_0(instance: &mut T, reserve_0: Balance) where T: Storage { + instance.data::().reserve_0 = reserve_0; +} + +pub fn get_reserve_1(instance: &T) -> Balance where T: Storage { + instance.data::().reserve_1 +} + +pub fn set_reserve_1(instance: &mut T, reserve_1: Balance) where T: Storage { + instance.data::().reserve_1 = reserve_1; +} + +pub fn get_block_timestamp_last(instance: &T) -> Balance where T: Storage { + instance.data::().block_timestamp_last +} + +pub fn set_block_timestamp_last(instance: &mut T, block_timestamp_last: Balance) where T: Storage { + instance.data::().block_timestamp_last = block_timestamp_last; +} + +pub fn get_price0_cumulative_last(instance: &T) -> Balance where T: Storage { + instance.data::().price0_cumulative_last +} + +pub fn set_price0_cumulative_last(instance: &mut T, price0_cumulative_last: Balance) where T: Storage { + instance.data::().price0_cumulative_last = price0_cumulative_last; +} + +pub fn get_price1_cumulative_last(instance: &T) -> Balance where T: Storage { + instance.data::().price1_cumulative_last +} + +pub fn set_price1_cumulative_last(instance: &mut T, price1_cumulative_last: Balance) where T: Storage { + instance.data::().price1_cumulative_last = price1_cumulative_last; +} + +pub fn get_k_last(instance: &T) -> Balance where T: Storage { + instance.data::().k_last +} + +pub fn set_k_last(instance: &mut T, k_last: Balance) where T: Storage { + instance.data::().k_last = k_last; +} + diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/deployables/factory.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/deployables/factory.rs new file mode 100644 index 00000000..5c01c58c --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/deployables/factory.rs @@ -0,0 +1,37 @@ +use openbrush::{traits::{Storage, AccountId}, contracts::ownable::OwnableError}; +use crate::providers::{data::factory::FactoryStorage, common::errors::UniswapV2Errors}; + + +pub trait FactoryImpl: + Storage +{ + fn set_fee_to(&mut self, _fee_to: AccountId) -> Result<(), UniswapV2Errors> { + let state = self.data::(); + + if state.fee_to_setter.unwrap() != Self::env().caller() { + return Err(UniswapV2Errors::OwnableError(OwnableError::CallerIsNotOwner)) + } + self.data::().fee_to_setter = Some(_fee_to); + Ok(()) + } + + fn set_fee_to_setter(&mut self, _fee_to_setter: AccountId) -> Result<(), UniswapV2Errors> { + let state = self.data::(); + + if state.fee_to_setter.unwrap() != Self::env().caller() { + return Err(UniswapV2Errors::OwnableError(OwnableError::CallerIsNotOwner)) + } + self.data::().fee_to_setter = Some(_fee_to_setter); + Ok(()) + } + + fn set_pair_code_hash(&mut self, _pair_code_hash: [u8; 32]) -> Result<(), UniswapV2Errors> { + let state = self.data::(); + + if state.fee_to_setter.unwrap() != Self::env().caller() { + return Err(UniswapV2Errors::OwnableError(OwnableError::CallerIsNotOwner)) + } + self.data::().pair_code_hash = _pair_code_hash; + Ok(()) + } +} \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/deployables/mod.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/deployables/mod.rs new file mode 100644 index 00000000..67469793 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/deployables/mod.rs @@ -0,0 +1,2 @@ +pub mod pair; +pub mod factory; \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/deployables/pair.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/deployables/pair.rs new file mode 100644 index 00000000..1add0e68 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/deployables/pair.rs @@ -0,0 +1,284 @@ + +use ink::prelude::vec::Vec; +use ink::primitives::AccountId; +use openbrush::{traits::{Storage, Balance}, contracts::{psp22::{psp22, extensions::metadata::PSP22MetadataImpl}, traits::psp22::PSP22Ref}}; +use crate::providers::{data::pair::{PairStorage, get_token_0, get_token_1, get_factory, get_price0_cumulative_last, get_price1_cumulative_last}, common::errors::UniswapV2Errors}; +use scale::CompactAs; +use sp_arithmetic::FixedU128; + + +pub trait PairImpl: + Storage + + Storage + + PSP22MetadataImpl + + psp22::Internal + +{ + // public varible get functions + fn token_0(&self) -> AccountId { + get_token_0(self) + } + + fn token_1(&self) -> AccountId { + get_token_1(self) + } + + fn factory(&self) -> AccountId { + get_factory(self) + } + + fn price0_cumulative_last(&self) -> u128 { + get_price0_cumulative_last(self) + } + + fn price1_cumulative_last(&self) -> u128 { + get_price1_cumulative_last(self) + } + + fn get_reserves(&self) -> (u128, u128, u128) { + let state = self.data::(); + (state.reserve_0, state.reserve_1, state.block_timestamp_last) + } + + + + + + + + + fn initialize(&mut self, _token0: AccountId, _token1: AccountId) { + let state = self.data::(); + state.token_0 = _token0; + state.token_1 = _token1; + } + + fn mint(&mut self, _to: AccountId) -> Result<(), UniswapV2Errors> { + let state = *self.data::(); + let this = Self::env().account_id(); + let (reserve_0, reserve_1, minimum_liquidity) = (state.reserve_0, state.reserve_1, state.minimum_liquidity); + let balance0 = PSP22Ref::balance_of(&state.token_0, this); + let balance1 = PSP22Ref::balance_of(&state.token_1, this); + let amount0 = balance0 - reserve_0; + let amount1 = balance1 - reserve_1; + let liqudity: Balance; + + let fee_on = self.internal_mint_fee(); + + + if self._total_supply() == 0 { + // this is the first liquidity is been added to the pool + liqudity = internal_sqrt(amount0 * amount1) - minimum_liquidity; + self._mint_to(AccountId::from([0u8; 32]), minimum_liquidity)?; + } else { + liqudity = (amount0 * self._total_supply() / reserve_0).min(amount1 * self._total_supply() / reserve_1); + } + + if liqudity == 0 { + return Err(UniswapV2Errors::InsufficientLiquidityMinted); + } + + self._mint_to(_to, liqudity)?; + + self.internal_update(balance0, balance1)?; + + if fee_on.unwrap_or(false) { + self.data::().k_last = (self.data::().reserve_0 as u128) * (self.data::().reserve_1 as u128); + } + + Ok(()) + } + + + fn burn(&mut self, _to: AccountId) -> Result<(), UniswapV2Errors> { + let state = *self.data::(); + let this = Self::env().account_id(); + let (token_0, token_1) = (state.token_0, state.token_1); + let mut balance0 = PSP22Ref::balance_of(&token_0, this); + let mut balance1 = PSP22Ref::balance_of(&token_1, this); + let liquidity = self._balance_of(&this); + + let fee_on = self.internal_mint_fee(); + let _total_supply = self._total_supply(); + + let amount0 = liquidity * balance0 / _total_supply; + let amount1 = liquidity * balance1 / _total_supply; + + if amount0 == 0 || amount1 == 0 { + return Err(UniswapV2Errors::InsufficientLiquidityBurned); + } + + self._burn_from(this, liquidity)?; + + PSP22Ref::transfer(&this, _to, amount0, Vec::::new())?; + PSP22Ref::transfer(&this, _to, amount1, Vec::::new())?; + + balance0 = PSP22Ref::balance_of(&token_0, this); + balance1 = PSP22Ref::balance_of(&token_1, this); + + if fee_on.unwrap_or(false) { + self.data::().k_last = (self.data::().reserve_0 as u128) * (self.data::().reserve_1 as u128); + } + + self.internal_update(balance0, balance1)?; + + Ok(()) + } + + + + fn swap(&mut self, _amount0: Balance, _amount1: Balance, _to: AccountId) -> Result<(), UniswapV2Errors> { + let state = *self.data::(); + let this = Self::env().account_id(); + + if _amount0 == 0 && _amount1 == 0 { + return Err(UniswapV2Errors::InsufficientAmountOut); + } + + let (reserve_0, reserve_1, token_0, token_1) = (state.reserve_0, state.reserve_1, state.token_0, state.token_1); + + if _to == token_0 || _to == token_1 { + return Err(UniswapV2Errors::InvalidToAddress); + } + + PSP22Ref::transfer(&token_0, _to, _amount0, Vec::::new())?; + PSP22Ref::transfer(&token_1, _to, _amount1, Vec::::new())?; + + let balance0 = PSP22Ref::balance_of(&token_0, this); + let balance1 = PSP22Ref::balance_of(&token_1, this); + + let amount0_in = if balance0 > reserve_0 - _amount0 { + balance0 - (reserve_0 - _amount0) + } else { + 0u128 + }; + + let amount1_in = if balance1 > reserve_1 - _amount1 { + balance1 - (reserve_1 - _amount1) + } else { + 0u128 + }; + + if amount0_in == 0 && amount1_in == 0 { + return Err(UniswapV2Errors::InsufficientAmountOut); + } + + let balance0adjusted = balance0 * 1000 - amount0_in * 3; + let balance1adjusted = balance1 * 1000 - amount1_in * 3; + + if (balance0adjusted * balance1adjusted) < (reserve_0 * reserve_1) * 1000u128.pow(2) { + return Err(UniswapV2Errors::ConstantProductError); + } + + self.internal_update(balance0, balance1)?; + Ok(()) + } + + + fn skim(&mut self, _to: AccountId) -> Result<(), UniswapV2Errors> { + let state = *self.data::(); + let this = Self::env().account_id(); + let (token_0, token_1) = (state.token_0, state.token_1); + let balance0 = PSP22Ref::balance_of(&token_0, this); + let balance1 = PSP22Ref::balance_of(&token_1, this); + let amount0 = balance0 - state.reserve_0; + let amount1 = balance1 - state.reserve_1; + + if amount0 > 0 { + PSP22Ref::transfer(&token_0, _to, amount0, Vec::::new())?; + } + + if amount1 > 0 { + PSP22Ref::transfer(&token_1, _to, amount1, Vec::::new())?; + } + + Ok(()) + } + + + fn sync(&mut self) -> Result<(), UniswapV2Errors> { + let state = *self.data::(); + let (token_0, token_1) = (state.token_0, state.token_1); + let balance0 = PSP22Ref::balance_of(&token_0, Self::env().account_id()); + let balance1 = PSP22Ref::balance_of(&token_1, Self::env().account_id()); + self.internal_update(balance0, balance1)?; + Ok(()) + } + + + + + + // ========================================= + // Internal Functions + // ========================================= + fn internal_transfer(&mut self, _token: AccountId, _to: AccountId, _value: u128) -> bool { + return PSP22Ref::transfer(&_token, _to, _value, Vec::::new()).is_ok(); + } + + fn internal_mint_fee(&mut self) -> Result { + let state = self.data::(); + let fee_to = Some(AccountId::from([1u8; 32])); // PSP22Ref::fee_to(&state.token_0); //TODO: fee_to + + let return_data = fee_to.is_some(); + + if return_data { + if state.k_last != 0 { + let root_k_pre = (state.reserve_0 as u128) * (state.reserve_1 as u128); + let root_k = internal_sqrt(root_k_pre); + let root_k_last = internal_sqrt(state.k_last); + + if root_k > root_k_last { + let numerator = self._total_supply() * (root_k - root_k_last); + let denominator = (root_k * 5) + root_k_last; + let liquidity = numerator / denominator; + if liquidity > 0 { + self._mint_to(fee_to.unwrap(), liquidity)?; + } + } + } + } + Ok(return_data) + } + + + + fn internal_update(&mut self, balance1: Balance, balance2: Balance) -> Result<(), UniswapV2Errors> { + let state = self.data::(); + let (reserve_0, reserve_1, block_timestamp_last) = (state.reserve_0, state.reserve_1, state.block_timestamp_last); + let time_elapsed = Self::env().block_timestamp() as u128 - block_timestamp_last; + + if time_elapsed > 0 && reserve_0 != 0 && reserve_1 != 0 { + state.price0_cumulative_last += (uq112x112decode(uq112x112encode(state.reserve_1), state.reserve_0)) * time_elapsed; + state.price1_cumulative_last += (uq112x112decode(uq112x112encode(state.reserve_0), state.reserve_1)) * time_elapsed; + } + + + state.reserve_0 = balance1; + state.reserve_1 = balance2; + state.block_timestamp_last = Self::env().block_timestamp() as u128; + + + // emit the sync event + Ok(()) + } + + +} + + + +fn internal_sqrt(_y: u128) -> u128 { + let d1 = FixedU128::from_inner(_y); + let d2 = FixedU128::sqrt(d1); + let d3 = *d2.encode_as(); + d3 +} + + +fn uq112x112encode(x: u128) -> u128 { + x * 2u128.pow(112) +} + +fn uq112x112decode(x: u128, y: u128) -> u128 { + x / y +} \ No newline at end of file diff --git a/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/mod.rs b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/mod.rs new file mode 100644 index 00000000..770cc004 --- /dev/null +++ b/ink-awesome-defi/uniswap-v2-core-ink/contracts/providers/mod.rs @@ -0,0 +1,3 @@ +pub mod data; +pub mod deployables; +pub mod common; \ No newline at end of file