Skip to content

FortaStaking

_This is a generic staking contract for the Forta platform. It allows any account to deposit ERC20 tokens to delegate their "power" by staking on behalf of a particular subject. The subject can be scanner, or any other actor in the Forta ecosystem, who need to lock assets in order to contribute to the system.

Stakers take risks with their funds, as bad action from a subject can lead to slashing of the funds. In the meantime, stakers are elligible for rewards. Rewards distributed to a particular subject's stakers are distributed following to each staker's share in the subject.

Stakers can withdraw their funds, following a withdrawal delay. During the withdrawal delay, funds are no longer counting toward the active stake of a subject, but are still slashable.

The SLASHER_ROLE should be given to a future smart contract that will be in charge of resolving disputes.

Stakers receive ERC1155 shares in exchange for their stake, making the active stake transferable. When a withdrawal is initiated, similarly the ERC1155 tokens representing the (transferable) active shares are burned in exchange for non-transferable ERC1155 tokens representing the inactive shares.

ERC1155 shares representing active stake are transferable, and can be used in an AMM. Their value is however subject to quick devaluation in case of slashing event for the corresponding subject. Thus, trading of such shares should be be done very carefully.

WARNING: To stake from another smart contract (smart contract wallets included), it must be fully ERC1155 compatible, implementing ERC1155Receiver. If not, minting of active and inactive shares will fail. Do not deposit on the constructor if you don't implement ERC1155Receiver. During the construction, the minting will succeed but you will not be able to withdraw or mint new shares from the contract. If this happens, transfer your shares to an EOA or fully ERC1155 compatible contract._

onRewardReceived

function onRewardReceived(uint8 subjectType, uint256 subject, uint256 amount) external

stakedToken

contract IERC20 stakedToken

_activeStake

struct Distributions.Balances _activeStake

_inactiveStake

struct Distributions.Balances _inactiveStake

_lockingDelay

mapping(uint256 => mapping(address => struct Timers.Timestamp)) _lockingDelay

_rewards

struct Distributions.Balances _rewards

_released

mapping(uint256 => struct Distributions.SignedBalances) _released

_frozen

mapping(uint256 => bool) _frozen

_withdrawalDelay

uint64 _withdrawalDelay

_treasury

address _treasury

_stakingParameters

contract IStakeController _stakingParameters

StakeDeposited

event StakeDeposited(uint8 subjectType, uint256 subject, address account, uint256 amount)

WithdrawalInitiated

event WithdrawalInitiated(uint8 subjectType, uint256 subject, address account, uint64 deadline)

WithdrawalExecuted

event WithdrawalExecuted(uint8 subjectType, uint256 subject, address account)

Froze

event Froze(uint8 subjectType, uint256 subject, address by, bool isFrozen)

Slashed

event Slashed(uint8 subjectType, uint256 subject, address by, uint256 value)

Rewarded

event Rewarded(uint8 subjectType, uint256 subject, address from, uint256 value)

Released

event Released(uint8 subjectType, uint256 subject, address to, uint256 value)

DelaySet

event DelaySet(uint256 newWithdrawalDelay)

TreasurySet

event TreasurySet(address newTreasury)

StakeParamsManagerSet

event StakeParamsManagerSet(address newManager)

MaxStakeReached

event MaxStakeReached(uint8 subjectType, uint256 subject)

TokensSwept

event TokensSwept(address token, address to, uint256 amount)

WithdrawalNotReady

error WithdrawalNotReady()

SlashingOver90Percent

error SlashingOver90Percent()

WithdrawalSharesNotTransferible

error WithdrawalSharesNotTransferible()

FrozenSubject

error FrozenSubject()

NoActiveShares

error NoActiveShares()

NoInactiveShares

error NoInactiveShares()

StakeInactiveOrSubjectNotFound

error StakeInactiveOrSubjectNotFound()

version

string version

constructor

constructor(address forwarder) public

initialize

function initialize(address __manager, address __router, contract IERC20 __stakedToken, uint64 __withdrawalDelay, address __treasury) public

Initializer method, access point to initialize inheritance tree.

Name Type Description
__manager address address of AccessManager.
__router address address of Router.
__stakedToken contract IERC20 ERC20 to be staked (FORT).
__withdrawalDelay uint64 cooldown period between withdrawal init and withdrawal (in seconds).
__treasury address address where the slashed tokens go to.

activeStakeFor

