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

Fee work #279

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 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
2 changes: 1 addition & 1 deletion .github/workflows/integration_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ jobs:
strategy:
fail-fast: false
matrix:
test_type: [ "AaveV2Stablecoin", "CellarV1", "CellarV2", "CellarV2_2", "ScheduledCorkProposal", "ScheduledAxelarCorkProposal", "ScheduledCorkMulticallProposal"]
test_type: [ "AaveV2Stablecoin", "CellarV1", "CellarV2", "CellarV2_2", "ScheduledCorkProposal", "ScheduledAxelarCorkProposal", "ScheduledCorkMulticallProposal", "UpdateStrategistPlatformCutJob"]
steps:
- name: Set up Go 1.22
uses: actions/setup-go@v2
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ default-members = ["."]
resolver = "2"

[workspace.package]
version = "4.2.7"
version = "4.2.8"
edition = "2021"

[workspace.dependencies]
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Reference: https://www.lpalmieri.com/posts/fast-rust-docker-builds/

FROM rust:1.76-bullseye as cargo-chef-rust
RUN cargo install cargo-chef --version 0.1.62
RUN cargo install cargo-chef --version 0.1.62 --locked
RUN rustup component add rustfmt

FROM cargo-chef-rust as planner
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ e2e_scheduled_cork_proposal_multicall_test:
@scripts/clean_slate.sh
@E2E_SKIP_CLEANUP=true integration_tests/integration_tests.test -test.failfast -test.v -test.run IntegrationTestSuite -testify.m TestScheduledCorkMulticallProposal || make -s fail

e2e_update_strategist_platform_cut_test:
@scripts/clean_slate.sh
@E2E_SKIP_CLEANUP=true integration_tests/integration_tests.test -test.failfast -test.v -test.run IntegrationTestSuite -testify.m TestUpdateStrategistPlatformCut || make -s fail

