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

Adding Router contract #37

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
9ea322c
Adding Router contract placeholder
dimpar Nov 20, 2023
9acd4c2
Adding solmate lib 6.2.0
dimpar Nov 22, 2023
de39aa2
Copying ERC4626 related contracts from ERC4626-Alliance
dimpar Nov 22, 2023
1d4c88e
Adding support for Solidity 0.8.10. Used by ERC4626 contracts
dimpar Nov 22, 2023
0a795c3
Adding annotation that these contracts were copied from ERC4626-Allia…
dimpar Nov 22, 2023
af2c73b
Ignoring styling of added Solidity ERC4626 lib contracts
dimpar Nov 22, 2023
12a29ea
Moving erc4626 contracts under lib/erc4626 dir
dimpar Nov 22, 2023
6fe3fc4
Adding initial modifiers and data structres for allocators
dimpar Nov 23, 2023
65678bd
For solidity>7.0 visibility for contracts can be ignored
dimpar Nov 23, 2023
2fc9357
Removing components of ERC4626RouterBase
dimpar Nov 24, 2023
5bd254a
Adding IERC4626 interface
dimpar Nov 24, 2023
e5e31d6
Update pre-commit hooks for `core` workspace
r-czajkowski Nov 15, 2023
fcea06f
Add pre-commit hooks for website workspace
r-czajkowski Nov 15, 2023
8db37ed
Add pre-commit hooks for dapp workspace
nkuba Nov 23, 2023
ca0fa0a
Auto-fix dapp files formatting
nkuba Nov 23, 2023
60edc3f
Add auto-fix commit to git blame ignore revs
nkuba Nov 23, 2023
238f2ab
Add info about testing pre-commit hooks config
nkuba Nov 23, 2023
e0ba0ac
Add basic GH workflow for website workspace
r-czajkowski Nov 17, 2023
ef5929d
Add basic GH workflow for dapp workspace
nkuba Nov 23, 2023
06edcd2
Add build execution in dapp and website CI
nkuba Nov 23, 2023
b7aee18
Drafting allocate and collect functions for Acre Router
dimpar Nov 24, 2023
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: 2 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Auto-fix linting
d2a058fe6cfbab6f82d0d977d1b2d8bd9f494df1
50 changes: 50 additions & 0 deletions .github/workflows/dapp.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: dApp

on:
push:
branches:
- main
paths:
- "dapp/**"
pull_request:

defaults:
run:
working-directory: ./dapp

jobs:
dapp-format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version-file: "dapp/.nvmrc"
cache: "yarn"
cache-dependency-path: "dapp/yarn.lock"

- name: Install Dependencies
run: yarn install --prefer-offline --frozen-lockfile

- name: Format
run: yarn format

dapp-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version-file: "dapp/.nvmrc"
cache: "yarn"
cache-dependency-path: "dapp/yarn.lock"

- name: Install Dependencies
run: yarn install --prefer-offline --frozen-lockfile

- name: Build
run: yarn build
50 changes: 50 additions & 0 deletions .github/workflows/website.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Website

on:
push:
branches:
- main
paths:
- "website/**"
pull_request:

defaults:
run:
working-directory: ./website

jobs:
website-format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version-file: "website/.nvmrc"
cache: "yarn"
cache-dependency-path: "website/yarn.lock"

- name: Install Dependencies
run: yarn install --prefer-offline --frozen-lockfile

- name: Format
run: yarn format

website-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version-file: "website/.nvmrc"
cache: "yarn"
cache-dependency-path: "website/yarn.lock"

- name: Install Dependencies
run: yarn install --prefer-offline --frozen-lockfile

- name: Build
run: yarn build
52 changes: 43 additions & 9 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,21 +1,55 @@
repos:
- repo: local
hooks:
- id: lint-sol
# Core
- id: core-lint-sol
name: "lint core sol"
entry: /usr/bin/env bash -c "cd core/ && npm run lint:sol"
files: '\.sol$'
entry: /usr/bin/env bash -c "npm --prefix ./core/ run lint:sol"
files: ^core/
types: [solidity]
language: script
description: "Checks solidity code according to the package's linter configuration"
- id: lint-js
- id: core-lint-js
name: "lint core ts/js"
entry: /usr/bin/env bash -c "cd core/ && npm run lint:js"
files: '\.(ts|js)$'
entry: /usr/bin/env bash -c "npm --prefix ./core/ run lint:js"
files: ^core/
types_or: [ts, javascript]
language: script
description: "Checks TS/JS code according to the package's linter configuration"
- id: lint-config
- id: core-lint-config
name: "lint core json/yaml"
entry: /usr/bin/env bash -c "cd core/ && npm run lint:config"
files: '\.(json|yaml)$'
entry: /usr/bin/env bash -c "npm --prefix ./core/ run lint:config"
files: ^core/
types_or: [json, yaml]
language: script
description: "Checks JSON/YAML code according to the package's linter configuration"
# dApp
- id: dapp-lint-js
name: "lint dapp ts/js"
entry: /usr/bin/env bash -c "npm --prefix ./dapp/ run lint:js"
files: ^dapp/
types_or: [ts, tsx, javascript, jsx]
language: script
description: "Checks TS/JS code according to the package's linter configuration"
- id: dapp-lint-config
name: "lint dapp json/yaml"
entry: /usr/bin/env bash -c "npm --prefix ./dapp/ run lint:config"
files: ^dapp/
types_or: [json, yaml]
language: script
description: "Checks JSON/YAML code according to the package's linter configuration"
# Website
- id: website-lint-js
name: "lint website ts/js"
entry: /usr/bin/env bash -c "npm --prefix ./website/ run lint:js"
files: ^website/
types_or: [ts, tsx, javascript, jsx]
language: script
description: "Checks TS/JS code according to the package's linter configuration"
- id: website-lint-config
name: "lint website json/yaml"
entry: /usr/bin/env bash -c "npm --prefix ./website/ run lint:config"
files: ^website/
types_or: [json, yaml]
language: script
description: "Checks JSON/YAML code according to the package's linter configuration"
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,15 @@ To setup the hooks follow the steps:
```sh
pre-commit install
```

