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

version v0.3.0 #132

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
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
15 changes: 14 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,17 @@

[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
url = https://github.com/foundry-rs/forge-std

[submodule "lib/pendle-core-v2-public"]
path = lib/pendle-core-v2-public
url = https://github.com/pendle-finance/pendle-core-v2-public

[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
branch = v4.9.3

[submodule "lib/openzeppelin-contracts-upgradeable"]
path = lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
> Version: `v0.3.0`

# DFMM

This repository contains the smart contracts source code for the DFMM protocol.



## What is DFMM?

The DFMM protocol is a novel portfolio management system designed to leverage external strategy contracts. This system separates the operational logic and the mathematical model: the `DFMM` core contract completely relies on the strategies to validate the state of each interaction. On the other hand, this core contract acts as a single entry point and performs all the operations, such as:
Expand Down
2 changes: 2 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
remappings = [
"solmate/=lib/solstat/lib/solmate/src/",
"solstat/=lib/solstat/src/",
"pendle/=lib/pendle-core-v2-public/contracts/"
]
solc_version = "0.8.22"

Expand All @@ -23,6 +24,7 @@ number_underscore = "thousands"
[rpc_endpoints]
local = "http://localhost:8545"
optimism_sepolia = "${OPTIMISM_SEPOLIA_RPC_URL}"
mainnet = "${MAINNET_RPC_URL}"

[etherscan]
optimism_sepolia = { key = "${ETHERSCAN_API_KEY}" }
18 changes: 18 additions & 0 deletions kit/src/behaviors/allocate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#[allow(unused_imports)]
use arbiter_engine::machine::ControlFlow;

use super::*;

#[derive(Debug, Deserialize, Serialize)]
pub struct Allocate {}
#[allow(unused_variables)]
#[async_trait::async_trait]
impl Behavior<()> for Allocate {
async fn startup(
&mut self,
client: Arc<ArbiterMiddleware>,
messager: Messager,
) -> Result<Option<EventStream<()>>> {
Ok(None)
}
}
15 changes: 12 additions & 3 deletions kit/src/behaviors/deployer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use arbiter_bindings::bindings::weth::WETH;
use arbiter_engine::messager::To;
use bindings::{
constant_sum::ConstantSum, dfmm::DFMM, geometric_mean::GeometricMean, log_normal::LogNormal,
};
Expand All @@ -11,6 +10,7 @@ use super::*;
pub struct Deployer {}
#[derive(Debug, Deserialize, Serialize)]
pub struct DeploymentData {
pub n_token_geometric_mean: Address,
pub weth: Address,
pub dfmm: Address,
pub geometric_mean: Address,
Expand Down Expand Up @@ -48,13 +48,13 @@ impl Behavior<()> for Deployer {
.await?;
trace!("ConstantSum deployed at {:?}", constant_sum.address());

let token_x = arbiter_bindings::bindings::arbiter_token::ArbiterToken::deploy(
let token_x = ArbiterToken::deploy(
client.clone(),
("Token X".to_owned(), "ARBX".to_owned(), 18u8),
)?
.send()
.await?;
let token_y = arbiter_bindings::bindings::arbiter_token::ArbiterToken::deploy(
let token_y = ArbiterToken::deploy(
client.clone(),
("Token Y".to_owned(), "ARBY".to_owned(), 18u8),
)?
Expand All @@ -67,7 +67,12 @@ impl Behavior<()> for Deployer {
token_y.address()
);

let n_token_geometric_mean = GeometricMean::deploy(client.clone(), dfmm.address())?
.send()
.await?;

let deployment_data = DeploymentData {
n_token_geometric_mean: n_token_geometric_mean.address(),
weth: weth.address(),
dfmm: dfmm.address(),
geometric_mean: geometric_mean.address(),
Expand Down Expand Up @@ -141,6 +146,10 @@ mod tests {
Address::from_str("0xaeb166f1355c6254d01a54317ef8d4d21bfcb4b0").unwrap(),
parsed_data.constant_sum
);
assert_eq!(
Address::from_str("0xa4bb88cbfc92d86ae00842dcfa5a1ac32b0714b3").unwrap(),
parsed_data.n_token_geometric_mean
);
} else {
panic!("No message received");
}
Expand Down
19 changes: 16 additions & 3 deletions kit/src/behaviors/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,31 @@
use std::sync::Arc;

use arbiter_bindings::bindings::arbiter_token::ArbiterToken;
use arbiter_engine::{
machine::{Behavior, CreateStateMachine, Engine, EventStream, StateMachine},
messager::Messager,
machine::{Behavior, ControlFlow, CreateStateMachine, Engine, EventStream, StateMachine},
messager::{Message, Messager, To},
};
use arbiter_macros::Behaviors;
use serde::{Deserialize, Serialize};

use self::deployer::Deployer;
use self::{allocate::Allocate, deployer::Deployer, token_admin::TokenAdmin};
use super::*;

pub mod allocate;
pub mod deployer;
pub mod token_admin;

#[derive(Behaviors, Debug, Deserialize, Serialize)]
pub enum Behaviors {
Allocate(Allocate),
Deployer(Deployer),
TokenAdmin(TokenAdmin),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TokenData {
pub name: String,
pub symbol: String,
pub decimals: u8,
pub address: Option<eAddress>,
}
128 changes: 128 additions & 0 deletions kit/src/behaviors/token_admin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
use std::collections::HashMap;

use super::*;

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct TokenAdmin {
/// The identifier of the token admin.
pub token_data: HashMap<String, TokenData>,
#[serde(skip)]
pub tokens: Option<HashMap<String, ArbiterToken<ArbiterMiddleware>>>,
#[serde(skip)]
pub client: Option<Arc<ArbiterMiddleware>>,
#[serde(skip)]
pub messager: Option<Messager>,
#[serde(default)]
pub count: u64,
#[serde(default = "default_max_count")]
pub max_count: Option<u64>,
}

pub fn default_max_count() -> Option<u64> {
Some(3)
}

/// Used as an action to ask what tokens are available.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum TokenAdminQuery {
/// Get the address of the token.
AddressOf(String),

/// Mint tokens.
MintRequest(MintRequest),
}

/// Used as an action to mint tokens.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MintRequest {
/// The token to mint.
pub token: String,

/// The address to mint to.
pub mint_to: eAddress,

/// The amount to mint.
pub mint_amount: u64,
}

#[async_trait::async_trait]
impl Behavior<Message> for TokenAdmin {
#[tracing::instrument(skip(self), fields(id = messager.id.as_deref()))]
async fn startup(
&mut self,
client: Arc<ArbiterMiddleware>,
messager: Messager,
) -> Result<Option<EventStream<Message>>> {
self.messager = Some(messager.clone());
self.client = Some(client.clone());
for token_data in self.token_data.values_mut() {
let token = ArbiterToken::deploy(
client.clone(),
(
token_data.name.clone(),
token_data.symbol.clone(),
token_data.decimals,
),
)
.unwrap()
.send()
.await
.unwrap();

token_data.address = Some(token.address());
self.tokens
.get_or_insert_with(HashMap::new)
.insert(token_data.name.clone(), token.clone());
}
Ok(None)
}

#[tracing::instrument(skip(self), fields(id =
self.messager.as_ref().unwrap().id.as_deref()))]
async fn process(&mut self, event: Message) -> Result<ControlFlow> {
if self.tokens.is_none() {
error!(
"There were no tokens to deploy! You must add tokens to
the token admin before running the simulation."
);
}

let query: TokenAdminQuery = serde_json::from_str(&event.data).unwrap();
trace!("Got query: {:?}", query);
let messager = self.messager.as_ref().unwrap();
match query {
TokenAdminQuery::AddressOf(token_name) => {
trace!(
"Getting address of token with name: {:?}",
token_name.clone()
);
let token_data = self.token_data.get(&token_name).unwrap();
messager
.send(To::Agent(event.from.clone()), token_data.address)
.await?;
}
TokenAdminQuery::MintRequest(mint_request) => {
trace!("Minting tokens: {:?}", mint_request);
let token = self
.tokens
.as_ref()
.unwrap()
.get(&mint_request.token)
.unwrap();
token
.mint(mint_request.mint_to, eU256::from(mint_request.mint_amount))
.send()
.await
.unwrap()
.await
.unwrap();
self.count += 1;
if self.count == self.max_count.unwrap_or(u64::MAX) {
warn!("Reached max count. Halting behavior.");
return Ok(ControlFlow::Halt);
}
}
}
Ok(ControlFlow::Continue)
}
}
4 changes: 2 additions & 2 deletions kit/src/bindings/arb_math.rs

Large diffs are not rendered by default.

Loading
Loading