function activeStakeFor(uint8 subjectType, uint256 subject) public view returns (uint256)

Get stake of a subject (not marked for withdrawal).

Name Type Description
subjectType uint8 agents, scanner or future types of stake subject. See SubjectTypes.sol
subject uint256 id identifying subject (external to FortaStaking).
Name Type Description
[0] uint256 amount of stakedToken actively staked on subject+subjectType.

totalActiveStake

function totalActiveStake() public view returns (uint256)

Get total active stake of all subjects (not marked for withdrawal).

Name Type Description
[0] uint256 amount of stakedToken actively staked on all subject+subjectTypes.

inactiveStakeFor

function inactiveStakeFor(uint8 subjectType, uint256 subject) external view returns (uint256)

Get inactive stake of a subject (marked for withdrawal).

Name Type Description
subjectType uint8 agents, scanner or future types of stake subject. See SubjectTypes.sol
subject uint256 id identifying subject (external to FortaStaking).
Name Type Description
[0] uint256 amount of stakedToken still staked on subject+subjectType but marked for withdrawal.

totalInactiveStake

function totalInactiveStake() public view returns (uint256)

Get total inactive stake of all subjects (marked for withdrawal).

Name Type Description
[0] uint256 amount of stakedToken still staked on all subject+subjectTypes but marked for withdrawal.

sharesOf

function sharesOf(uint8 subjectType, uint256 subject, address account) public view returns (uint256)

Get (active) shares of an account on a subject, corresponding to a fraction of the subject stake.

This is equivalent to getting the ERC1155 balanceOf for keccak256(abi.encodePacked(subjectType, subject)), shifted 9 bits, with the 9th bit set and uint8(subjectType) masked in

Name Type Description
subjectType uint8 agents, scanner or future types of stake subject. See SubjectTypes.sol
subject uint256 id identifying subject (external to FortaStaking).
account address holder of the ERC1155 staking shares.
Name Type Description
[0] uint256 amount of ERC1155 shares account is in possession in representing stake on subject+subjectType.

totalShares

function totalShares(uint8 subjectType, uint256 subject) external view returns (uint256)

Get the total (active) shares on a subject.

This is equivalent to getting the ERC1155 totalSupply for keccak256(abi.encodePacked(subjectType, subject)), shifted 9 bits, with the 9th bit set and uint8(subjectType) masked in

Name Type Description
subjectType uint8 agents, scanner or future types of stake subject. See SubjectTypes.sol
subject uint256 id identifying subject (external to FortaStaking).
Name Type Description
[0] uint256 total ERC1155 shares representing stake on subject+subjectType.

inactiveSharesOf

function inactiveSharesOf(uint8 subjectType, uint256 subject, address account) external view returns (uint256)

Get inactive shares of an account on a subject, corresponding to a fraction of the subject inactive stake.

This is equivalent to getting the ERC1155 balanceOf for keccak256(abi.encodePacked(subjectType, subject)), shifted 9 bits, with the 9th bit unset and uint8(subjectType) masked in.

Name Type Description
subjectType uint8 agents, scanner or future types of stake subject. See SubjectTypes.sol
subject uint256 id identifying subject (external to FortaStaking).
account address holder of the ERC1155 staking shares.
Name Type Description
[0] uint256 amount of ERC1155 shares account is in possession in representing inactive stake on subject+subjectType, marked for withdrawal.

totalInactiveShares

function totalInactiveShares(uint8 subjectType, uint256 subject) external view returns (uint256)

Get the total inactive shares on a subject.

This is equivalent to getting the ERC1155 totalSupply for keccak256(abi.encodePacked(subjectType, subject)), shifted 9 bits, with the 9th bit unset and uint8(subjectType) masked in

Name Type Description
subjectType uint8 agents, scanner or future types of stake subject. See SubjectTypes.sol
subject uint256 id identifying subject (external to FortaStaking).
Name Type Description
[0] uint256 total ERC1155 shares representing inactive stake on subject+subjectType, marked for withdrawal.

isFrozen

function isFrozen(uint8 subjectType, uint256 subject) public view returns (bool)

Checks if a subject frozen (stake of frozen subject cannot be withdrawn).

Name Type Description
subjectType uint8 agents, scanner or future types of stake subject. See SubjectTypes.sol
subject uint256 id identifying subject (external to FortaStaking).
Name Type Description
[0] bool true if subject is frozen, false otherwise

deposit

