-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c8068f7
commit af5e674
Showing
12 changed files
with
499 additions
and
20 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
[workspace] | ||
resolver = "2" | ||
members = [ | ||
"msig_court" | ||
"asset-timelock", | ||
"msig_court", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
[package] | ||
name = "asset-timelock" | ||
version = "0.1.0" | ||
authors = ["[your_name] <[your_email]>"] | ||
edition = "2021" | ||
|
||
[dependencies] | ||
ink = { version = "5.0.0", default-features = false } | ||
liberland-extension = { path = "../../liberland-extension/ink", default-features = false} | ||
|
||
[dev-dependencies] | ||
ink_e2e = { version = "5.0.0" } | ||
|
||
[lib] | ||
path = "lib.rs" | ||
|
||
[features] | ||
default = ["std"] | ||
std = [ | ||
"ink/std", | ||
"liberland-extension/std", | ||
] | ||
ink-as-dependency = [] | ||
e2e-tests = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
#![cfg_attr(not(feature = "std"), no_std, no_main)] | ||
|
||
#[cfg(test)] | ||
mod mock; | ||
|
||
#[ink::contract(env = liberland_extension::LiberlandEnvironment)] | ||
mod asset_timelock { | ||
use ink::storage::Mapping; | ||
use liberland_extension::{AssetId, AssetsBalance}; | ||
|
||
pub type DepositId = u32; | ||
|
||
#[derive(Debug, PartialEq, Eq, Clone)] | ||
#[ink::scale_derive(Encode, Decode, TypeInfo)] | ||
#[cfg_attr(feature = "std", derive(ink::storage::traits::StorageLayout))] | ||
pub struct Deposit { | ||
timestamp: Timestamp, | ||
asset_id: AssetId, | ||
recipient: AccountId, | ||
amount: AssetsBalance, | ||
} | ||
|
||
#[derive(Debug, PartialEq, Eq, Clone)] | ||
#[ink::scale_derive(Encode, Decode, TypeInfo)] | ||
pub enum Error { | ||
/// Funds not unlocked yet | ||
TooEarly, | ||
/// No such deposit found | ||
NotFound, | ||
/// Runtime call failed | ||
CallFailed, | ||
/// Arithmetic overflow | ||
Overflow, | ||
/// Unlock timestamp is before current timestamp | ||
TimestampFromThePast, | ||
} | ||
|
||
impl From<liberland_extension::Error> for Error { | ||
fn from(_: liberland_extension::Error) -> Self { | ||
Self::CallFailed | ||
} | ||
} | ||
|
||
pub type Result<T> = core::result::Result<T, Error>; | ||
|
||
#[ink(storage)] | ||
#[derive(Default)] | ||
pub struct AssetTimelock { | ||
next_deposit_id: DepositId, | ||
deposits: Mapping<DepositId, Deposit>, | ||
} | ||
|
||
#[ink(event)] | ||
pub struct Deposited { | ||
#[ink(topic)] | ||
depositor: AccountId, | ||
#[ink(topic)] | ||
recipient: AccountId, | ||
deposit_id: DepositId, | ||
asset_id: AssetId, | ||
timestamp: Timestamp, | ||
amount: AssetsBalance, | ||
} | ||
|
||
#[ink(event)] | ||
pub struct Withdrawn { | ||
#[ink(topic)] | ||
recipient: AccountId, | ||
deposit_id: DepositId, | ||
asset_id: AssetId, | ||
amount: AssetsBalance, | ||
} | ||
|
||
impl AssetTimelock { | ||
#[ink(constructor)] | ||
pub fn new() -> Self { | ||
Default::default() | ||
} | ||
|
||
#[ink(message)] | ||
pub fn get_deposit(&self, deposit_id: DepositId) -> Option<Deposit> { | ||
self.deposits.get(deposit_id) | ||
} | ||
|
||
#[ink(message)] | ||
pub fn deposit( | ||
&mut self, | ||
asset_id: AssetId, | ||
recipient: AccountId, | ||
amount: AssetsBalance, | ||
timestamp: Timestamp, | ||
) -> Result<DepositId> { | ||
if timestamp < self.env().block_timestamp() { | ||
return Err(Error::TimestampFromThePast); | ||
} | ||
let depositor = self.env().caller(); | ||
let contract_account = self.env().account_id(); | ||
let deposit_id = self.next_deposit_id; | ||
self.next_deposit_id = self.next_deposit_id.checked_add(1).ok_or(Error::Overflow)?; | ||
self.env().extension().asset_transfer_approved( | ||
asset_id, | ||
depositor, | ||
contract_account, | ||
amount, | ||
)?; | ||
self.deposits | ||
.insert(deposit_id, &Deposit { timestamp, asset_id, recipient, amount }); | ||
self.env().emit_event(Deposited { | ||
depositor, | ||
deposit_id, | ||
asset_id, | ||
recipient, | ||
timestamp, | ||
amount, | ||
}); | ||
Ok(deposit_id) | ||
} | ||
|
||
#[ink(message)] | ||
pub fn withdraw(&mut self, deposit_id: DepositId) -> Result<()> { | ||
let Deposit { asset_id, recipient, amount, timestamp } = | ||
self.deposits.take(&deposit_id).ok_or(Error::NotFound)?; | ||
if timestamp > self.env().block_timestamp() { | ||
return Err(Error::TooEarly); | ||
} | ||
self.env().extension().asset_transfer(asset_id, recipient, amount)?; | ||
Ok(()) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
pub struct MockedLiberlandExtensionSuccess; | ||
impl ink::env::test::ChainExtension for MockedLiberlandExtensionSuccess { | ||
fn ext_id(&self) -> u16 { | ||
0 | ||
} | ||
|
||
fn call(&mut self, _func_id: u16, _input: &[u8], _output: &mut Vec<u8>) -> u32 { | ||
0 | ||
} | ||
} | ||
|
||
pub struct MockedLiberlandExtensionFail; | ||
impl ink::env::test::ChainExtension for MockedLiberlandExtensionFail { | ||
fn ext_id(&self) -> u16 { | ||
0 | ||
} | ||
|
||
fn call(&mut self, _func_id: u16, _input: &[u8], _output: &mut Vec<u8>) -> u32 { | ||
1 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.