Skip to content

Commit

Permalink
Added Treasury (#62)
Browse files Browse the repository at this point in the history
* updated treasury contract

* impleamented tests

* updated test lib

* Update: If applied this commit will fix all the highlighted issues in #62

* Update test for providing liquidity to Carmine AMM

* Implement two step ownership transfer

* Integrate treasury contract

* Integrate treasury contract

* Integrate treasury contract and update CI
  • Loading branch information
Nonnyjoe authored and tensojka committed Jun 8, 2024
1 parent 8e6ff76 commit b92974f
Show file tree
Hide file tree
Showing 8 changed files with 433 additions and 8 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ on:
- 'Scarb.toml'

env:
SCARB_VERSION: 2.6.3
FOUNDRY_VERSION: 0.19.0
SCARB_VERSION: 2.6.4
FOUNDRY_VERSION: 0.20.1

jobs:
build:
Expand Down
10 changes: 8 additions & 2 deletions Scarb.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@ name = "governance"
version = "0.3.0"
dependencies = [
"cubit",
"openzeppelin",
"snforge_std",
]

[[package]]
name = "openzeppelin"
version = "0.10.0"
source = "git+https://github.com/OpenZeppelin/cairo-contracts.git?tag=v0.10.0#d77082732daab2690ba50742ea41080eb23299d3"

[[package]]
name = "snforge_std"
version = "0.19.0"
source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.19.0#a3391dce5bdda51c63237032e6cfc64fb7a346d4"
version = "0.20.1"
source = "git+https://github.com/foundry-rs/starknet-foundry.git?tag=v0.20.1#fea2db8f2b20148cc15ee34b08de12028eb42942"
14 changes: 11 additions & 3 deletions Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,24 @@ cairo-version = "2.6.3"
[dependencies]
cubit = { git = "https://github.com/influenceth/cubit.git", commit = "62756082bf2555d7ab25c69d9c7bc30574ff1ce8" }
starknet = ">=1.3.0"
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.19.0" }
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry.git", tag = "v0.20.1" }
openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.10.0" }

[[target.starknet-contract]]

[[tool.snforge.fork]]
name = "MAINNET"
url = "http://34.22.208.73:6060/v0_6"
url = "http://34.22.208.73:6060/v0_7"
block_id.tag = "Latest"

[[tool.snforge.fork]]
name = "GOERLI"
url = "http://34.22.208.73:6061/v0_6"
url = "http://34.22.208.73:6061/v0_7"
block_id.tag = "Latest"

[[tool.snforge.fork]]
name = "SEPOLIA"
url = "http://34.22.208.73:6062/v0_7"
block_id.tag = "Latest"

RUST_BACKTRACE=1
1 change: 1 addition & 0 deletions src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ mod proposals;
mod traits;
mod types;
mod upgrades;
mod treasury;
237 changes: 237 additions & 0 deletions src/treasury.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
use starknet::ContractAddress;
use governance::types::OptionType;

#[starknet::interface]
trait ITreasury<TContractState> {
fn send_tokens_to_address(
ref self: TContractState,
receiver: ContractAddress,
amount: u256,
token_addr: ContractAddress
) -> bool;
fn update_AMM_address(ref self: TContractState, new_amm_address: ContractAddress);
fn provide_liquidity_to_carm_AMM(
ref self: TContractState,
pooled_token_addr: ContractAddress,
quote_token_address: ContractAddress,
base_token_address: ContractAddress,
option_type: OptionType,
amount: u256
);
fn withdraw_liquidity(
ref self: TContractState,
pooled_token_addr: ContractAddress,
quote_token_address: ContractAddress,
base_token_address: ContractAddress,
option_type: OptionType,
lp_token_amount: u256
);
fn get_amm_address(self: @TContractState) -> ContractAddress;
}

#[starknet::contract]
mod Treasury {
use core::starknet::event::EventEmitter;
use super::{OptionType};
use core::num::traits::zero::Zero;
use openzeppelin::access::ownable::OwnableComponent;
use openzeppelin::access::ownable::interface::IOwnableTwoStep;
use openzeppelin::upgrades::upgradeable::UpgradeableComponent;
use openzeppelin::upgrades::interface::IUpgradeable;
use starknet::{ContractAddress, get_caller_address, get_contract_address, ClassHash};
use governance::airdrop::{IAirdropDispatcher, IAirdropDispatcherTrait};
use governance::traits::{
IERC20Dispatcher, IERC20DispatcherTrait, IAMMDispatcher, IAMMDispatcherTrait
};
component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);
component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);


#[abi(embed_v0)]
impl OwnableTwoStepImpl = OwnableComponent::OwnableTwoStepImpl<ContractState>;
impl InternalImpl = OwnableComponent::InternalImpl<ContractState>;
impl UpgradeableInternalImpl = UpgradeableComponent::InternalImpl<ContractState>;

#[storage]
struct Storage {
amm_address: ContractAddress,
#[substorage(v0)]
ownable: OwnableComponent::Storage,
#[substorage(v0)]
upgradeable: UpgradeableComponent::Storage
}
#[derive(starknet::Event, Drop)]
struct TokenSent {
receiver: ContractAddress,
token_addr: ContractAddress,
amount: u256
}

#[derive(starknet::Event, Drop)]
struct AMMAddressUpdated {
previous_address: ContractAddress,
new_amm_address: ContractAddress
}

#[derive(starknet::Event, Drop)]
struct LiquidityProvided {
quote_token_address: ContractAddress,
base_token_address: ContractAddress,
option_type: OptionType,
amount: u256
}

