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

Draft version of smart contracts #13

Merged
merged 90 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
f07c91f
add erc20 staking pool
ayodeko Mar 28, 2024
3172595
add factory contract
ayodeko Mar 28, 2024
e2441f9
extra changes to factory contract
ayodeko Mar 28, 2024
18b1346
extra changes to factory contract
ayodeko Mar 28, 2024
f79e3ec
install hardhat
ayodeko Apr 2, 2024
106daf2
extra changes and to the staking pool
ayodeko Apr 2, 2024
7321cfd
extra changes to staking pool
ayodeko Apr 2, 2024
d3092cc
Add StakingPool
ayodeko Apr 2, 2024
2cb1f48
Made changes requested from pull request review
ayodeko Apr 9, 2024
1adb56f
extra changes to pull request review
ayodeko Apr 9, 2024
334e293
extra review changes
ayodeko Apr 10, 2024
69591f0
more changes
ayodeko Apr 10, 2024
04555df
more review changes
ayodeko Apr 10, 2024
29717b0
[Update] Fixed reward update issues, minor code improvements
SergeyPoslavskiy Apr 10, 2024
1ab0fee
[Update] Minor naming updates, gas optimization
SergeyPoslavskiy Apr 11, 2024
612242b
[Update] Removed deploy fee
SergeyPoslavskiy Apr 11, 2024
4347553
[Update] Added separate claim lockup
SergeyPoslavskiy Apr 11, 2024
66a31b7
Merge pull request #1 from soramitsu/feature/init_ERC20_pool_and_factory
SergeyPoslavskiy Apr 12, 2024
8bf95ef
[Update] Added draft version of penaltyFee pool
SergeyPoslavskiy Apr 12, 2024
afd5231
[Update] Minor fixes, added slither
SergeyPoslavskiy Apr 12, 2024
ca5c17e
Merge branch 'develop' into feature/erc20penaltyfeepool
SergeyPoslavskiy Apr 12, 2024
0a7a8e1
implemented no lock up pool and factory
ayodeko Apr 16, 2024
b304b6e
rename lock up pool and factory
ayodeko Apr 16, 2024
81247b7
[Update] Minor review and bug fixes
SergeyPoslavskiy Apr 17, 2024
337ee9e
add vs settings to gitignore
ayodeko Apr 16, 2024
1275b36
[Testing] Initialize Lock Up unit testing, code chage to lock up cont…
ayodeko Apr 20, 2024
b73b86e
[Fix] Bug Fixes on contracts
ayodeko Apr 20, 2024
7371159
[Refactore] destrctured startTime error
ayodeko Apr 20, 2024
3ddd359
[Test] Added Mock Token, more test changes
ayodeko Apr 22, 2024
00ed516
[Update] refactor commission
SergeyPoslavskiy Apr 23, 2024
29cdeb7
[Update] Rewards are transfered during pool activation, fixed error n…
SergeyPoslavskiy Apr 23, 2024
365a2e4
[Update] Added factory, changed fee calculation logic
SergeyPoslavskiy Apr 23, 2024
7cc580d
[Test] Refacored tests to new structure
ayodeko Apr 24, 2024
190422b
[Test] Added extra test scenarios
ayodeko Apr 25, 2024
79b0050
[Fixes] made changes to conditional statement in pool constructor
ayodeko Apr 25, 2024
b5e9cdc
[Test] Added extra tests for unstake
ayodeko Apr 26, 2024
22efa3b
[Fix] Fixed reward calculation issue caused by precision factor
SergeyPoslavskiy Apr 26, 2024
b0a5edf
Merge pull request #9 from soramitsu/feature/erc20nolockuppool
SergeyPoslavskiy May 2, 2024
7b84a10
Merge pull request #10 from soramitsu/develop
SergeyPoslavskiy May 2, 2024
324c7b7
[Test] Extra changes to test scenarios
ayodeko May 2, 2024
0938eb6
[Update] Added penalty fee pool, added getUserInfo function
SergeyPoslavskiy May 2, 2024
03b6386
Merge pull request #11 from soramitsu/feature/erc20penaltyfeepool
SergeyPoslavskiy May 2, 2024
83290ba
Merge pull request #12 from soramitsu/feature/erc20nolockuppool
SergeyPoslavskiy May 2, 2024
606e443
[CI] Added slither analysis
SergeyPoslavskiy May 2, 2024
f4468e9
[CI] Fix ci policies
SergeyPoslavskiy May 2, 2024
8b1d9b9
[CI] Removed CI
SergeyPoslavskiy May 2, 2024
b2c8168
[CI] Refactor CI, removed sarif upload for now
SergeyPoslavskiy May 3, 2024
2e9bf2f
[Lint] Test lint with slither report
SergeyPoslavskiy May 3, 2024
cb29b62
[Update] Added code comments example, minor claim logic update with 0…
SergeyPoslavskiy May 3, 2024
2e4011f
[Update] Added interfaces for pool and errors
SergeyPoslavskiy May 3, 2024
b8970b5
[Update] Added struct inheritance
SergeyPoslavskiy May 3, 2024
d1b040f
[Update] Modified reward calculation in activate function
SergeyPoslavskiy May 6, 2024
ca9081d
[Update] Added view function to get pools in factories, refactored ac…
SergeyPoslavskiy May 6, 2024
cc7de7c
[Update] Added claimFee in penalty pool
SergeyPoslavskiy May 6, 2024
056719a
[Feature] Init ERC721 pool
ayodeko May 6, 2024
e6f4a56
[Edit] More erc721 changes
ayodeko May 6, 2024
ce31bb1
Merge branch 'develop' into feature/erc721lockupstakingpool
ayodeko May 6, 2024
1b63b49
[Update] Added deployment script
SergeyPoslavskiy May 6, 2024
e13ad4a
Merge pull request #18 from soramitsu/develop
SergeyPoslavskiy May 6, 2024
3cc2e13
[Fix] Fixed ci workflows
SergeyPoslavskiy May 6, 2024
ce55673
Merge branch 'develop' into feature/erc721lockupstakingpool
SergeyPoslavskiy May 6, 2024
c5fc949
[Update] Implemented draft request format for lockup factory
SergeyPoslavskiy May 6, 2024
d81c8ed
Merge remote-tracking branch 'origin/feature/erc721lockupstakingpool'…
ayodeko May 6, 2024
7f3d0de
[Update] Implemented draft request format for lockup pool
SergeyPoslavskiy May 6, 2024
e7a6dad
[Update] Extended lockup factory, added events and custom errors
SergeyPoslavskiy May 7, 2024
b78dc6f
[Update] Minor update
SergeyPoslavskiy May 7, 2024
7cb3b86
[Fix] Prevent simple reentrancy
SergeyPoslavskiy May 7, 2024
65805d2
[Update] Refactor ERC721 contract to inherit from interface
ayodeko May 8, 2024
98ae036
[Fix] bug fix in ERC721
ayodeko May 8, 2024
a613676
[Update] request based model implementation
SergeyPoslavskiy May 13, 2024
8c631f6
Merge pull request #19 from soramitsu/feature/request_based_factory
SergeyPoslavskiy May 13, 2024
d76d778
Merge pull request #20 from soramitsu/develop
SergeyPoslavskiy May 13, 2024
9021954
[Fix] Minor erc721 pool fixes
SergeyPoslavskiy May 13, 2024
b81f0d7
[CI] Added codespell, fixed slither
SergeyPoslavskiy May 13, 2024
80fb968
[Fix] Fixed codespell
SergeyPoslavskiy May 13, 2024
81258c3
[Fix] Fixed codespell, slither issues
SergeyPoslavskiy May 13, 2024
0f489a1
[Update] Added ERC721 lockup and draft-ERC721penaltyFee, updated pack…
SergeyPoslavskiy May 14, 2024
3057de7
Merge pull request #17 from soramitsu/feature/erc721lockupstakingpool
SergeyPoslavskiy May 14, 2024
2f5f0b1
Merge pull request #22 from soramitsu/develop
SergeyPoslavskiy May 14, 2024
c7b2ff3
[CI] Added coverage workflow
SergeyPoslavskiy May 14, 2024
835449f
[Fix] Added coverage to hh config
SergeyPoslavskiy May 14, 2024
49d87bf
[Update] Added ERC721 factories, code refactoring
SergeyPoslavskiy May 14, 2024
9847461
[Fix] Fixed case sensitive impotrs
SergeyPoslavskiy May 14, 2024
fe64f16
Rename ERC721LockupFactory.sol to ERC721LockUpFactory.sol
SergeyPoslavskiy May 14, 2024
22d5d16
Rename ERC721NoLockupFactory.sol to ERC721NoLockUpFactory.sol
SergeyPoslavskiy May 14, 2024
7833584
Rename IERC20NoLockupPool.sol to IERC20NoLockUpPool.sol
SergeyPoslavskiy May 14, 2024
5f5bcc0
Rename IERC721NoLockupPool.sol to IERC721NoLockUpPool.sol
SergeyPoslavskiy May 14, 2024
c656988
Rename ILockupFactory.sol to ILockUpFactory.sol
SergeyPoslavskiy May 14, 2024
bcdba86
Rename INoLockupFactory.sol to INoLockUpFactory.sol
SergeyPoslavskiy May 14, 2024
55d6919
Merge pull request #23 from soramitsu/feature/request_based_factory
SergeyPoslavskiy May 14, 2024
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 .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
AMOY_API_KEY="00002N111EF000004101000051113J0000"
PRIVATE_KEY="0x0000000000000000000000000000000000000000000000000000000000000000"
19 changes: 19 additions & 0 deletions .github/workflows/codespell.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Codespell checkup