function deposit(uint8 subjectType, uint256 subject, uint256 stakeValue) public returns (uint256)

Deposit `stakeValue` tokens for a given `subject`, and mint the corresponding active ERC1155 shares. will return tokens staked over maximum for the subject. If stakeValue would drive the stake over the maximum, only stakeValue - excess is transferred, but transaction will not fail. Reverts if max stake for subjectType not set, or subject not found

NOTE: Subject type is necessary because we can't infer subject ID uniqueness between scanners, agents, etc Emits a ERC1155.TransferSingle event and StakeDeposited (to allow accounting per subject type) Emits MaxStakeReached(subjectType, activeSharesId) WARNING: To stake from another smart contract (smart contract wallets included), it must be fully ERC1155 compatible, implementing ERC1155Receiver. If not, minting of active and inactive shares will fail. Do not deposit on the constructor if you don't implement ERC1155Receiver. During the construction, the minting will succeed but you will not be able to withdraw or mint new shares from the contract. If this happens, transfer your shares to an EOA or fully ERC1155 compatible contract.

Name Type Description
subjectType uint8 agents, scanner or future types of stake subject. See SubjectTypes.sol
subject uint256 id identifying subject (external to FortaStaking).
stakeValue uint256 amount of staked token.
Name Type Description
[0] uint256 amount of ERC1155 active shares minted.

_getInboundStake

function _getInboundStake(uint8 subjectType, uint256 subject, uint256 stakeValue) private view returns (uint256, bool)

Calculates how much of the incoming stake fits for subject.

Name Type Description
subjectType uint8 valid subect type
subject uint256 the id of the subject
stakeValue uint256 stake sent by staker
Name Type Description
[0] uint256 stakeValue - excess
[1] bool true if reached max

initiateWithdrawal

function initiateWithdrawal(uint8 subjectType, uint256 subject, uint256 sharesValue) public returns (uint64)

Starts the withdrawal process for an amount of shares. Burns active shares and mints inactive shares (non transferrable). Stake will be available for withdraw() after _withdrawalDelay. If the subject has not been slashed, the shares will correspond 1:1 with stake.

Emits a WithdrawalInitiated event.

Name Type Description
subjectType uint8 agents, scanner or future types of stake subject. See SubjectTypes.sol
subject uint256 id identifying subject (external to FortaStaking).
sharesValue uint256 amount of shares token.
Name Type Description
[0] uint64 amount of time until withdrawal is valid.

withdraw

function withdraw(uint8 subjectType, uint256 subject) public returns (uint256)

Burn `sharesValue` inactive shares for a given `subject`, and withdraw the corresponding tokens (if the subject type has not been frozen, and the withdrawal delay time has passed).

shars must have been marked for withdrawal before by initiateWithdrawal(). Emits events WithdrawalExecuted and ERC1155.TransferSingle.

Name Type Description
subjectType uint8 agents, scanner or future types of stake subject. See SubjectTypes.sol
subject uint256 id identifying subject (external to FortaStaking).
Name Type Description
[0] uint256 amount of withdrawn staked tokens.

slash

function slash(uint8 subjectType, uint256 subject, uint256 stakeValue) public returns (uint256)

Slash a fraction of a subject stake, and transfer it to the treasury. Restricted to the `SLASHER_ROLE`.

This will alter the relationship between shares and stake, reducing shares value for a subject. Emits a Slashed event.

Name Type Description
subjectType uint8 agents, scanner or future types of stake subject. See SubjectTypes.sol
subject uint256 id identifying subject (external to FortaStaking).
stakeValue uint256 amount of staked token.
Name Type Description
[0] uint256 stakeValue

freeze

function freeze(uint8 subjectType, uint256 subject, bool frozen) public

Freeze/unfreeze withdrawal of a subject stake. This will be used when something suspicious happens with a subject but there is not a strong case yet for slashing. Restricted to the `SLASHER_ROLE`.

Emits a Freeze event.

Name Type Description
subjectType uint8 agents, scanner or future types of stake subject. See SubjectTypes.sol
subject uint256 id identifying subject (external to FortaStaking).
frozen bool true to freeze, false to unfreeze.

reward

function reward(uint8 subjectType, uint256 subject, uint256 value) public

Deposit reward value for a given `subject`. The corresponding tokens will be shared amongst the shareholders of this subject.

Emits a Reward event.

Name Type Description
subjectType uint8 agents, scanner or future types of stake subject. See SubjectTypes.sol
subject uint256 id identifying subject (external to FortaStaking).
value uint256 amount of reward tokens.

