Specification for OVERLOΔD
on the Ethereum Virtual Machine
1.0 Abstract
Overload is a restaking protocol on the Ethereum Virtual Machine (EVM) that allows you to restake any ERC-20, to any contract. This document covers the entierty of the Overload protocol, as well as the technical implementation details and trade-offs considered whilst designing the primitive.
2.0 Motivation
Given the rise of restaked Ether (ETH) and restaked liquid staking derivatives (LSDs), we generalize the concept further to allow any onchain ERC-20 token to be restakable. We believe this increases possible security for Actively Validated Services (AVSs), and will be a net-positive for the industry.
We find the opportunity to also extend the contract functionality further, and have aimed to architect a permisionless and modular restaking contract. Developers can find optionality in how they want the restaking to behave, and how they want the AVSs to reach consensus. This becomes possible through the implementation of Uniswap V4-esque hooks, as well as modularizing the states of an AVS correctly.
The trade-offs that Overload introduce are what we believe is to be unique, when compared to other protocols in the market. Overload takes a more onchain-first approach in which we believe simplifies the core contracts as well reduces the possible attack-vectors and avoids codebase bloat when building AVSs. By moving the node gossiping and attestations effectively onchain, we sidestep a whole set of common issues in Proof-of-Stake consensus. Given these novel attributes of reaching consensus, we call this approach Proof-on-Chain consensus, which we will explain in further detail in this document.
3.0 Abstractions
This section will briefly introduce the various abstractions in the Overload protocol.
Restaking/Delegation
Restaking and delegation are synonymous inside the overload-sol
codebase, and is mainly managed by the `Overload` Solidty contract.
Let `X` be the amount of tokens deposited into Overload. Then, a delegator is able to delegate to a maximum of 32 distinct consensus addresses, where for each consensus address there is one validator delegated too.
struct Delegation { address consensus; address validator; uint256 amount; } mapping(address owner => mapping(address token => Delegation[])) public delegations;
Validator
A delegator delegates to a validator, and it is possible to delegate yourself as well. The validators are tasked with attesting chunks, either onchain or offchain.
We recommend onchain attestations to avoid e.g. double voting behaviours. When attestations are gathered offchain, then a more rigourous implementation of slashing also becomes required, which is non-trivial to implement and test. The validator node software will also become bloated with peer-to-peer libraries, and networking between nodes will be critical.
With transaction fees coming down due to L2 technology and EIP-4844, we believe it is timely to moving more validator logic to onchain contracts. Fast-forwarding more years, we see a possiblity in which transactions fees can maybe be lowered by another order of magnitude, and onchain consensus becomes a more enticing architecture for a restaking primitive.
struct Validator { uint256 amount; uint32 startBlock; uint32 endBlock; } struct Metadata { uint16 fee; // fee in 0.0001 = 0.01% (1% is `100`), range is `0` to `10000`. string name; string description; } mapping(address consensus => mapping(address validator => Metadata)) public metadata; mapping(address consensus => mapping(address validator => mapping(address token => Validator[]))) public validators;
We also include checkpointing to validator's attestation power. This makes is possible to get the attestation power for a validator at any blockheight, both onchain and offchain. For fetching data offchain, it is possible to fork at a blockheight as well.
Chunk
A chunk is an onchain or offchain data structure that is to be attested by validators. The detailed implementation of a chunk is up to the developer to decide.
If the chunks are posted onchain, then it is the "sequencer" that has the role to post the chunks. The term sequencer is borrowed from L2 terminology, as their roles are similar in nature. The sequencer can be decentralized, but we expect them to be centralized to begin with. The difficulty of decentralizing the sequencer can be tough, depending on what the application does.
Sequencer
The sequencer has the role of posting every chunk onchain. If the consensus is offchain, then we expect the implementation is for the sequencer to gather signatures offchain, and aggregate them through BLS signatures. In this scenario, BLS signatures are a gas and networking bandwidth optimization.
In the onchain scenario, the sequencer will not post attestations onchain for the validators anymore, as we would otherwise have to re-implement slashing to prevent double voting and other possible offenses.
The EVM support BLS signatures through the alt_bn128
curve, now called bn254
. This has been proven to not give 128-bits of security, although it's the only pairing-friendly elliptic curve that's available on the EVM at the moment. When bls12-381
precompiles are added to the EVM, then we suggest AVS to upgrade to that curve instead. To read more about bls12-381
, we refer to EIP-2537.
Gossip
Gossiping for Overload we expect to be onchain. This includes gossiping of chunks, validator attestations, total attestations, active attestations and other values required to reach consensus for AVSs.
By moving gossiping onchain, each validator does not need to e.g. configure firewalls, instead everything is read-and-write directly to the L2 blockchain, which effectively acts as the networking layer. We believe this simplifies the development for AVS, as nodes with extensive peer-to-peer software take time to test, to ensure liveness and that packages are broadcasted correctly in the network.
A project would also need to address e.g. potential DDoS attacks, so we believe moving networking onchain to L2s is a good trade-off given transactions costs have down an order of magnitude since EIP-4844. For posting blobs that are of larger size, we believe Data Availability blockchains such as Celestia can be utilized to reduce operation costs further for validators, if needed.
Penalties
When attestations are moved onchain, the need to slash a validator that double votes becomes a non-problem. By saving the state of a validator that has voted, they cannot vote more than once which is inherent to how the EVM works.
This allows for a different user-experience for delegators/restakers, where they do not have to worry about being slashed when a validator has potential bugs.
The problem of liveness/inactivity still remains. If validators joins a validator set, but in a scenario where quorum is not reached, the AVS would fail to reach finality. For Ethereum, the solution is "inacitivy leak", where their stake of `32 ETH` slowly drained, and upon reaching `16 ETH` they are ejected. For Tendermint, validator can be jailed if, thus kicked from the validator set.
For Overload, we expect AVSs to implement a mechanism where validtors can be kicked from the validator set, if they fail to attest across sufficient amount of chunks. This would not include slashing, and would instead imply losing out on rewards during that period, until the validator turns amends the problem and re-joins the validator set again. This keeps the restaking protocol minimal and we believe this is a good set of trade-offs.
Rewards
Rewards can be implemented either fully onchain or as a merkle tree distributer.
For simple AVS mechanisms, it would be possible to build onchain reward claiming. For more complicated cases where you would want to reward each delegator and validator pro-rata, we believe it's more efficient to calculate the reward for each actor offchain, and then posting it as a merkle tree onchain for claiming. This is both gas efficient and simplifies the logic. Given that there are scenarios where the sequencer is centralized, the trade-offs in centralizing the rewards as well can make sense.
A production implementation should also batch rewards into chunks of e.g. every thousand, to reduce gas costs further for validators and delegators.
4.0 Specification
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.
ERC-6909
Overload's core contract Overload.sol
fully implements ERC-6909. This sets the basis for storing the balances for any ERC-20 token that is deposited into Overload and preserves ecosystem composability.
Methods
deposit()
Transfer amount
of an ERC-20 token
from owner
to Overload
.
MUST revert when the caller's balance for the token
is insufficient.
MUST increase unbonded
balance of the owner
and token
with amount
.
MUST return true
.
function deposit(address owner, address token, uint256 amount) external returns (bool);
withdraw()
Transfer amount
of an ERC-20 token
from Overload
to recipient
.
MUST revert when transferFrom
fails.
MUST decrease unbonded
balance of the owner
and token
with amount
.
MUST return true
.
function withdraw( address owner, address token, uint256 amount, address recipient ) external returns (bool);
delegate()
Delegate amount
of a ERC-6909 token
from owner
to target
.
MUST revert when amount
is greater than balance in bonded
plus unbonded
.
MUST increase bonded if total delegated amount
to consensus
is greater than bonded.
MUST create a new checkpoint for validator and increase by amount
for consensus
.
MUST create a new checkpoint for pool and increase by amount
for consensus
.
MUST return true
.
struct DelegateKey { address owner; address token; address consensus; address validator; uint256 amount; } function delegate(DelegateKey memory key) external returns (bool);