on:
push:
branches: [ develop ]
pull_request:
branches: [ master, develop ]

jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run CodeSpell
uses: codespell-project/[email protected]
with:
check_filenames: true
skip: package-lock.json,*.pdf
30 changes: 30 additions & 0 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Solidity Coverage

on:
push:
branches: [ develop ]
pull_request:
branches: [ master, develop ]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [ 20.x ]

steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set .env
run: cp .env.example .env

- name: Run tests
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run coverage
- uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
34 changes: 34 additions & 0 deletions .github/workflows/slither.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Slither Analysis

on:
push:
branches: [ develop ]
pull_request:
branches: [ master, develop ]

jobs:
analyze:
runs-on: ubuntu-latest
permissions:
contents: read
actions: read
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set .env
run: cp .env.example .env

- name: Run Slither
uses: crytic/[email protected]
id: slither
with:
fail-on: high
sarif: results.sarif
slither-config: slither.config.json
slither-args: --checklist --markdown-root ${{ github.server_url }}/${{ github.repository }}/blob/${{ github.sha }}/

- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ${{ steps.slither.outputs.sarif }}
29 changes: 29 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Hardhat Testing

on:
push:
branches: [ develop ]
pull_request:
branches: [ master, develop ]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [ 20.x ]

steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set .env
run: cp .env.example .env

