Skip to content

Commit

Permalink
update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
anajuliabit committed Jun 25, 2024
1 parent 380c582 commit 832f70b
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 298 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ out/
# Dotenv file
.env

node_modules/
node_modules/

lcov.info
97 changes: 48 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,66 +1,65 @@
## Foundry
## Overview

**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.**
Enables keypers to stake SHU tokens for a minimum period. In exchange, keypers receive rewards in the form of
SHU. Rewards are automatically compounded when the contract state is updated and can be withdraw at any time.

Foundry consists of:
The architecture consists of two contracts:

- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools).
- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data.
- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network.
- **Chisel**: Fast, utilitarian, and verbose solidity REPL.
1. [Staking Contract](docs/staking-contract.md): The main contract where keypers can stake SHU tokens and claim rewards.
2. [Rewards Distributor Contract](docs/rewards-distributor.md): A contract that distributes rewards to the
staking contract at a fixed rate per second.

## Documentation
The contracts are designed to be customizable, with adjustable parameters such as the lock period, minimum stake, and reward emission. Additionally, the contracts uses the Transparent Proxy pattern, where only the DAO has the permission to upgrade the contract and call the owner functions defined below.

https://book.getfoundry.sh/
## Security Considerations

## Usage
1. The contracts uses the Ownable2Step pattern where only the DAO has the
permission to upgrade the contract and call the owner functions.
2. The contracts follows the checks-effects-interactions pattern to
prevent reentrancy attacks.
3. The contracts has 100% unit test coverage
4. The contracts has been deployed to the testnet and integration tests
have been run.
5. The contracts has integration tests running against the mainnet fork
to ensure the contract behaves as expected in a real environment.
6. The contracts has been audited by a third-party security firm or audit contest platform.
7. An AST analyzer has been run on the staking contract.
8. There are CI checks in place to ensure the code is formatted correctly and
the tests pass.

### Build
## FAQ

```shell
$ forge build
```
1. Is there a deadline for distributing the rewards?
No, the rewards distribution will continue until the rewards contract is depleted.

### Test
2. Can the stkSHU token be transferred?
No, the stkSHU token is non-transferable. Keyper can only unstake the SHU
tokens which will burn the stkSHU tokens.

```shell
$ forge test
```
3. Is the lock period the same for all stakes?
No, each stake has an individual lock period determined by the current lock period set by the DAO at the time of keyper's stake. The lock period can be updated by the DAO. If the new lock period is shorter than the current one for that stake, the new lock period will be honored. This allows keyper to trust that their tokens will not be locked for longer than the originally agreed-upon period when they staked, and also enables keyper to unstake their tokens in emergency situations.

### Format
4. Are the rewards distributed per second or per block?
Per second.

```shell
$ forge fmt
```
5. Are the rewards automatically compounded?
Yes, the rewards are automatically compounded when the contract state is updated, i.e., when anyone interacts with a non-view function.

### Gas Snapshots
6. Are the rewards calculated based on individual stakes or the total amount of shares the keyper has?
The rewards are calculated based on the total amount of shares the keyper
has. This means that when the keyper claims rewards, they will receive the
rewards for all their stakes.

```shell
$ forge snapshot
```
7. When unstaking, are the rewards also transferred to the keyper?
The keyper has the option to choose whether they want to claim the rewards when they unstake. This is the default behavior.

### Anvil
8. Is there a minimum stake amount?
Yes, there is a minimum amount of SHU tokens that must be staked at the first
stake. This amount can be set by the DAO. An unstake can never result in a
balance lower than the minimum stake amount.

```shell
$ anvil
```
## Protocol Invariants [TBD]

### Deploy

```shell
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>
```

### Cast

```shell
$ cast <subcommand>
```

### Help

```shell
$ forge --help
$ anvil --help
$ cast --help
```
1. The total amount of SHU tokens staked in the contract must be equal to the
total amount of SHU tokens staked by each keyper: `totalStaked = sum(stakes[keyper].amount)`.
2. On unstake, `keyperStake.timestamp + lockPeriod <= block.timestamp` if global `lockPeriod` is greater or equal to the stake lock period, otherwise `keyperStake.timestamp + keyperStake.lockPeriod <= block.timestamp`.
50 changes: 50 additions & 0 deletions docs/rewards-distributor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Rewards Distribution Contract

The rewards distribution contract is responsible for distributing rewards to the
staking and delegate contract. The rewards distribution contract is owned by the DAO and
contains the rewards emission rate for each receiver, i.e either the staking or
delegate contract.

## Storage Layout

- `mapping(address receiver => RewardConfiguration configuration) public
rewardConfigurations`: a mapping from the receiver address to the reward configuration.

```solidity
struct RewardConfiguration {
uint256 emissionRate; // emission per second
uint256 lastUpdate; // last update timestamp
}
```

1. The `emissionRate` defines the number of rewards tokens distributed per
second. This is a fixed rate and determines how many reward tokens the contract
allocates every second to be distributed to all the stakers in the receiver contract.

2. The `lastUpdate` timestamp is the last time the rewards were distributed to the
receiver contract. This timestamp is used to calculate the rewards accumulated
since the last update.

## Owner Functions (DAO)

### `setRewardConfiguration(address receiver, uint256 emissionRate)`

Add, update or stop distributing rewards to a receiver. The emission rate is
the number of reward tokens distributed per second. This function can only be
called by the Owner (DAO). If the emission rate for the specified receiver is not 0,
the function will update the `emissionRate`. If the owner wants to stop
distributing rewards, they should set the emission rate to 0.

## Permissionless Functions

### `distributionRewards()`

Distribute all the rewards to the receiver contract accumulated until from the
`lastUpdate` timestamp to the current timestamp. If the msg.sender is not one of
the receivers, the function will revert.

## View Functions

### `getRewardConfiguration(address receiver)`

Get the reward configuration for a specific receiver.
Loading

0 comments on commit 832f70b

Please sign in to comment.