#[derive(starknet::Event, Drop)]
struct LiquidityWithdrawn {
quote_token_address: ContractAddress,
base_token_address: ContractAddress,
option_type: OptionType,
lp_token_amount: u256
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
TokenSent: TokenSent,
AMMAddressUpdated: AMMAddressUpdated,
LiquidityProvided: LiquidityProvided,
LiquidityWithdrawn: LiquidityWithdrawn,
#[flat]
OwnableEvent: OwnableComponent::Event,
#[flat]
UpgradeableEvent: UpgradeableComponent::Event
}

mod Errors {
const INSUFFICIENT_FUNDS: felt252 = 'Insufficient token balance';
const INSUFFICIENT_POOLED_TOKEN: felt252 = 'Insufficient Pooled balance';
const INSUFFICIENT_LP_TOKENS: felt252 = 'Insufficient LP token balance';
const ADDRESS_ZERO_GOVERNANCE: felt252 = 'Governance addr is zero address';
const ADDRESS_ZERO_AMM: felt252 = 'AMM addr is zero address';
const ADDRESS_ALREADY_CHANGED: felt252 = 'New Address same as Previous';
}

#[constructor]
fn constructor(
ref self: ContractState,
gov_contract_address: ContractAddress,
AMM_contract_address: ContractAddress
) {
assert(gov_contract_address != zeroable::Zeroable::zero(), Errors::ADDRESS_ZERO_GOVERNANCE);
assert(AMM_contract_address != zeroable::Zeroable::zero(), Errors::ADDRESS_ZERO_AMM);
self.amm_address.write(AMM_contract_address);
self.ownable.initializer(gov_contract_address);
}

#[abi(embed_v0)]
impl Treasury of super::ITreasury<ContractState> {
fn send_tokens_to_address(
ref self: ContractState,
receiver: ContractAddress,
amount: u256,
token_addr: ContractAddress
) -> bool {
self.ownable.assert_only_owner();
let token: IERC20Dispatcher = IERC20Dispatcher { contract_address: token_addr };
assert(token.balanceOf(get_contract_address()) >= amount, Errors::INSUFFICIENT_FUNDS);
let status: bool = token.transfer(receiver, amount);
self.emit(TokenSent { receiver, token_addr, amount });
return status;
}

fn update_AMM_address(ref self: ContractState, new_amm_address: ContractAddress) {
self.ownable.assert_only_owner();
assert(new_amm_address != zeroable::Zeroable::zero(), Errors::ADDRESS_ZERO_AMM);
assert(new_amm_address != self.amm_address.read(), Errors::ADDRESS_ALREADY_CHANGED);
let previous_address: ContractAddress = self.amm_address.read();
self.amm_address.write(new_amm_address);
self.emit(AMMAddressUpdated { previous_address, new_amm_address })
}

fn provide_liquidity_to_carm_AMM(
ref self: ContractState,
pooled_token_addr: ContractAddress,
quote_token_address: ContractAddress,
base_token_address: ContractAddress,
option_type: OptionType,
amount: u256
) {
self.ownable.assert_only_owner();
let carm_AMM: IAMMDispatcher = IAMMDispatcher {
contract_address: self.amm_address.read()
};

let pooled_token: IERC20Dispatcher = IERC20Dispatcher {
contract_address: pooled_token_addr
};

assert(
pooled_token.balanceOf(get_contract_address()) >= amount,
Errors::INSUFFICIENT_POOLED_TOKEN
);
pooled_token.approve(self.amm_address.read(), amount);

carm_AMM
.deposit_liquidity(
pooled_token_addr, quote_token_address, base_token_address, option_type, amount
);
self
.emit(
LiquidityProvided {
quote_token_address, base_token_address, option_type, amount
}
);
}

fn withdraw_liquidity(
ref self: ContractState,
pooled_token_addr: ContractAddress,
quote_token_address: ContractAddress,
base_token_address: ContractAddress,
option_type: OptionType,
lp_token_amount: u256
) {
self.ownable.assert_only_owner();
let carm_AMM: IAMMDispatcher = IAMMDispatcher {
contract_address: self.amm_address.read()
};

let lp_token_addr = carm_AMM
.get_lptoken_address_for_given_option(
quote_token_address, base_token_address, option_type
);
let lp_token: IERC20Dispatcher = IERC20Dispatcher { contract_address: lp_token_addr };
assert(
lp_token.balanceOf(get_contract_address()) >= lp_token_amount,
Errors::INSUFFICIENT_LP_TOKENS
);

carm_AMM
.withdraw_liquidity(
pooled_token_addr,
quote_token_address,
base_token_address,
option_type,
lp_token_amount
);
self
.emit(
LiquidityWithdrawn {
quote_token_address, base_token_address, option_type, lp_token_amount
}
);
}

fn get_amm_address(self: @ContractState) -> ContractAddress {
self.amm_address.read()
}
}

#[abi(embed_v0)]
impl UpgradeableImpl of IUpgradeable<ContractState> {
fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {
self.ownable.assert_only_owner();
self.upgradeable._upgrade(new_class_hash);
}
}
}
2 changes: 1 addition & 1 deletion tests/add_options.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use tests::basic::submit_44_signal_proposals;
use super::basic::submit_44_signal_proposals;

use governance::traits::IAMM;
use governance::contract::IGovernanceDispatcher;
Expand Down
3 changes: 3 additions & 0 deletions tests/lib.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod test_treasury;
mod basic;
mod add_options;
Loading

0 comments on commit b92974f

Please sign in to comment.