- name: Run tests
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run test
- name: Markdown report
run: cat "./test/gasReport.md" > $GITHUB_STEP_SUMMARY
20 changes: 20 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
node_modules
.env

# Hardhat files
/cache
/artifacts
/ignition/deployments
/test/gasReport.md

# TypeChain files
/typechain
/typechain-types

# solidity-coverage files
/coverage
/coverage.json
yarn.lock


settings.json
122 changes: 122 additions & 0 deletions contracts/factories/ERC20LockUpFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
ERC20LockUpFactory
SPDX-License-Identifier: MIT
*/

pragma solidity 0.8.25;
import {ERC20LockUpPool} from "../pools/ERC20LockUpStakingPool.sol";
import {ILockUpFactory} from "../interfaces/IFactories/ILockUpFactory.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

/// @title ERC20LockUpStakingFactory
/// @notice A smart contract for deploying ERC20 LockUp staking pools.
/// @author Ayooluwa Akindeko, Soramitsu team
contract ERC20LockUpStakingFactory is Ownable, ILockUpFactory {
using SafeERC20 for IERC20;

address[] public stakingPools;
Request[] public requests;
mapping(uint256 id => address pool) public poolById;

constructor() Ownable(msg.sender) {}

/// @notice Function allows users to deploy the LockUp staking pool with specified parameters
function deploy(uint256 id) public returns (address newPoolAddress) {
if (requests.length < id) revert InvalidId();
Request memory req = requests[id];
if (req.requestStatus != Status.APPROVED) revert InvalidRequestStatus();
if (msg.sender != req.deployer) revert InvalidCaller();
newPoolAddress = address(
new ERC20LockUpPool{
salt: keccak256(
abi.encode(
req.data.stakeToken,
req.data.rewardToken,
req.data.rewardPerSecond,
req.data.poolStartTime,
req.data.poolEndTime
)
)
}(
req.data.stakeToken,
req.data.rewardToken,
req.data.poolStartTime,
req.data.poolEndTime,
req.data.unstakeLockUpTime,
req.data.claimLockUpTime,
req.data.rewardPerSecond
)
);
stakingPools.push(newPoolAddress);
requests[id].requestStatus = Status.DEPLOYED;
poolById[id] = newPoolAddress;
uint256 rewardAmount = (req.data.poolEndTime - req.data.poolStartTime) *
req.data.rewardPerSecond;
ERC20LockUpPool(newPoolAddress).transferOwnership(msg.sender);
// Transfer reward tokens from the owner to the contract
// slither-disable-next-line arbitrary-send-erc20
IERC20(req.data.rewardToken).safeTransferFrom(
msg.sender,
newPoolAddress,
rewardAmount
);
emit StakingPoolDeployed(newPoolAddress, id);
}

function requestDeployment(DeploymentData calldata data) external {
if (data.stakeToken == address(0) || data.rewardToken == address(0))
revert InvalidTokenAddress();
if (data.rewardPerSecond == 0) revert InvalidRewardRate();
requests.push(
Request({
deployer: msg.sender,
requestStatus: Status.CREATED,
data: data
})
);
emit RequestSubmitted(
requests.length - 1,
msg.sender,
Status.CREATED,
data
);
}

function approveRequest(uint256 id) external onlyOwner {
if (requests.length < id) revert InvalidId();
Request storage req = requests[id];
if (req.requestStatus != Status.CREATED) revert InvalidRequestStatus();
req.requestStatus = Status.APPROVED;
emit RequestStatusChanged(id, req.requestStatus);
}

function denyRequest(uint256 id) external onlyOwner {
if (requests.length < id) revert InvalidId();
Request storage req = requests[id];
if (req.requestStatus != Status.CREATED) revert InvalidRequestStatus();
req.requestStatus = Status.DENIED;
emit RequestStatusChanged(id, req.requestStatus);
}

function cancelRequest(uint256 id) external {
if (requests.length < id) revert InvalidId();
Request storage req = requests[id];
if (msg.sender != req.deployer) revert InvalidCaller();
if (
req.requestStatus != Status.CREATED &&
req.requestStatus != Status.APPROVED
) revert InvalidRequestStatus();
req.requestStatus = Status.CANCELED;
emit RequestStatusChanged(id, req.requestStatus);
}

function getRequests() external view returns (Request[] memory reqs) {
reqs = requests;
}

function getPools() external view returns (address[] memory pools) {
pools = stakingPools;
}
}
120 changes: 120 additions & 0 deletions contracts/factories/ERC20NoLockUpFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
ERC20LockUpFactory
SPDX-License-Identifier: MIT
*/