fail:
@echo 'test failed; dumping container logs into ./testdata for review'
@mkdir -p ./testdata
Expand Down
Binary file modified crates/steward-proto/src/gen/descriptor.bin
Binary file not shown.
2 changes: 1 addition & 1 deletion crates/steward-proto/src/gen/steward.v4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5023,7 +5023,7 @@ pub struct CellarV25governance {
}
/// Nested message and enum types in `CellarV2_5Governance`.
pub mod cellar_v2_5governance {
/// The function you wish to execute on the target cellar
/// The function you wish to execute on the target cellar
#[derive(serde::Deserialize, serde::Serialize, Clone, PartialEq, ::prost::Message)]
pub struct FunctionCall {
#[prost(
Expand Down
2 changes: 1 addition & 1 deletion hash_proto
Original file line number Diff line number Diff line change
@@ -1 +1 @@
4e0284025de03d59dfec8ca9913874737e4a310150543686ae35adbe406dbb42
e8a8e44b747fa06f2ca23cfbbbfc368d88d2cb13b08ae35587b1d163df780543
244 changes: 243 additions & 1 deletion integration_tests/cellar_v2_2_abi.go

Large diffs are not rendered by default.

596 changes: 596 additions & 0 deletions integration_tests/cellar_v2_5_abi.go

Large diffs are not rendered by default.

174 changes: 1 addition & 173 deletions integration_tests/ethereum/contracts/MockCellarV2.2.json
Original file line number Diff line number Diff line change
@@ -1,173 +1 @@
[
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "adaptor",
"type": "address"
}
],
"name": "AddAdaptorToCatalogue",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint32",
"name": "position",
"type": "uint32"
}
],
"name": "AddPositionToCatalogue",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"components": [
{
"internalType": "address",
"name": "adaptor",
"type": "address"
},
{
"internalType": "bytes[]",
"name": "callData",
"type": "bytes[]"
}
],
"indexed": false,
"internalType": "struct CellarV2_2.AdaptorCall[]",
"name": "data",
"type": "tuple[]"
}
],
"name": "CallOnAdaptor",
"type": "event"
},
{
"anonymous": false,
"inputs": [],
"name": "Multicall",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "user",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnerUpdated",
"type": "event"
},
{
"inputs": [
{
"internalType": "address",
"name": "adaptor",
"type": "address"
}
],
"name": "addAdaptorToCatalogue",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint32",
"name": "position",
"type": "uint32"
}
],
"name": "addPositionToCatalogue",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"internalType": "address",
"name": "adaptor",
"type": "address"
},
{
"internalType": "bytes[]",
"name": "callData",
"type": "bytes[]"
}
],
"internalType": "struct CellarV2_2.AdaptorCall[]",
"name": "data",
"type": "tuple[]"
}
],
"name": "callOnAdaptor",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes[]",
"name": "data",
"type": "bytes[]"
}
],
"name": "multicall",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "setOwner",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Cellar__InvalidFeeCut","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"adaptor","type":"address"}],"name":"AddAdaptorToCatalogue","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"position","type":"uint32"}],"name":"AddPositionToCatalogue","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"adaptor","type":"address"},{"internalType":"bytes[]","name":"callData","type":"bytes[]"}],"indexed":false,"internalType":"struct CellarV2_2.AdaptorCall[]","name":"data","type":"tuple[]"}],"name":"CallOnAdaptor","type":"event"},{"anonymous":false,"inputs":[],"name":"Multicall","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"oldPlatformCut","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newPlatformCut","type":"uint64"}],"name":"StrategistPlatformCutChanged","type":"event"},{"inputs":[],"name":"MAX_FEE_CUT","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"adaptor","type":"address"}],"name":"addAdaptorToCatalogue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"position","type":"uint32"}],"name":"addPositionToCatalogue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"adaptor","type":"address"},{"internalType":"bytes[]","name":"callData","type":"bytes[]"}],"internalType":"struct CellarV2_2.AdaptorCall[]","name":"data","type":"tuple[]"}],"name":"callOnAdaptor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeData","outputs":[{"internalType":"uint64","name":"strategistPlatformCut","type":"uint64"},{"internalType":"uint64","name":"platformFee","type":"uint64"},{"internalType":"uint64","name":"lastAccrual","type":"uint64"},{"internalType":"address","name":"strategistPayoutAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"cut","type":"uint64"}],"name":"setStrategistPlatformCut","outputs":[],"stateMutability":"nonpayable","type":"function"}]
54 changes: 54 additions & 0 deletions integration_tests/ethereum/contracts/MockCellarV2.2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,58 @@ contract CellarV2_2 is Owned {
function addPositionToCatalogue(uint32 position) external onlyOwner {
emit AddPositionToCatalogue(position);
}

/**
* @notice Emitted when strategist platform fee cut is changed.
* @param oldPlatformCut value strategist platform fee cut was changed from
* @param newPlatformCut value strategist platform fee cut was changed to
*/
event StrategistPlatformCutChanged(uint64 oldPlatformCut, uint64 newPlatformCut);

/**
* @notice Attempted to change strategist fee cut with invalid value.
*/
error Cellar__InvalidFeeCut();

/**
* @notice Data related to fees.
* @param strategistPlatformCut Determines how much platform fees go to strategist.
* This should be a value out of 1e18 (ie. 1e18 represents 100%, 0 represents 0%).
* @param platformFee The percentage of total assets accrued as platform fees over a year.
This should be a value out of 1e18 (ie. 1e18 represents 100%, 0 represents 0%).
* @param strategistPayoutAddress Address to send the strategists fee shares.
*/
struct FeeData {
uint64 strategistPlatformCut;
uint64 platformFee;
uint64 lastAccrual;
address strategistPayoutAddress;
}
cbrit marked this conversation as resolved.
Show resolved Hide resolved

/**
* @notice Stores all fee data for cellar.
*/
FeeData public feeData =
FeeData({
strategistPlatformCut: 0.75e18,
platformFee: 0.01e18,
lastAccrual: 0,
strategistPayoutAddress: address(0)
});

/**
* @notice Sets the max possible fee cut for this cellar.
*/
uint64 public constant MAX_FEE_CUT = 1e18;

/**
* @notice Sets the Strategists cut of platform fees
* @param cut the platform cut for the strategist
*/
function setStrategistPlatformCut(uint64 cut) external onlyOwner {
if (cut > MAX_FEE_CUT) revert Cellar__InvalidFeeCut();
emit StrategistPlatformCutChanged(feeData.strategistPlatformCut, cut);

feeData.strategistPlatformCut = cut;
}
cbrit marked this conversation as resolved.
Show resolved Hide resolved
}
1 change: 1 addition & 0 deletions integration_tests/ethereum/contracts/MockCellarV2.5.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Cellar__InvalidFeeCut","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"oldPlatformCut","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newPlatformCut","type":"uint64"}],"name":"StrategistPlatformCutChanged","type":"event"},{"inputs":[],"name":"feeData","outputs":[{"internalType":"uint64","name":"strategistPlatformCut","type":"uint64"},{"internalType":"uint64","name":"platformFee","type":"uint64"},{"internalType":"uint64","name":"lastAccrual","type":"uint64"},{"internalType":"address","name":"strategistPayoutAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"cut","type":"uint64"}],"name":"setStrategistPlatformCut","outputs":[],"stateMutability":"nonpayable","type":"function"}]
64 changes: 64 additions & 0 deletions integration_tests/ethereum/contracts/MockCellarV2.5.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

import {Address, ERC20, Owned} from "./interfaces.sol";

/**
* @title Sommelier Cellar
* @notice A composable ERC4626 that can use a set of other ERC4626 or ERC20 positions to earn yield.
* @author Brian Le
*/
contract CellarV2_5 is Owned {
using Address for address;

constructor() Owned(msg.sender) {}

/**
* @notice Attempted to change strategist fee cut with invalid value.
*/
error Cellar__InvalidFeeCut();

/**
* @notice Emitted when strategist platform fee cut is changed.
* @param oldPlatformCut value strategist platform fee cut was changed from
* @param newPlatformCut value strategist platform fee cut was changed to
*/
event StrategistPlatformCutChanged(uint64 oldPlatformCut, uint64 newPlatformCut);

/**
* @notice Sets the max possible fee cut for this cellar.
*/
uint64 internal constant MAX_FEE_CUT = 1e18;

/**
* @notice Data related to fees.
* @param strategistPlatformCut Determines how much platform fees go to strategist.
* This should be a value out of 1e18 (ie. 1e18 represents 100%, 0 represents 0%).
* @param platformFee The percentage of total assets accrued as platform fees over a year.
* This should be a value out of 1e18 (ie. 1e18 represents 100%, 0 represents 0%).
* @param strategistPayoutAddress Address to send the strategists fee shares.
*/
struct FeeData {
uint64 strategistPlatformCut;
uint64 platformFee;
uint64 lastAccrual;
address strategistPayoutAddress;
}

/**
* @notice Stores all fee data for cellar.
*/
FeeData public feeData = FeeData({
strategistPlatformCut: 0.75e18,
platformFee: 0.01e18,
lastAccrual: 0,
strategistPayoutAddress: address(0)
});

function setStrategistPlatformCut(uint64 cut) external onlyOwner {
if (cut > MAX_FEE_CUT) revert Cellar__InvalidFeeCut();
emit StrategistPlatformCutChanged(feeData.strategistPlatformCut, cut);

feeData.strategistPlatformCut = cut;
}
cbrit marked this conversation as resolved.
Show resolved Hide resolved
}
13 changes: 13 additions & 0 deletions integration_tests/ethereum/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ task(
await cellarV2_2.deployed();
console.log(`cellar v2.2 contract deployed at - ${cellarV2_2.address}`);

const CellarV2_5 = await hre.ethers.getContractFactory("CellarV2_5");
const cellarV2_5 = (await CellarV2_5.deploy());
await cellarV2_5.deployed();
console.log(`cellar v2.5 contract deployed at - ${cellarV2_5.address}`);

const Adaptor = await hre.ethers.getContractFactory("Adaptor");
const adaptor = (await Adaptor.deploy());
await adaptor.deployed();
Expand Down Expand Up @@ -72,6 +77,14 @@ task(
`CellarV2.2 contract at ${cellarV2_2.address} is now owned by Gravity contract at ${gravity.address} with hash ${cellarV2_2Hash}`,
);

let { cellarV2_5Hash } = await cellarV2_5.setOwner(gravity.address, {
gasPrice: hre.ethers.BigNumber.from('99916001694'),
from: cellarSignerAddress
});
console.log(
`CellarV2.5 contract at ${cellarV2_5.address} is now owned by Gravity contract at ${gravity.address} with hash ${cellarV2_5Hash}`,
);

let { vaultHash } = await vaultCellar.setOwner(gravity.address, {
gasPrice: hre.ethers.BigNumber.from('99916001694'),
from: cellarSignerAddress
Expand Down
Loading
Loading