#### Testing

To test the pre-commit hooks configuration you can invoke them with one of the
commands:
```sh
# Execute hooks for all files:
pre-commit run --all-files

# Execute hooks for specific files (e.g. Acre.sol):
pre-commit run --files ./core/contracts/Acre.sol
```
Empty file removed core/.git-blame-ignore-revs
Empty file.
1 change: 1 addition & 0 deletions core/.prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ deployments/
export.json
export/
typechain/
contracts/lib/
4 changes: 3 additions & 1 deletion core/.solhint.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
"extends": "thesis",
"plugins": [],
"rules": {}
"rules": {
"func-visibility": ["warn", { "ignoreConstructors": true }]
}
}
1 change: 1 addition & 0 deletions core/.solhintignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules/
contracts/lib/
105 changes: 105 additions & 0 deletions core/contracts/AcreRouter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
pragma solidity 0.8.20;

import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol";
import {ERC20} from "solmate/src/tokens/ERC20.sol";
import {ERC4626} from "solmate/src/mixins/ERC4626.sol";
import {Owned} from "solmate/src/auth/Owned.sol";

// TODO: add description
contract AcreRouter is Owned {
using SafeTransferLib for ERC20;

ERC20 public immutable stBTC;
ERC20 public immutable tBTC;

/// @notice Approved allocators which essentially are the ERC4626 vaults that
/// deposit funds to yield strategies, e.g. Uniswap V3 WBTC/TBTC pool.
/// Each Allocator contract is managed by a Yield Manager. From Acre"s
/// perspective, the Allocator contract can be a part of an external
/// Yield Module and does not care how the yield is generated.
address[] public allocators;
mapping(address => bool) public isAllocator;

/// @notice Acre Manager address. Only Acre Manager can set or remove
/// Strategy Allocators.
address public acreManager;

event AllocatorAdded(address indexed allocator);
event AllocatorRemoved(address indexed allocator);

event AcreManagerSet(address indexed manager);

modifier onlyAcreManager() {
require(msg.sender == acreManager, "Caller is not an Acre Manager");
_;
}

constructor(ERC20 _stBTC, ERC20 _tBTC) Owned(msg.sender) {
stBTC = _stBTC;
tBTC = _tBTC;
}

function setAcreManager(address manager) external onlyOwner {
require(manager != address(0), "Zero address");
acreManager = manager;
emit AcreManagerSet(manager);
}

function addAllocator(address allocator) external onlyAcreManager {
require(!isAllocator[allocator], "Allocator already exists");
allocators.push(allocator);
isAllocator[allocator] = true;
emit AllocatorAdded(allocator);
}

function removeAllocator(address allocator) external onlyAcreManager {
require(isAllocator[allocator], "Not an allocator");

delete isAllocator[allocator];

for (uint256 i = 0; i < allocators.length; i++) {
if (allocators[i] == allocator) {
allocators[i] = allocators[allocators.length - 1];
allocators.pop();
break;
}
}

emit AllocatorRemoved(allocator);
}

/// @notice Routes funds from stBTC (Acre) to a given allocator
/// @param allocator Address of the allocator to route the funds to.
/// @param amount Amount of TBTC to allocate.
function allocate(address allocator, uint256 amount) public {
require(msg.sender == address(stBTC), "stBTC only");
if (!isAllocator[allocator]) {
revert("Allocator is not approved");
}

tBTC.safeTransferFrom(msg.sender, address(this), amount);
tBTC.safeApprove(allocator, amount);
// TODO: implement protection from the inflation attack / slippage
ERC4626(allocator).deposit(amount, address(this));
}

/// @notice Collects TBTC from an allocator and approves them to be collected
/// by stBTC (Acre)
/// @param allocator Address of the allocator to collect the assets from.
/// @param shares Amount of shares to collect. Shares are the internal representation
/// of the underlying asset in the allocator. Concrete amount of the
/// underlying asset is calculated by calling `convertToAssets` on
/// the allocator and the shares are burned.
function collect(address allocator, uint256 shares) public {
require(msg.sender == address(stBTC), "stBTC only");

if (!isAllocator[allocator]) {
revert("Allocator is not approved");
}

// TODO: implement protection from the inflation attack / slippage
// TODO: use IERC4626 interface
uint256 assets = ERC4626(allocator).redeem(shares, address(this), address(this));
tBTC.safeApprove(address(stBTC), assets);
}
}
Loading
Loading