pragma solidity 0.8.25;
import {ERC20NoLockUpPool} from "../pools/ERC20NoLockUpStakingPool.sol";
import {INoLockUpFactory} from "../interfaces/IFactories/INoLockUpFactory.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

/// @title ERC20LockUpStakingFactory
/// @notice A smart contract for deploying ERC20 regular staking pools.
/// @author Ayooluwa Akindeko, Soramitsu team
contract ERC20NoLockUpStakingFactory is Ownable, INoLockUpFactory {
using SafeERC20 for IERC20;

address[] public stakingPools;
Request[] public requests;
mapping(uint256 id => address pool) public poolById;

constructor() Ownable(msg.sender) {}

/// @notice Function allows users to deploy the LockUp staking pool with specified parameters
function deploy(uint256 id) public returns (address newPoolAddress) {
if (requests.length < id) revert InvalidId();
Request memory req = requests[id];
if (req.requestStatus != Status.APPROVED) revert InvalidRequestStatus();
if (msg.sender != req.deployer) revert InvalidCaller();
newPoolAddress = address(
new ERC20NoLockUpPool{
salt: keccak256(
abi.encode(
req.data.stakeToken,
req.data.rewardToken,
req.data.rewardPerSecond,
req.data.poolStartTime,
req.data.poolEndTime
)
)
}(
req.data.stakeToken,
req.data.rewardToken,
req.data.rewardPerSecond,
req.data.poolStartTime,
req.data.poolEndTime
)
);
stakingPools.push(newPoolAddress);
requests[id].requestStatus = Status.DEPLOYED;
poolById[id] = newPoolAddress;
uint256 rewardAmount = (req.data.poolEndTime - req.data.poolStartTime) *
req.data.rewardPerSecond;
ERC20NoLockUpPool(newPoolAddress).transferOwnership(msg.sender);
// Transfer reward tokens from the owner to the contract
// slither-disable-next-line arbitrary-send-erc20
IERC20(req.data.rewardToken).safeTransferFrom(
msg.sender,
newPoolAddress,
rewardAmount
);
emit StakingPoolDeployed(newPoolAddress, id);
}

function requestDeployment(DeploymentData calldata data) external {
if (data.stakeToken == address(0) || data.rewardToken == address(0))
revert InvalidTokenAddress();
if (data.rewardPerSecond == 0) revert InvalidRewardRate();
requests.push(
Request({
deployer: msg.sender,
requestStatus: Status.CREATED,
data: data
})
);
emit RequestSubmitted(
requests.length - 1,
msg.sender,
Status.CREATED,
data
);
}

function approveRequest(uint256 id) external onlyOwner {
if (requests.length < id) revert InvalidId();
Request storage req = requests[id];
if (req.requestStatus != Status.CREATED) revert InvalidRequestStatus();
req.requestStatus = Status.APPROVED;
emit RequestStatusChanged(id, req.requestStatus);
}

function denyRequest(uint256 id) external onlyOwner {
if (requests.length < id) revert InvalidId();
Request storage req = requests[id];
if (req.requestStatus != Status.CREATED) revert InvalidRequestStatus();
req.requestStatus = Status.DENIED;
emit RequestStatusChanged(id, req.requestStatus);
}

function cancelRequest(uint256 id) external {
if (requests.length < id) revert InvalidId();
Request storage req = requests[id];
if (msg.sender != req.deployer) revert InvalidCaller();
if (
req.requestStatus != Status.CREATED ||
req.requestStatus != Status.APPROVED
) revert InvalidRequestStatus();
req.requestStatus = Status.CANCELED;
emit RequestStatusChanged(id, req.requestStatus);
}

function getRequests() external view returns (Request[] memory reqs) {
reqs = requests;
}

function getPools() external view returns (address[] memory pools) {
pools = stakingPools;
}
}
Loading
Loading