sweep

function sweep(contract IERC20 token, address recipient) public returns (uint256)

Sweep all token that might be mistakenly sent to the contract. This covers both unrelated tokens and staked tokens that would be sent through a direct transfer. Restricted to SWEEPER_ROLE. If tokens are the same as staked tokens, only the extra tokens (no stake or rewards) will be transferred.

WARNING: thoroughly review the token to b

Name Type Description
token contract IERC20 address of the token to be swept.
recipient address destination address of the swept tokens
Name Type Description
[0] uint256 amount of tokens swept. For unrelated tokens is FortaStaking's balance, for stakedToken its the balance over the active stake + inactive stake + rewards

releaseReward

function releaseReward(uint8 subjectType, uint256 subject, address account) public returns (uint256)

Release reward owed by given `account` for its current or past share for a given `subject`.

If staking from a contract, said contract may optionally implement ERC165 for IRewardReceiver. Emits a Release event.

Name Type Description
subjectType uint8 agents, scanner or future types of stake subject. See SubjectTypes.sol
subject uint256 id identifying subject (external to FortaStaking).
account address that staked on the subject.
Name Type Description
[0] uint256 available reward transferred.

_availableReward

function _availableReward(uint256 activeSharesId, address account) internal view returns (uint256)

Amount of reward tokens owed by given `account` for its current or past share for a given `subject`.

Name Type Description
activeSharesId uint256 ERC1155 id representing the active shares of a subject / subjectType pair.
account address address of the staker
Name Type Description
[0] uint256 rewards available for staker on that subject.

availableReward

function availableReward(uint8 subjectType, uint256 subject, address account) external view returns (uint256)

Amount of reward tokens owed by given `account` for its current or past share for a given `subject`.

Name Type Description
subjectType uint8 type of staking subject (see SubjectTypes.sol)
subject uint256 ID of subject
account address address of the staker
Name Type Description
[0] uint256 rewards available for staker on that subject.

relayPermit

function relayPermit(uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public

Relay a ERC2612 permit signature to the staked token. This cal be bundled with a {deposit} or a {reward} operation using Multicall.

Name Type Description
value uint256 amount of token allowance for deposit/reward
deadline uint256 for the meta-tx to be relayed.
v uint8 part of signature
r bytes32 part of signature
s bytes32 part of signature

_totalHistoricalReward

function _totalHistoricalReward(uint256 activeSharesId) internal view returns (uint256)

_historicalRewardFraction

function _historicalRewardFraction(uint256 activeSharesId, uint256 amount) internal view returns (uint256)

_beforeTokenTransfer

function _beforeTokenTransfer(address operator, address from, address to, uint256[] ids, uint256[] amounts, bytes data) internal virtual

See {ERC1155-_beforeTokenTransfer}.

_stakeToActiveShares

function _stakeToActiveShares(uint256 activeSharesId, uint256 amount) internal view returns (uint256)

_stakeToInactiveShares

function _stakeToInactiveShares(uint256 inactiveSharesId, uint256 amount) internal view returns (uint256)

_activeSharesToStake

function _activeSharesToStake(uint256 activeSharesId, uint256 amount) internal view returns (uint256)

_inactiveSharesToStake

function _inactiveSharesToStake(uint256 inactiveSharesId, uint256 amount) internal view returns (uint256)

setDelay

function setDelay(uint64 newDelay) public

Sets withdrawal delay. Restricted to DEFAULT_ADMIN_ROLE

Name Type Description
newDelay uint64 in seconds.

setTreasury

function setTreasury(address newTreasury) public

Sets destination of slashed tokens. Restricted to DEFAULT_ADMIN_ROLE

Name Type Description
newTreasury address address.

setStakingParametersManager

function setStakingParametersManager(contract IStakeController newStakingParameters) public

setURI

function setURI(string newUri) public

Sets URI of the ERC1155 tokens. Restricted to DEFAULT_ADMIN_ROLE

Name Type Description
newUri string root of the hosted metadata.

_msgSender

function _msgSender() internal view virtual returns (address sender)

Helper to get either msg msg.sender if not a meta transaction, signer of forwarder metatx if it is.

_msgData

function _msgData() internal view virtual returns (bytes)

Helper to get msg.data if not a meta transaction, forwarder data in metatx if it is.

__gap

uint256[40] __gap
Back to top