Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: polish code and add unit tests #2

Merged
merged 2 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
215 changes: 107 additions & 108 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ members = [
"tests"
]

[workspace.lints.clippy]
all = "deny"
nursery = "deny"
pedantic = "deny"

[profile.release]
codegen-units = 1
opt-level = "z"
Expand Down
26 changes: 23 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
# Set of contracts for the Defuse project

### Accounts contract
### Building and running

The purpose of the contract is to store user's owners of different tokens.
Build the smart contracts:

### Intent contract
```shell
cargo make build
```

Run integration tests:

```shell
cargo make test
```

Run clippy linter:

```shell
cargo make clippy
```

### Contracts

- [Account contract](account/README.md)
- [Controller contract](controller/README.md)
- [Intent contract](intent/README.md)
6 changes: 2 additions & 4 deletions account/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ edition.workspace = true
[lib]
crate-type = ["cdylib", "rlib"]

[lints.clippy]
all = "deny"
nursery = "deny"
pedantic = "deny"
[lints]
workspace = true

[dependencies]
near-sdk.workspace = true
Expand Down
1 change: 1 addition & 0 deletions account/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Account contract for the Defuse project
2 changes: 0 additions & 2 deletions account/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// use near_sdk::env;

#[derive(Debug)]
pub enum Error {
AccountExist,
Expand Down
14 changes: 6 additions & 8 deletions account/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use near_sdk::borsh::{BorshDeserialize, BorshSerialize};
use near_sdk::store::LookupSet;
use near_sdk::{
env, ext_contract, near_bindgen, AccountId, BorshStorageKey, PanicOnDefault, PromiseOrValue,
env, ext_contract, near, AccountId, BorshStorageKey, PanicOnDefault, PromiseOrValue,
};

use crate::error::LogError;
Expand All @@ -10,16 +9,15 @@ use crate::types::{Account, AccountDb};
mod error;
mod types;

#[derive(BorshSerialize, BorshDeserialize, BorshStorageKey)]
#[borsh(crate = "near_sdk::borsh")]
#[derive(BorshStorageKey)]
#[near(serializers=[borsh])]
enum Prefix {
Accounts,
Indexers,
}

#[near_bindgen]
#[derive(BorshSerialize, BorshDeserialize, PanicOnDefault)]
#[borsh(crate = "near_sdk::borsh")]
#[near(contract_state)]
#[derive(PanicOnDefault)]
pub struct AccountContract {
owner_id: AccountId,
/// MPC contract id.
Expand All @@ -31,7 +29,7 @@ pub struct AccountContract {
accounts: AccountDb,
}

#[near_bindgen]
#[near]
impl AccountContract {
#[init]
#[must_use]
Expand Down
8 changes: 3 additions & 5 deletions account/src/types/account.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use near_sdk::borsh::{BorshDeserialize, BorshSerialize};
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::near;

#[derive(Default, Clone, BorshSerialize, BorshDeserialize, Deserialize, Serialize)]
#[derive(Default, Clone)]
#[cfg_attr(test, derive(Debug, Eq, PartialEq))]
#[borsh(crate = "near_sdk::borsh")]
#[serde(crate = "near_sdk::serde")]
#[near(serializers=[borsh, json])]
pub struct Account {
is_locked: bool,
}
6 changes: 2 additions & 4 deletions account/src/types/account_db.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use near_sdk::borsh::{BorshDeserialize, BorshSerialize};
use near_sdk::store::LookupMap;
use near_sdk::{AccountId, IntoStorageKey};
use near_sdk::{near, AccountId, IntoStorageKey};
use std::collections::HashMap;

use crate::error::Error;
Expand All @@ -9,8 +8,7 @@ use crate::types::Account;
// Accounts that belong user. Key here is derivation path.
type UserAccounts = HashMap<String, Account>;

#[derive(BorshSerialize, BorshDeserialize)]
#[borsh(crate = "near_sdk::borsh")]
#[near(serializers=[borsh])]
pub struct AccountDb(LookupMap<AccountId, UserAccounts>);

impl AccountDb {
Expand Down
6 changes: 2 additions & 4 deletions controller/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ edition.workspace = true
[lib]
crate-type = ["cdylib", "rlib"]

[lints.clippy]
all = "deny"
nursery = "deny"
pedantic = "deny"
[lints]
workspace = true

[dependencies]
near-sdk.workspace = true
3 changes: 3 additions & 0 deletions controller/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Controller contract for the Defuse project

The main goal of the contract is to manage and update account and intent contracts.
10 changes: 4 additions & 6 deletions controller/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
use near_sdk::borsh::{BorshDeserialize, BorshSerialize};
use near_sdk::{near_bindgen, AccountId, PanicOnDefault};
use near_sdk::{near, AccountId, PanicOnDefault};

#[near_bindgen]
#[derive(BorshSerialize, BorshDeserialize, PanicOnDefault)]
#[borsh(crate = "near_sdk::borsh")]
#[near(contract_state)]
#[derive(PanicOnDefault)]
pub struct ControllerContract {
owner_id: AccountId,
}

#[near_bindgen]
#[near]
impl ControllerContract {
#[init]
#[must_use]
Expand Down
6 changes: 2 additions & 4 deletions intent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ edition.workspace = true
[lib]
crate-type = ["cdylib", "rlib"]

[lints.clippy]
all = "deny"
nursery = "deny"
pedantic = "deny"
[lints]
workspace = true

[dependencies]
near-sdk.workspace = true
1 change: 1 addition & 0 deletions intent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Intent contract for the Defuse project
36 changes: 25 additions & 11 deletions intent/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
use near_sdk::borsh::{BorshDeserialize, BorshSerialize};
use near_sdk::env::panic_str;
use near_sdk::json_types::U128;
use near_sdk::store::{LookupMap, LookupSet};
use near_sdk::{
env, ext_contract, log, near_bindgen, AccountId, BorshStorageKey, NearToken, PanicOnDefault,
Promise, PromiseOrValue,
env, ext_contract, log, near, AccountId, BorshStorageKey, NearToken, PanicOnDefault, Promise,
PromiseOrValue,
};

use crate::{types::intent::Action, types::Intent};

pub mod error;
pub mod types;

#[derive(BorshSerialize, BorshDeserialize, BorshStorageKey)]
#[borsh(crate = "near_sdk::borsh")]
#[derive(BorshStorageKey)]
#[near(serializers=[borsh])]
enum Prefix {
SupportedTokens,
AllowedSolvers,
Intents,
}

#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize, PanicOnDefault)]
#[borsh(crate = "near_sdk::borsh")]
#[near(contract_state)]
#[derive(PanicOnDefault)]
pub struct IntentContract {
owner_id: AccountId,
supported_tokens: LookupSet<String>,
allowed_solvers: LookupSet<AccountId>,
intents: LookupMap<String, Intent>,
}

#[near_bindgen]
#[near]
impl IntentContract {
/// Contract constructor.
#[init]
Expand Down Expand Up @@ -108,7 +106,7 @@ impl IntentContract {
}
}

/// Callback which remove executed intent.
/// Callback which removes an intent after successful execution.
#[private]
pub fn cleanup_intent(&mut self, intent_id: &String) {
self.intents.remove(intent_id);
Expand All @@ -131,7 +129,7 @@ impl IntentContract {
predecessor_id == intent.initiator
|| predecessor_id == self.owner_id
|| predecessor_id == env::current_account_id(),
"Only initiator, self or owner can roll back intent"
"Only initiator, self or owner can roll back the intent"
);

ext_ft::ext(intent.send.token_id.clone())
Expand All @@ -140,11 +138,27 @@ impl IntentContract {
.then(Self::ext(env::current_account_id()).cleanup_intent(id))
}

/// Set a new owner of the contract.
pub fn set_owner(&mut self, owner_id: AccountId) {
self.assert_owner();
self.owner_id = owner_id;
}

/// Return owner of the contract.
pub const fn get_owner(&self) -> &AccountId {
&self.owner_id
}

/// Return pending intent by id.
pub fn get_intent(&self, id: &String) -> Option<&Intent> {
self.intents.get(id)
}

/// Check if the provided solver is allowed.
pub fn is_allowed_solver(&self, solver_id: &AccountId) -> bool {
self.allowed_solvers.contains(solver_id)
}

fn assert_owner(&self) {
assert_eq!(
self.owner_id,
Expand Down
64 changes: 50 additions & 14 deletions intent/src/types/intent/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
use near_sdk::json_types::U128;
use near_sdk::serde::{Deserialize, Serialize};
use near_sdk::{
base64::{engine::general_purpose::STANDARD, Engine},
borsh::{BorshDeserialize, BorshSerialize},
env, AccountId,
borsh::BorshDeserialize,
env, near, AccountId,
};

use crate::error::ContractError;

#[derive(BorshDeserialize, BorshSerialize, Deserialize, Serialize)]
#[borsh(crate = "near_sdk::borsh")]
#[serde(crate = "near_sdk::serde")]
#[near(serializers=[borsh, json])]
pub struct Intent {
pub initiator: AccountId,
pub send: TokenAmount,
Expand All @@ -29,8 +26,7 @@ impl Intent {
}
}

#[derive(BorshDeserialize, BorshSerialize)]
#[borsh(crate = "near_sdk::borsh")]
#[near(serializers=[borsh])]
pub enum Action {
CreateIntent((String, Intent)),
ExecuteIntent(String),
Expand Down Expand Up @@ -63,9 +59,8 @@ impl Action {
}
}

#[derive(Default, Debug, BorshDeserialize, BorshSerialize, Deserialize, Serialize)]
#[borsh(crate = "near_sdk::borsh")]
#[serde(crate = "near_sdk::serde")]
#[derive(Default, Debug)]
#[near(serializers=[borsh, json])]
pub enum Expiration {
#[default]
None,
Expand All @@ -75,10 +70,51 @@ pub enum Expiration {
Block(u64),
}

#[derive(Debug, Clone, BorshDeserialize, BorshSerialize, Deserialize, Serialize)]
#[borsh(crate = "near_sdk::borsh")]
#[serde(crate = "near_sdk::serde")]
#[derive(Debug, Clone)]
#[near(serializers=[borsh, json])]
pub struct TokenAmount {
pub token_id: AccountId,
pub amount: U128,
}

#[test]
fn test_create_action_serialize() {
let action = Action::CreateIntent((
"1".to_string(),
Intent {
initiator: "user.near".parse().unwrap(),
send: TokenAmount {
token_id: "token_a.near".parse().unwrap(),
amount: 1000.into(),
},
receive: TokenAmount {
token_id: "token_b.near".parse().unwrap(),
amount: 2000.into(),
},
expiration: Expiration::Block(123_456),
},
));

assert_eq!(
action.encode().unwrap(),
"AAEAAAAxCQAAAHVzZXIubmVhcgwAAAB0b2tlbl9hLm5lYXLoAwAAAAAAAAAAAAAAAAAADAAAAHRva2VuX2IubmVhctAHAAAAAAAAAAAAAAAAAAACQOIBAAAAAAA="
);
}

#[test]
fn test_create_action_deserialize() {
let action = Action::decode("AAEAAAAxCQAAAHVzZXIubmVhcgwAAAB0b2tlbl9hLm5lYXLoAwAAAAAAAAAAAAAAAAAADAAAAHRva2VuX2IubmVhctAHAAAAAAAAAAAAAAAAAAACQOIBAAAAAAA=").unwrap();
assert!(matches!(action, Action::CreateIntent((id, _)) if id == "1"));
}

#[test]
fn test_execute_action_serialize() {
let action = Action::ExecuteIntent("1".to_string());
assert_eq!(action.encode().unwrap(), "AQEAAAAx");
}

#[test]
fn test_execute_action_deserialize() {
let action = Action::decode("AQEAAAAx").unwrap();
assert!(matches!(action, Action::ExecuteIntent(id) if id == "1"));
}
6 changes: 2 additions & 4 deletions tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ name = "defuse-contract-tests"
version = "0.1.0"
edition.workspace = true

[lints.clippy]
all = "deny"
nursery = "deny"
pedantic = "deny"
[lints]
workspace = true

[dependencies]
defuse-intent-contract = { path = "../intent" }
Expand Down
Loading