# Geode Document Hub

Everything about Staking.

#### <mark style="color:red;">Secure Code, Decentralized Library, Future of Staking.</mark>

A secure global standard that allows anyone to create and maintain **their own Permissionless, Trustless Staking Solution** on the Ethereum Blockchain.

The Staking Library is maintained by the Geode Finance Governance, and secured by pool owners via a Dual Governance.

## <mark style="color:purple;">A Challenging Mission</mark>

{% embed url="<https://vimeo.com/758855725>" %}

Linus Torvalds was bothered by the centralization and monopolization of the operating systems. So he created Linux.

Satoshi Nakamoto was bothered by the centralization and monopolization of traditional monetary systems. So he created Bitcoin.

*Do we stop now?*

## <mark style="color:purple;">Why Geode?</mark>

Geode is revolutionizing the understanding behind Staking Derivatives by granting **any centralized or decentralized** entities the ability to run their own solution **without intermediaries**.

* A standard for staking pools and derivatives.
* A standard for the communication between Node Operators and Staking Pools.

### Unlock Unlimited Potential.

Thanks to the Modular Architecture of the **Configurable Staking Pools,** everything about staking is within reach.

<figure><img src="/files/3NbLatN4KIqevPw4oD8T" alt=""><figcaption><p>Modular Architecture</p></figcaption></figure>

* Save the cost of maintenance on multiple levels.
* Provide better yield bearing mechanisms for your community.
* Increase your TVL by offering Liquid Staking.
* Integrate your own derivative into your products or create new products with it.
* Generate remarkable and sustainable revenue with a pool maintenance fee.
* Fully segregated staking, providing better security and enables you to perform KYC & AML
* Create auto-staking contracts!
* Stake and forget.

{% content-ref url="/pages/wjuUXSbPQC2Vbhf8CSqv" %}
[The Staking Library](/the-staking-library)
{% endcontent-ref %}

### Remove tail risk.

Third party Staking Derivatives expose tail risk to the whole staking ecosystem.

Geode allows any party to manage its own risk profile.

**Thanks to&#x20;**<mark style="color:purple;">**Contract Owned Staking Derivatives**</mark>**&#x20;you don't need the middleman anymore.**&#x20;

**Craft your own solution instead.**

<div align="center"><figure><img src="/files/fPCZSaJiOJc0vm1tTleb" alt=""><figcaption><p>Isolated risk.</p></figcaption></figure></div>

* Manage your risk profile by simply reaching out to Solo/Industrial Node Operators directly via our marketplace
* Have complete ownership of your staking pool, control the Withdrawal Contract and have total ownership over your funds

{% content-ref url="/pages/8al101kYMumrrAiepfDu" %}
[Operator Marketplace](/operator-marketplace)
{% endcontent-ref %}

## <mark style="color:purple;">Start Building!</mark>

Invest your time on improving your protocol, instead of building out your own Staking solution.

We got you on that:

* Geode Portal is secured by Dual Governance and Limited Upgradability!
* Guard your Withdrawal Contract with upgradeProposals!
* Automate your workflow with Maintainers!
* Build on top of your Staking Derivative with Interfaces!

{% content-ref url="/pages/UTUcBbx5mlct3FgSPNOD" %}
[Staking Pool Handbook](/avalanche-guides/staking-pool-handbook)
{% endcontent-ref %}

## <mark style="color:purple;">The Future of Geode</mark>

We aim to establish the best user experience for Stakers, Pool Owners, an d Node Operators.

We considered every little detail, and created a firm frame by utilizing a Modular Architecture.

**Now, it is time to build on top of it:**

* **More Interfaces**
* **Better Maintainers**
* **Improved Features**
* **Further Decentralization**&#x20;

{% content-ref url="/pages/D3ja8PPTsEV1vSTZ1JYi" %}
[Future of Geode](/key-concepts/future-of-geode)
{% endcontent-ref %}


# The Staking Library

Craft your own solution.

## Current State of Staking Derivatives

There are 3 main issues with the current design of the Staking Derivatives market.

* Monopolization
* Sustainability
* Trust

> All these issues are significantly related to each other. During our research we concluded that it all comes down to one: *<mark style="color:green;">Trust</mark>*.

{% hint style="success" %} <mark style="color:green;">Geode's</mark> <mark style="color:green;"></mark><mark style="color:green;">**Trustless**</mark> <mark style="color:green;"></mark><mark style="color:green;">and</mark> <mark style="color:green;"></mark><mark style="color:green;">**Scalable**</mark> <mark style="color:green;"></mark><mark style="color:green;">solution was designed to fix all of these issues!</mark>
{% endhint %}

#### To overcome them, we researched and improved our understanding further:

{% content-ref url="/pages/Et5Fgnw0LNGGUhrRqj4U" %}
[The Issue](/the-staking-library/the-issue)
{% endcontent-ref %}

## Staking Reimagined:

### An <mark style="color:purple;">Open Market</mark> Built on Top of a <mark style="color:green;">Permissionless</mark> <mark style="color:green;">Global Standard.</mark>

The market was disrupted when the first version of Permissionless Decentralized Exchanges were created. The risk of Centralized Exchanges is theoretically mitigated, since anyone is able to create a Contract Owned Liquidity Pool now.

#### Geode provides a Permissionless Staking Library that allows anyone to craft, create and maintain their own <mark style="color:purple;">trustless</mark> staking solution.

### Simple...

* Takes 1 Tx to create a staking pool.
* Allows choosing a subset of Node Operators, can easily change it afterwards.
* Every pool is segregated, thus the risk is isolated.
* Every validator is unique, thus the risk is isolated.
* Immutable token contract, securing the stakers' tokens.
* Geode Governance can not upgrade but only propose upgrades on unique instances of the library.

### … we don't need intermediaries anymore:

{% content-ref url="/pages/zCuqiEEeVq8BgVKCEquu" %}
[A Solution](/the-staking-library/a-solution)
{% endcontent-ref %}

## Learn how to utilize The Staking Library:

{% content-ref url="/pages/vBtJvmPwn59ItxKwb6mU" %}
[Staking Pool HandBook](/ethereum-guides/staking-pool-handbook)
{% endcontent-ref %}


# The Issue

## Monopolization

* Liquid Staking Infrastructures are no joke. They are very sensitive and require a lot of attention to detail. Even within the short period since Serenity Phase 0, we have witnessed multiple of them failing to deliver, mistakenly losing user funds or even rug pulls.

> Resulted in customers choosing trusted pools over smaller ones.

* Naturally, it costs a lot to build and maintain these products.

> Discouraged builders even more, resulting in less competition for the already established centralized and decentralized staking solutions.

* Finally, Liquid Staking Derivatives require a large amount of liquidity to ensure the "Price Peg" is maintained.

> Created an environment where it is near impossible to compete with established Protocols.

{% hint style="success" %} <mark style="color:green;">To solve the Monopolization issue:</mark>

* <mark style="color:green;">Solve the Sustainability issue.</mark>
  {% endhint %}

### Sustainability

A Liquid Staking Derivative (LSD) can grow fast in an unhealthy, speculative environment. It can acquire a big proportion of market-share, within a short period of time and with unsustainable incentives. Its fall is inevitable when the market rejects/forgets it.&#x20;

Because, idle assets spread better than derivatives...

**We understood that the Intermediary Staking Tokens (ERC20s) that are created by service providers, will not continuously provide better, unprecedented yields&#x20;**<mark style="color:blue;">**compared to the staking rewards.**</mark>&#x20;

This achievement requires an environment where there is a demand for the secondary asset. This, requires a monopoly, which is not healthy for the ecosystem.

{% hint style="success" %} <mark style="color:green;">To solve the Sustainability issue:</mark>

* <mark style="color:green;">Create a global standard for Staking Derivatives.</mark>
* <mark style="color:green;">Solve the Trust issue between parties.</mark>
  {% endhint %}

### Trust

First-gen Derivatives are created and managed by Centralized Staking Pools. As a result, it can be assumed that "trust" being issued to third parties was inevitable. This however, created a tail risk threatening the very foundation of decentralization.

{% hint style="danger" %} <mark style="color:red;">All these points are susceptible to a single-point of failure.</mark>
{% endhint %}

* Upgradable Contracts:

> One can not have immutable implementations in an environment where everything changes rapidly. But it is also not acceptable that a "Withdrawal Contract" can be held prisoner by someone with more than 50% of a governance token.

* Node Operator Management:

> Currently, it is not possible to force a validator to unstake. If a Node Operator chooses to keep them going, there is nothing a derivative can do.

* 3rd Party Risks:

> When a LSD is onboarded to a new protocol, that protocol becomes susceptible to the <mark style="color:red;">tail risk</mark>. **The impact of failure is not isolated, but rather spreads further.**


# A Solution

<figure><img src="/files/3NbLatN4KIqevPw4oD8T" alt=""><figcaption><p>Portal, gETH and Withdrawal Contracts work together to ensure a global standard.</p></figcaption></figure>

## An <mark style="color:purple;">Open Market</mark> Built on Top of a <mark style="color:green;">Permissionless</mark> <mark style="color:green;">Global Standard.</mark>

1. Geode's Staking Library utilizes an immutable token that is called gETH. It is the internal **database of our Trustless Staking Derivatives.**

* The **risk** associated with different staking derivatives are **isolated**.

2. These derivatives are maintained by **Configurable Staking Pools**.

* These pools are **permissionless.** They can be created by **any centralized or decentralized entities, and even solo users**.

3. Staking Pools can easily work with any subset of Permissioned and Permissionless Node Operators, via the **Operator Marketplace**.

* These Pools and Marketplace are hosted within a smart contract called **Geode Portal**.

4. Operators and Pools are unique, they are not pooled.

* The marketplace **regulates itself** with healthy competition.

5. Portal utilizes a **Modular approach** on Maintainers, Interfaces, Whitelists, Liquidity, etc.

* Nothing is decided. Things are customizable. **Everything is possible**.

6. Portal defines the interactions between *users and pools*, and *pools and operators*.

* An **improved user experience** for everyone, without sacrificing any possible features.

7. Validators are **unique and immutable** after creation.

* Changing associated parameters, such as fees, doesn't affect the previously created validators.&#x20;

8. Fees are charged after a validator's withdrawal.

* **Protecting the stakers** until the previously agreed deal is over.

9. When a validator is created, Portal no longer holds any ownership on the pooled funds.

* The Portal is upgradable, but guarded with a **Dual Governance**.

10. **Withdrawal Contracts** are the "owners" of the validators.&#x20;

* Every staking pool has a unique Withdrawal Contract that is guarded by the Pool Owner.

11. Trustlessness and Scalability are secured for future implementations, ensuring future staking innovations can be implemented.&#x20;

* To make things like Synthetic Minting, Dynamic Withdrawals, etc. possible, Geode provides a bound liquidity pool as well.


# Operator Marketplace

Choose your own operators.

We've learned about the Global Standard that Geode has created to establish a trustless marketplace between Staking Pools and Node Operators:

{% content-ref url="/pages/wjuUXSbPQC2Vbhf8CSqv" %}
[The Staking Library](/the-staking-library)
{% endcontent-ref %}

Now, let's take a look at the underlying mechanism to see how this marketplace operates.&#x20;

## An Open Marketplace

<figure><img src="/files/BWMdcH9rTrzNFw16pPI3" alt=""><figcaption></figcaption></figure>

#### Currently, there are 2 parties in this marketplace:&#x20;

* Configurable Staking Pools&#x20;
* Node Operators

{% hint style="success" %} <mark style="color:green;">In an open market that is regulated well, one's benefit is everyone's benefit.</mark>
{% endhint %}

### A validator's Lifecycle

{% content-ref url="/pages/E0XOdijxPxVbc4Shq5aR" %}
[A Validator's Lifecycle](/operator-marketplace/a-validators-lifecycle)
{% endcontent-ref %}

### Regulating the Marketplace

{% content-ref url="/pages/EPfcOKTGOHajyq1Qd52D" %}
[Regulating the Marketplace](/operator-marketplace/regulating-the-marketplace)
{% endcontent-ref %}

## 1. Configurable Staking Pools

| Profit                           | Expense  |
| -------------------------------- | -------- |
| Pool maintenance fee, up to 10%. | Gas cost |

### Staking pools are permissionless.&#x20;

Anyone can create a staking pool with Portal.

During the creation process, a pool is configured with certain options like maintainer, interface, maintenance fee, etc.&#x20;

Some of these configurations can be changed later by the controller.&#x20;

### Local and Global Security&#x20;

When a staking pool is created via Geode's Portal, it uses it's own isolated storage. This storage is protected from governance attacks by **Dual Governance**.&#x20;

After a validator is created, Portal holds no ownership on the pooled funds. It is simply transferred to a unique **Withdrawal Contract** guarded by the pool's controller.

#### Pool Maintenance Fee

{% content-ref url="/pages/rIGZWSJishlr5v5VVXf9" %}
[Maintenance Fee](/operator-marketplace/maintenance-fee)
{% endcontent-ref %}

## 2. Permissioned Node Operators

| Profit                            | Expenses              |
| --------------------------------- | --------------------- |
| Up to 10% of the staking rewards. | Operational expenses. |
| Up to 10% of the MEV.             | Gas cost.             |
| Up to 10% of the Block Rewards.   | Infrastructure cost.  |

Permissioned Node Operators are allowed to create and operate validators on behalf of the staking pools without any collateral.

#### Onboarding New Operators to the Marketplace

{% content-ref url="/pages/VjqGpLYmMAQ3zzukicpP" %}
[Onboarding New Operators](/operator-marketplace/onboarding-new-operators)
{% endcontent-ref %}

## 3. Permissionless Node Operators

{% hint style="danger" %} <mark style="color:red;">This topic is currently under construction. Check out the Degen Operators (WIP) for further information.</mark>
{% endhint %}


# A Validator's Lifecycle

<figure><img src="/files/D9deIpxchEElfEnZsGbL" alt=""><figcaption></figcaption></figure>

The controller of a Staking Pool can choose any set of Node Operators to work with.

* Staking Pools give an **allowance** to the Node Operators.&#x20;

{% hint style="info" %}
**Allowance** represents the maximum number of validators to be created.
{% endhint %}

* Node Operators propose a validator with specific details.
* Every proposal requires 1 ETH from Operator, **which will be reimbursed upon activation.**

{% hint style="info" %}
Pool Maintenance Fee, Operator Fee, and validator period is set on proposal.&#x20;

These parameters can not be changed afterwards.
{% endhint %}

* Oracle approves these proposals.
* Node Operators move 32 ETH from the staking pool to the approved validator.
* Validators are exited within the validator period.
* Fees are distributed after the validator withdrawal. However, with partial claiming

{% hint style="success" %} <mark style="color:green;">Staking Pool can change the allowance at any given point.</mark>&#x20;

<mark style="color:green;">As old validators are exited, their stake is redistributed as per the allowance.</mark>
{% endhint %}


# Maintenance Fee

Pool Owners are responsible from various tasks, such as:

* Managing the pool variables, like fee and maintainer.
* Choosing the operator subset.
* Securing the Withdrawal Contract by upgrading it whenever it is necessary.

In return, they can charge <mark style="color:purple;">**up to 10%**</mark> of the staking yield.

#### It is important to note that the maintenance fee is not a staking-as-a-service fee.

{% hint style="success" %}
Geode charges **0% staking-as-a-service fee,** and can not change this until March 2025 without the approval of Portal's Senate.
{% endhint %}


# Onboarding New Operators

### Onboarding a permissioned operator is a simple process.

1. New Operators are proposed by Geode Governance.&#x20;
2. Senate approves the onboarding.
3. Initial parameters are set by the Operator's Owner by calling `initiateOperator()`.
4. The Operator is active, and can start proposing new validators for any pool created with The Staking Library.

Learn more about the Dual Governance:

{% content-ref url="/pages/v9gOWBJ7h1IFN3aewcPa" %}
[Dual Governance](/key-concepts/portal/dual-governance)
{% endcontent-ref %}


# Regulating the Marketplace

#### Simply it **regulates itself with a healthy competition.**&#x20;

Node Operators can set a fee up to 10% for their services.

{% hint style="success" %}
Contrary to other staking pools, Operators collect their fee according to the performance of their validators; encouraging them to be more profitable.
{% endhint %}

Any pool can work with any Node Operator, w*ith minimal disturbance*. However, the pool controllers should consider some parameters, such as:

* Fee
* Validator Period
* Number of Total Validators
* Past Performance
* Country/Regulation

### "Minimal Disturbance"

#### There are some ground rules to protect the all parties from each other.

* There is a 3 day cooldown period when a pool maintenance fee is changed.
* There is a 3 day cooldown period when an operator fee is changed.
* There is a 3 day cooldown period when a validator period is changed.
* There is a 14 day isolation period for faulty or malicious Node Operators, called prison:

{% content-ref url="/pages/OoraH2lmR3OqQiymGmK4" %}
[Prison](/operator-marketplace/regulating-the-marketplace/prison)
{% endcontent-ref %}


# Prison

#### Prison isolates the Node Operators from the Marketplace, in case they act in a faulty or malicious manner:

* Invalid validator proposal.
* Not withdrawing validator funds before the expected exit time.
* Not routing the block rewards, or MEV rewards to the Withdrawal Contract. &#x20;

The Prison Sentence for any of these infractions is 14 days.

{% hint style="info" %}
In the case that a Node Operator with a good track record is imprisoned for an honest mistake, Governance can bail out the imprisoned Operator early.
{% endhint %}

{% hint style="info" %}
Geode Governance can also imprison a Node Operator from the Marketplace, which is  indefinitely effective.
{% endhint %}

> **What happens when an operator is imprisoned?**
>
> 1. Can not propose new validators.
> 2. Can not stake to beacon chain for previously accepted validator proposals.
> 3. Can not change their parameters such as fees, validatorPeriod...
> 4. Can not access to `wallet`, effectively, can not claim their rewards.


# Staking Derivatives

### Simple.

When a user stakes their collateral, they are given a corresponding amount of a derivative.

The sole purpose of this derivative is to increase its value over time, representing the yield acquired from the staking operations.

After the Shanghai Upgrade on Ethereum goes live, these derivatives can be used to claim the corresponding Ether.

Thus, completing its mission of rewarding the staker.

#### Not so simple.

Unfortunately, Staking Derivatives differ tremendously from each other.

* **Status of the Derivative**: This can be a number in a database, an upgradable ERC20, an immutable and open-source one, etc.
* **Security of the Principal**: Withdrawal keys can be lost, databases can be hacked, contracts can be attacked.&#x20;
* **Quality of the Pool Operations:** it can be expensive to maintain your smart contracts in an ever-changing environment.
* **Quality of the Node Operations**: Decentralized Operators, Industrial Operators, Pooled Operators, etc.
* **The Percentage of the Backed Collateral**: Some derivatives allow synthetic minting, meaning it isn't even 100% backed, while others are backed more than 100%.
* **Legal Obstacles:** Obviously an increasing problem.

{% hint style="info" %}

### "Liquid" Staking Derivatives

Staking Derivatives that are represented with ERC20 tokens, which can then be used within DeFi.&#x20;

Can be issued by anyone, without any premise.
{% endhint %}

## G-Derivatives: gETH and gAVAX

### Establishing a Secure, Global Standard.

#### G-derivatives are <mark style="color:purple;">**immutable ERC-1155 contracts**</mark> that are utilized for internal accounting within Geode's staking library.

The Staking Library defines it's operations by way of this ERC-1155 contract.&#x20;

Since it is immutable, this contract ensures the underlying balance of the staked asset without any possibility of alteration.

Users, and approved contracts, can manage and transfer their tokens directly or via interfaces.

With a little magic, they can even be used in other forms; such as ERC20!

Thus allowing any Staking Derivative to be a <mark style="color:purple;">Liquid</mark> Staking Derivative.

{% hint style="success" %}
Using a single ERC1155, instead of multiple ERC20s, provides better DeFi compatibility in the future. For example, A DeFi app can onboard all Geode-hosted derivatives at once, without tracking and updating multiple token addresses.
{% endhint %}

## Let's dive in

G-Derivatives are *Databases* of <mark style="color:purple;">Balances</mark> and <mark style="color:purple;">Prices</mark> with extra <mark style="color:purple;">Scalability (interfaces).</mark>

<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fer1zzrzebhprc2IWX2y9%2Fuploads%2FrD3jpCVkEu0b0sOf5ktZ%2FgDer.png?alt=media&#x26;token=a1c3cda2-1bd3-4d1a-8714-86b5069eb9bc" alt=""><figcaption></figcaption></figure>

{% content-ref url="/pages/MV8KTeN5UvIdftSC9D7P" %}
[G-Derivatives](/key-concepts/staking-derivatives/g-derivatives)
{% endcontent-ref %}


# G-Derivatives

### G-Derivatives are *Databases* of <mark style="color:purple;">Balances</mark> and <mark style="color:purple;">Prices</mark> with extra <mark style="color:purple;">Scalability (interfaces).</mark>

<figure><img src="/files/JulC0qj7i5HOmLLU8Vp1" alt=""><figcaption><p>a special ERC1155 contract</p></figcaption></figure>

## <mark style="color:purple;">Balances</mark>

Acts as a **Database** for the amount of staked Ether that is represented by multiple Maintainers.

Balances for the depositors are tracked with a predetermined ID. IDs are the main separators of the different types of gETH, thus different maintainers.&#x20;

```solidity
mapping(uint256 => mapping(address => uint256)) private _balances;
```

{% hint style="warning" %}
Balances can be directly changed by **Interfaces.**
{% endhint %}

{% hint style="success" %}
Anyone can disable the access of the interfaces by simply using the **avoidInterfaces** function!
{% endhint %}

## <mark style="color:purple;">Pricing</mark>

The balance of users, doesn’t change while the amount of the underlying tokens increase over time thanks to **Staking Rewards**.

Every different ID of gETH has a different *\_pricePerShare* value.&#x20;

```solidity
mapping(uint256 => uint256) private _pricePerShare;
```

### **\_pricePerShare**

Basically, a variable that represents the equivalent of 1 gETH, in terms of underlying Ether.&#x20;

*\_pricePerShare* is used by Geode on minting / burning operations, *and* can be used by other contracts with peace of mind.&#x20;

It's value is updated by an Oracle.

{% content-ref url="/pages/mSbBs4vOrv18Q1994rDO" %}
[Oracles](/key-concepts/oracles)
{% endcontent-ref %}

{% hint style="info" %}
The **\_pricePerShare** parameter is one of the key components that supports DeFi.
{% endhint %}

## <mark style="color:purple;">Interfaces</mark>

> **Interfaces** are one of the most important concepts introduced by Geode.fi.

ERC-1155 tokens are not compatible within the DeFi ecosystem, thus they need to be mutated for public usage.&#x20;

**Every Derivative has a different use-case, depending on the represented Protocol, therefore it doesn’t come with a preset implementation.**

Interfaces are external contracts used to manage the underlying assets for different purposes. Unlocking infinite flexibility!

{% hint style="success" %}
There can be multiple Interfaces for one gETH ID.

However, Portal doesn't currently allow that.
{% endhint %}

```solidity
mapping(uint256 => mapping(address => bool)) private _interfaces;
```

{% hint style="success" %}
Transactions that are conducted with Interfaces can bypass the [ERC1155 requirements](https://eips.ethereum.org/EIPS/eip-1155#erc-1155-token-receiver), while other non-compatible contracts cannot receive them.
{% endhint %}

```solidity
  function _doSafeTransferAcceptanceCheck(...) private {
    if (to.isContract() && !isInterface(operator, id)) 
    {
    ...
    }
```

#### Learn more about other cool gETH functionalities:

{% content-ref url="/pages/MsaaugV6L8LFYtBZIQuv" %}
[gETH vs gAVAX](/key-concepts/staking-derivatives/g-derivatives/geth-vs-gavax)
{% endcontent-ref %}

#### See our case studies about some interfaces here: &#x20;

{% content-ref url="/pages/NMzvFXpWn6oyM78TmdkQ" %}
[Current Interfaces](/key-concepts/permissionless-configurable-staking-pools/current-interfaces)
{% endcontent-ref %}


# gETH vs gAVAX

#### Improvements to G-Derivatives resulted in some differences between these two ERC1155 contracts.

## <mark style="color:blue;">Avoiders</mark>

gAVAX is developed with the assumption that the staker would choose which Staking Pool to stake with. However, it is not hard to see that when people start building on top of Geode, they might want to avoid this assumption.&#x20;

*Avoiders* simply prevent the effect of any Interfaces on their g-derivative balance. For example, they can not use their token as an ERC20, as they can not use the ERC20-interface to communicate with the ERC1155 contract.&#x20;

```solidity
/**
* @notice Mapping of user addresses who chose to restrict the usage of interfaces
**/
mapping(address => bool) private _interfaceAvoiders;

function isAvoider(address account) public view virtual returns (bool) {
   return _interfaceAvoiders[account];
}

/**
* @notice One can desire to restrict the affect of interfaces on their gETH,
* this can be achieved by simply calling this function
* @param isAvoid true: restrict interfaces, false: allow the interfaces,
**/
function avoidInterfaces(bool isAvoid) external virtual {
   _interfaceAvoiders[_msgSender()] = isAvoid;
   emit InterfacesAvoided(_msgSender(), isAvoid);
}
```

{% hint style="info" %}
gAVAX lacks this improvement.
{% endhint %}

## <mark style="color:blue;">Denominator</mark>

The ERC1155 standard does not support "decimals" natively, as ERC20 does. However, both "pricePerShare" and "Balances" need to be denominated in some way. As our auditors warned us, we did not use decimals key as it is already reserved.

```solidity
uint256 private constant _denominator = 1 ether;

/**
* @notice a centralized denominator = 1e18
*/
function denominator() external view virtual returns (uint256) {
    return _denominator;
}

```

{% hint style="info" %}
gAVAX lacks this improvement.
{% endhint %}

## <mark style="color:blue;">priceUpdateTimestamp</mark>

Some DeFi applications, such as a DWP, can be improved with the date of the latest price update from Telescope. It is logical to keep this data here, instead of Portal.

```solidity
function priceUpdateTimestamp(uint256 id) external view returns (uint256) {
    return _priceUpdateTimestamp[id];
}

function _setPricePerShare(uint256 _price, uint256 _id) internal virtual {
    _pricePerShare[_id] = _price;
    _priceUpdateTimestamp[_id] = block.timestamp; // added this line
}
```

{% hint style="info" %}
gAVAX lacks this improvement.
{% endhint %}


# Portal

## The Staking Gateway

**Geode Finance utilizes a Modular Architecture, making things&#x20;**<mark style="color:purple;">**safer**</mark>**&#x20;for stakers, and&#x20;**<mark style="color:purple;">**easier**</mark>**&#x20;for Pool Providers**.

<figure><img src="/files/3NbLatN4KIqevPw4oD8T" alt=""><figcaption></figcaption></figure>

#### The most crucial component is The Portal.

* Creation and maintenance of the configurable staking pools.
* Minting new tokens.
* Securing the Ether until it is staked in a validator.
* Onboarding new Operators to the marketplace.
* Management and regulation of the Operator marketplace.
* Allowing new functionalities to be implemented with ease.
* Securing it's own codebase from Governance.
* Various tasks of Oracle.

#### To achieve these tasks and improve the staking user experience for everyone:

1. We need to make sure every Staking Pool and Node Operator is isolated in a well organized storage space. We can also add new functionalities with ease:

{% content-ref url="/pages/f6aPTl3GvoGb7XFJpfTl" %}
[Isolated Storage](/key-concepts/portal/isolated-storage)
{% endcontent-ref %}

2. We need to define the different parties that will use this storage space, in a secure and generalized way. Thereby preventing any third party access:

{% content-ref url="/pages/v9gOWBJ7h1IFN3aewcPa" %}
[Dual Governance](/key-concepts/portal/dual-governance)
{% endcontent-ref %}

3. We need to define the ownership of the funds explicitly, in a way that Portal doesn't hold any responsibility after validator creation:

{% content-ref url="/pages/fajxkHebpiVLDHZHMN44" %}
[Withdrawal Contracts](/key-concepts/withdrawal-contracts)
{% endcontent-ref %}

4. We need to create an upgradability pattern **for both Portal and Withdrawal Contracts**, so we can prevent Governance from changing these mechanisms inconveniently or maliciously.

{% content-ref url="/pages/L3X2sxZ3SIUb60lPc3zN" %}
[Limited Upgradability](/key-concepts/portal/limited-upgradability)
{% endcontent-ref %}

5. Now, we can implement The Staking Library. It should manage and provide a wide variety of features for the staking derivatives:

{% content-ref url="/pages/l3JsCfbAgizvErNll8Jz" %}
[Permissionless Configurable Staking Pools](/key-concepts/permissionless-configurable-staking-pools)
{% endcontent-ref %}

6. We need to have a marketplace for Pools and Operators to communicate easily:

{% content-ref url="/pages/8al101kYMumrrAiepfDu" %}
[Operator Marketplace](/operator-marketplace)
{% endcontent-ref %}

6. We need to have a generalized approach on price updates, that supports infinitely many staking pools:

{% content-ref url="/pages/a6KgOb1EpyxvB8IaMCjD" %}
[Telescope Ether](/key-concepts/oracles/telescope-ether)
{% endcontent-ref %}


# Isolated Storage

<figure><img src="/files/klybTiqX7ls49q6byaxb" alt=""><figcaption></figcaption></figure>

#### Portal is designed to host multiple parties without them affecting each other's storage space under any condition.

## DataStoreUtils Library

DataStore is a storage management tool designed to create a safe and scalable storage layout with the help of <mark style="color:purple;">**IDs**</mark> and <mark style="color:purple;">**KEYs**</mark>.&#x20;

Creating a sustainable development environment, even in ever changing technology.

#### With DataStore, Portal achieves 3 goals:

* A Dynamic Struct that is defined with the "TYPE" parameter, that can hold any amount of parameters, instead of only 16 *(max # of variables a struct can hold in Solidity).*
* Make it very easy to build new classes that have different parameters and functionalities, without altering the codebase.
* Separating the storage space of the contract, allowing Portal to maintain multiple parties without any friction.
* Ensuring the variable types: uint, address, and bytes.

## <mark style="color:purple;">Deep Dive</mark>

Storage Management library for dynamic structs based on data types.

#### The DataStore Struct

{% code title="DataStoreLib.sol" %}

```solidity
  struct DataStore {
    // type[0,1,2,3...] => ID list
    mapping(uint256 => uint256[]) allIdsByType;
    // keccak(id, key) => data
    mapping(bytes32 => uint256) UintData;
    mapping(bytes32 => bytes) BytesData;
    mapping(bytes32 => address) AddressData;
  }
```

{% endcode %}

Within the struct, there are 4 different mappings to serve different types of storage.

#### Generating an ID and Key

{% code title="" %}

```solidity
  function generateId(
    bytes memory NAME,
    uint256 TYPE
  ) internal pure returns (uint256 id) {
    id = uint256(keccak256(abi.encodePacked(NAME, TYPE)));
  }
  
  function getKey(
    uint256 _id,
    bytes32 _param
  ) internal pure returns (bytes32 key) {
    key = keccak256(abi.encodePacked(_id, _param));
  }
```

{% endcode %}

* IDs should be unique.
* Keys are bound to IDs, ensuring 2 IDs with same parameters can not share a storage slot.
* TYPEs are explicit, 4 representing Operators, 5 representing pools, and so on...
* NAMEs should be guarded within the same TYPE, meaning there can only be 1 entity with a given NAME and TYPE.

#### Sample Write Operation

{% code title="DataStoreLib.sol" %}

```solidity
   function writeUintForId(
    DataStore storage self,
    uint256 _id,
    bytes32 _key,
    uint256 data
  ) public {
    self.UintData[keccak256(abi.encodePacked(_id, _key))] = data;
  }
  
```

{% endcode %}

Basically, it takes the id and key pair encoded, secures a slot in the mapping for the id & key pair, and assigns the data to slot in the UintData mapping where the DataStore struct is taken as a storage argument. Every write operation in the library follows the same procedure.

#### Sample Read Operation

{% code title="DataStoreLib.sol" %}

```solidity
 function readBytesForId(
    DataStore storage self,
    uint256 _id,
    bytes32 _key
  ) public view returns (uint256 data) {
    data = self.BytesData[keccak256(abi.encodePacked(_id, _key))];
  }
```

{% endcode %}

This is also a typical read operation in the library, getting the data from the assigned slot with the given id and key pair, and returning the data publicly with the view restriction.

## <mark style="color:purple;">Reading the DataStore Through Portal</mark>&#x20;

Portal has a public endpoint for the view functions of the DataStore.&#x20;

This provides access to all data stored in the Portal, without needing to go through the docs, and scan through all the functions 🙂

<pre class="language-solidity" data-title="Portal.sol"><code class="lang-solidity"><strong>function generateId(
</strong>    string calldata _name,
    uint256 _type
  ) external pure virtual override returns (uint256 id) {
    id = uint256(keccak256(abi.encodePacked(_name, _type)));
  }
</code></pre>

* *generateId()* Mimics the DataStore.generateId for string inputs.

{% code title="Portal.sol" %}

```solidity
  function getKey(
    uint256 id,
    bytes32 param
  ) external pure virtual override returns (bytes32 key) {
    return DataStoreUtils.getKey(_id, _param);
  }
```

{% endcode %}

* An example key generation can be:

```javascript
Portal.getKey(Portal.generateId("poolName", 5), getBytes32("surplus"));
Portal.getKey(Portal.generateId("operatorName", 5), getBytes32("totalValidators"));
```

#### Reading Simple Data

* An example read operation:

```javascript
Portal.readUintForId(Portal.generateId("poolName", 5), getBytes32("surplus"));
```

\---

{% code title="Portal.sol" %}

```solidity
  function readUintForId(
    uint256 id,
    bytes32 key
  ) external view virtual override returns (uint256 data) {
    data = DATASTORE.readUintForId(id, key);
  }

  function readAddressForId(
    uint256 id,
    bytes32 key
  ) external view virtual override returns (address data) {
    data = DATASTORE.readAddressForId(id, key);
  }

  function readBytesForId(
    uint256 id,
    bytes32 key
  ) external view virtual override returns (bytes memory data) {
    data = DATASTORE.readBytesForId(id, key);
  }
```

{% endcode %}

#### Reading an array&#x20;

* Currently only arrays are: `validators` and `interfaces`
* &#x20;Getting length of an array:

```javascript
Portal.readUintForId(Portal.generateId("poolName", 5), getBytes32("validators"));
```

* An example read operation on arrays:

```javascript
Portal.readUintForId(Portal.generateId("poolName", 5), getBytes32("validators"), 3);
```

\---

{% code title="Portal.sol" %}

```solidity
function readUintArrayForId(
    uint256 id,
    bytes32 key,
    uint256 index
  ) external view virtual override returns (uint256 data) {
    data = DATASTORE.readUintArrayForId(id, key, index);
  }

  function readBytesArrayForId(
    uint256 id,
    bytes32 key,
    uint256 index
  ) external view virtual override returns (bytes memory data) {
    data = DATASTORE.readBytesArrayForId(id, key, index);
  }

  function readAddressArrayForId(
    uint256 id,
    bytes32 key,
    uint256 index
  ) external view virtual override returns (address data) {
    data = DATASTORE.readAddressArrayForId(id, key, index);
  
```

{% endcode %}


# Dual Governance

## Building on top of the Isolated Storage

#### We learned that DataStore keeps different entities in isolated storage slots with different IDs.&#x20;

However, this functionality is nothing to be excited about without a mechanism to enforce this logic on protocol and contract upgrades.

#### Geode manages crucial parts of it's operation with 2 step verification:

1. Governance Proposals
2. Senate Approvals

This setup creates another safeguard for the users of The Staking Library.

## Proposals

A proposal is Geode Governance offering a change within the protocol to the Senate.&#x20;

Every proposals isolates an ID for DataStore.

After the Controller is chosen, no one else can touch to the given storage ID.

<figure><img src="/files/Kid7sGQI2BPLVNvtZwiw" alt=""><figcaption></figcaption></figure>

{% code title="GeodeUtilsLib.sol" %}

```solidity
  struct Proposal {
    address CONTROLLER;
    uint256 TYPE;
    bytes NAME;
    uint256 deadline;
  }
```

{% endcode %}

A Proposal has 4 parameters:

* **TYPE**: separates the proposals and related functionality between different ID types.
* **NAME**:important for ID generation through `DataStore.generateId()`
* **CONTROLLER**: the address that refers to the change that is proposed by given proposal ID.&#x20;
  * &#x20;This slot can refer to the controller of an id, a new implementation contract, a new Senate etc.
* **deadline**: refers to last timestamp until a proposal expires.

{% hint style="info" %}
All TYPEs are reserved as `ID_TYPE` within  [`globals.sol`](/developers/live-contracts/ethereum-v2/portal.sol/globals.sol)`.`
{% endhint %}

#### **There can be more TYPE reservations in the future.**

<table><thead><tr><th width="120">ID_TYPE</th><th>CONTROLLER</th></tr></thead><tbody><tr><td>0</td><td><mark style="background-color:red;">NONE -unused</mark></td></tr><tr><td>1</td><td><mark style="color:green;">new senate address</mark></td></tr><tr><td>2</td><td><mark style="color:blue;">new implementation contract for Portal</mark></td></tr><tr><td>3</td><td><mark style="background-color:red;">GAP - unused</mark></td></tr><tr><td>4</td><td><mark style="color:green;">Controller of a Operator</mark></td></tr><tr><td>5</td><td><mark style="color:purple;">Controller of a Pool</mark></td></tr><tr><td>21</td><td><mark style="color:blue;">Module: Withdrawal Contracts</mark></td></tr><tr><td>31</td><td><mark style="color:blue;">Module: gETH interfaces</mark></td></tr><tr><td>41</td><td><mark style="color:blue;">Module: Liquidity Pool</mark></td></tr><tr><td>42</td><td><mark style="color:blue;">Module: Liquidity Pool Token</mark></td></tr></tbody></table>

### Governance

Currently, Governance is an internal ERC-20 token that is only owned by Geode Finance Developers and Treasury.

This internal ownership is a needed step to eliminate the risk of some attacks like Governance tak-over.

In the future, the Governance of Geode is supposed to be decentralized with the distribution of these tokens.

### Senate

Currently, Senate is a Multisig of Geode developers.&#x20;

But GeodeUtils Library includes a logic for changing the Senate, as well as an Election for it.

TYPE 1 proposals stand for Senate Elections.

However, the future of Senate will not be decided by elections, but with an other approach:

#### A Decentralized Senate with a weighted vote distribution:

{% content-ref url="/pages/BuwGF9OGVcDub71pHNXi" %}
[Quadratic Weighted Senate (DRAFT)](/key-concepts/future-of-geode/further-decentralization/quadratic-weighted-senate-draft)
{% endcontent-ref %}

### Limited Upgradability

*TYPE 2* proposals ensure Limited Upgradability on both Portal and Withdrawal Contracts.

{% content-ref url="/pages/L3X2sxZ3SIUb60lPc3zN" %}
[Limited Upgradability](/key-concepts/portal/limited-upgradability)
{% endcontent-ref %}

### Onboarding Operators

*TYPE 4* proposals stands for onboarding a new Node Operator to the Marketplace:

page link

### New Withdrawal Contract, gETH interface or Liquidity Pools

Other *TYPEs* like *21, 31* etc. stands for other important parameters of Portal like default Liquidity Pool or withdrawal Contract implementation.


# Limited Upgradability

## Global Trustlessness

Geode Finance cannot upgrade the source code of it's contract infrastructure without the approval of their users.&#x20;

This creates a more secure implementation and prevents any harmful events that can be caused by a Governance Token, thus removes the trust between users and the developers.

{% hint style="success" %}

#### <mark style="color:green;">Limited Upgradability is used within both Portal and Withdrawal Contract.</mark>

{% endhint %}

### Upgrading the Portal

1. A new implementation address is proposed by Governance.
2. Proposal can be approved by Senate.
3. Upgrade is now allowed.

### Upgrading Withdrawal Contracts

1. New Withdrawal Contract is proposed by the Governance with the TYPE of `WITHDRAWAL_CONTRACT_UPGRADE`
2. Senate Approves the new Withdrawal Contract. From now on Portal references to the new implementation address
3. Then, anyone can call `fetchUpgradeProposal`:
   1. `fetchUpgradeProposal,` notifies the Portal.
   2. Portal proposes a new implementation on Withdrawal Contract with the TYPE of `UPGRADE`.
   3. Withdrawal Contracts pointing the old implementation enters into **Recovery Mode.**
   4. Owners can approve the proposal and migrate to a new implementation, exiting from the Recovery Mode.

{% hint style="success" %}
If the `fetchUpgradeProposal` **is called by the Owner, the proposal is also automatically approved.**
{% endhint %}


# Permissionless Configurable Staking Pools

We learned how The Staking Library provides a firm foundation for Staking operations, and allows anyone to have a Staking Derivative:

{% content-ref url="/pages/wjuUXSbPQC2Vbhf8CSqv" %}
[The Staking Library](/the-staking-library)
{% endcontent-ref %}

Then, we learned how the Operator Marketplace makes staking operations much easier, and increases the user experience for both Pool Owners and Node Operators:

{% content-ref url="/pages/8al101kYMumrrAiepfDu" %}
[Operator Marketplace](/operator-marketplace)
{% endcontent-ref %}

Now, lets take a look at the Staking pools, and the superpowers of their Modular Architecture.

## One Transaction To Rule Them All!

During the same transaction for creation of a staking pool, the following functionalities can be configured:

### Private Pools - optional

* If a pool is Public, everyone can use it.&#x20;
* Private pools are only available to their owners and other whitelisted addresses.
* Pool owners can make pools public or private as they wish.
* Any contract with a `isWhitelisted()` function can be used by the Private Pools.

{% content-ref url="/pages/ee1qPNg9mYqC5t04mRUo" %}
[Private Pools and Whitelisting](/ethereum-guides/staking-pool-handbook/private-pools-and-whitelisting)
{% endcontent-ref %}

### Interfaces - optional

* **If you don't need an ERC20 for example, a pool can operate without an interface.**
* While gETH allows multiple interfaces, Portal only allows 1 interface per derivative for security reasons.
* Interfaces should be created on the initiation process. Currently, an interface **can** not be added after the pool initiation for security reasons.
* New interfaces require the approval of the Senate.
* Any interface can be chosen from the list below:

{% content-ref url="/pages/NMzvFXpWn6oyM78TmdkQ" %}
[Current Interfaces](/key-concepts/permissionless-configurable-staking-pools/current-interfaces)
{% endcontent-ref %}

### Maintainers - optional

* **If you don't have a very active pool, you can choose your operators without a maintainer.**
* Pool tasks such as management of the Operators can be automated through maintainers.
* Adding a maintainer is not a security risk, any contract or address can be chosen as a maintainer. However, it is always best to DYOR.
* Maintainers can not steal Pool fees or Pool funds.

{% content-ref url="/pages/pr7YAwNKRplvqovwxwxF" %}
[Maintainers](/key-concepts/permissionless-configurable-staking-pools/maintainers)
{% endcontent-ref %}

### Bound Liquidity Pools - optional

* **If you don't need liquidity, your pool doesn't need a bound liquidity pool.**
* **You can always change your mind later.**

{% content-ref url="/pages/D6utzcdejMctLxSHh3Qr" %}
[Bound Liquidity Pools](/key-concepts/bound-liquidity-pools)
{% endcontent-ref %}


# Current Interfaces

{% hint style="success" %}

#### This is the list of currently available, secure, and audited interfaces.&#x20;

This list will be updated as new interfaces are added to Portal.
{% endhint %}

## ERC20

#### Interface ID:

<mark style="color:purple;">52080999241024020947914008153249669221696720177727983794039099715751453236701</mark>&#x20;

#### Allowing any derivative to be liquid.

{% content-ref url="/pages/Bo0BQGMUIbBFQBEEna1a" %}
[ERC20InterfaceUpgaradable.sol](/developers/live-contracts/ethereum-v2/interfaces/erc20interfaceupgaradable.sol)
{% endcontent-ref %}

## ERC20Permit

#### Interface ID:

<mark style="color:purple;">50490156267966951633552038357636683005958029756062533881506474161986935451665</mark>&#x20;

Implementation of the ERC20Interface with Permit extension allowing approvals to be made via signatures.

{% content-ref url="/pages/WKUY1U7pSAGFpGXBqhNk" %}
[ERC20InterfacePermitUpgradable.sol](/developers/live-contracts/ethereum-v2/interfaces/erc20interfacepermitupgradable.sol)
{% endcontent-ref %}

## ERC20Rebasing

#### <mark style="color:red;">Currently not available - WIP</mark>

Instead of a value accrual ERC20 token, you can use a rebasing token with increasing balances on each price update.

## ERC20RebasingPermit

#### <mark style="color:red;">Currently not available - WIP</mark>

Implementation of the ERC20RebasingInterface with Permit extension allowing approvals to be made via signatures.


# Maintainers

#### Allowance

The Operator Marketplace works with `Allowances` and `Approvals`, like ERC20.

Every 32 ETH represents 1 validator, 1 balance.

Staking Pools can approve any subset of Node Operators for any amount of validators.

Node Operators can create any number of validators for the mentioned pool, up to their allowance.

While simple, and conventional, this task can be a burden for bigger Staking Pools.

Furthermore, this logic can be easily automated and not require any further user interaction.

### These Automators Are Called <mark style="color:purple;">Maintainers</mark>

The pool's owner, a script, smart contract, or a third party can be the maintainer of a pool.

Setting a maintainer is easy, and doesn't require anyone's approval other than the Staking Pool Owner.

Every Pool can have 1 Maintainer.

### It Is Safe To Trust Any Maintainers As They Don’t Have Many Permissions

* <mark style="color:green;">Can set validator allowance.</mark>
* **Can not** change pool status to private/public.
* **Can not** set a whitelist.
* **Can not** deploy a liquidity pool.
* **Can not** access to stakers' funds.
* **Can not** claim any fees.
* **Can not** switch MaintenanceFee.
* **Can not** change Maintainer.
* **Can not** change Controller.

## Node Operators Can Use Maintainers Too

A Node Operator on the Marketplace is owned by its Controller.&#x20;

But again, Staking Operations can be easily automated.

* <mark style="color:green;">Can switch Validator Period.</mark>
* <mark style="color:green;">Can propose new validators.</mark>
* <mark style="color:green;">Can stake to beacon.</mark>
* **Can not** claim any fees.
* **Can not** switch MaintenanceFee.
* **Can not** change Maintainer.
* **Can not** change Controller.


# Withdrawal Contracts

## <mark style="color:green;">Savior of the Stakers.</mark>

#### The Staking Library utilizes <mark style="color:purple;">Contract Owned Staking Derivatives</mark>. The contract in question is called the Withdrawal Contract.

Withdrawal Contracts are simple contracts:

They secure the staked funds and handle the withdrawal queues.&#x20;

### Every Staking Pool has a unique Withdrawal Contract.&#x20;

When a staking pool is created, the latest version of the Withdrawal Contract is deployed automatically.

The owner of the Withdrawal Contract is the owner of the staking pool.

#### Any tokens related to a validator end their journey in the Pool's Withdrawal Contract:

* Staking Rewards
* Block Rewards
* MEV profits
* Principle
* Fees

### Withdrawal Contracts Are Smart

**Like Portal not trusting it's Governance, Withdrawal Contracts don't trust Portal : it uses dual governance and limited upgradability.**

Changing the latest version of the Withdrawal Contracts requires the approval of the Senate.

Changing the implementation code of a specific Pool's Withdrawal Contract requires the approval of the Pool Owner.

Meaning, although they are upgradable, not even Geode Governance has access to the funds within the Withdrawal Contract.

### Upgrading Withdrawal Contracts

1. A new Withdrawal Contract is proposed by the Governance with the TYPE of `WITHDRAWAL_CONTRACT_UPGRADE`
2. Geode Senate Approves the new Withdrawal Contract. From now on, Portal refers to the new implementation address
3. Then, anyone can call `fetchUpgradeProposal`:
   1. `fetchUpgradeProposal` notifies the Portal.
   2. Portal proposes a new implementation of Withdrawal Contract with the TYPE of `UPGRADE`.
   3. Withdrawal Contracts pointing the old implementation enter into **Recovery Mode.**
   4. Owners can approve the proposal and migrate to a new implementation, exiting from  Recovery Mode.

{% hint style="success" %}
If the `fetchUpgradeProposal` **is called by the Owner, the proposal is also automatically approved.**
{% endhint %}

### <mark style="color:purple;">Recovery Mode</mark>

{% content-ref url="/pages/YmTvsIiMCDzgBxMMwPst" %}
[Recovery Mode](/key-concepts/withdrawal-contracts/recovery-mode)
{% endcontent-ref %}

### <mark style="color:purple;">Withdrawal Queue</mark>

{% content-ref url="/pages/CizCsCIzxHm4ZlAehBnA" %}
[Withdrawal Queue](/key-concepts/withdrawal-contracts/withdrawal-queue)
{% endcontent-ref %}


# Recovery Mode

### &#x20;All the Reasons for Recovery Mode

* Withdrawal Contract is paused by the Owner.
* Withdrawal Contract's owner is no longer the Pool's Owner.
* Withdrawal Contract needs to be upgraded to a new version.
* Withdrawal Contract is expired (not likely).

### Under Recovery Mode

{% hint style="success" %}
These operations will continue after the problem is solved, and the Withdrawal Contract has exited Recovery Mode.&#x20;
{% endhint %}

* **Withdrawal Queues and Token transfers continue as usual. 🙂**
* **No more minting** is allowed by the Portal, meaning `deposit()`calls *might* fail.
* **No more validator proposals** can be activated, meaning `stakeBeacon()` calls *will* fail.


# Withdrawal Queue

{% hint style="warning" %}
This functionality is currently under construction.
{% endhint %}


# Bound Liquidity Pools

#### Geode Finance provides an optional B**ound** Liquidity Pool to any Staking Pool utilizing The Staking Library.

### One Transaction To Rule Them All

Creating a liquidity pool is not a separate and time consuming process. Anyone can optionally create a bound liquidity pool within the same transaction used to create their staking pool.&#x20;

<figure><img src="/files/v049ozAvgoIbk3eV4BV4" alt=""><figcaption></figcaption></figure>

## <mark style="color:purple;">Optimized</mark>

Geode's Liquidity Pools are optimized for staking derivatives:

### Better Pricing

Geode's liquidity pools provide better pricing by utilizing a **stableswap pool with a dynamic peg.** Meaning instead of using a pricing algorithm for the derivatives, it uses an algorithm for the underlying Ether.

### Peg Protection

When your staking derivative has a bound liquidity pool, Portal checks if there is a better price on the market before minting any new tokens.&#x20;

Preventing any supply increase without balancing the demand, while giving your stakers a better price.

### Easy Routing

Using Geode Finance's liquidity pool allows your stakers to move their funds between different staking derivatives in just one transaction, with minimal slippage.

## <mark style="color:purple;">No Admin Fees</mark>

Conventional stableswap pools charge an admin fee up to 50%, meaning only 0.02% of 0.04% is shared with the LPs.

Geode Finance doesn't collect any admin fees on their liquidity pools.

#### 100% Higher APR

Geode gives all of the 0.04% fee to the Liquidity Providers, resulting in a 100% increase on the base APR.

## <mark style="color:purple;">Future Utilities</mark>

The Geode team is constantly working on improving The Staking Library with more functionalities.

There are many features that might require having a bound liquidity pool in the future.

If your pool has a bound liquidity pool, your stakers will be able to utilize these, and many other futures instantly.

**Such as:**

{% content-ref url="/pages/dbkn4i9j3YIpqSsYDBc7" %}
[Synthetic Liquidity (WIP)](/key-concepts/future-of-geode/synthetic-liquidity-wip)
{% endcontent-ref %}

{% content-ref url="/pages/zE53gGgMS4FfwVrNpLo9" %}
[Dynamic Withdrawals (WIP)](/key-concepts/future-of-geode/dynamic-withdrawals-wip)
{% endcontent-ref %}

## <mark style="color:purple;">Learn More:</mark>

{% content-ref url="/pages/YPoBnC5WwSrxMzFkdBi6" %}
[Liquidity Pool HandBook](/ethereum-guides/liquidity-pool-handbook)
{% endcontent-ref %}


# Oracles

## <mark style="color:purple;">Telescope Powers the Staking Universe</mark>

{% hint style="success" %}
This implementation of oracle utilizes the Gnosis Safe Contracts. To understand how multi-signature works, and to get better insight about quorum please read the [Gnosis Safe Documentation](https://docs.gnosis-safe.io/).&#x20;
{% endhint %}

{% hint style="info" %}
For more technical context, please review the Telescope-Ether on Github here: [https://github.com/Geodefi/Telescope-Ether](https://github.com/Geodefi/Telescope-Avax)
{% endhint %}

Telescope is a chain-specific, pocket-size Distributed Oracle that contains multiple Nodes with multiple roles within Geode's Staking Library.&#x20;

Like any other Oracle Network, Telescope has multiple Nodes that are collecting and interpreting off-chain information, verifying each other's results and finally submitting the verified data to on-chain contracts, in this case Geode Portal.

### <mark style="color:purple;">Telescope's Structure</mark>

Telescope on Ethereum and Avalanche shares the same logic on slightly different tasks:

#### In the next diagram, red arrows show the journey of a successful price update with a 3/4 multisig setup, with 4 Node Operators:

<figure><img src="/files/t3KWUkVsnAF3ohadyi4l" alt=""><figcaption></figcaption></figure>

1. **Nodes**: individual scripts watching the Consensus Layer, trying to achieve a consensus on their tasks.
2. **Watchers**: Collecting verified signatures from Nodes and submitting them to a multisig contract.
3. **Multisig**: After making sure that more than enough Node Operators have signed a Transaction, it updates the Portal parameters.
4. **Portal**: Makes sure that the update is within the sane limitations.

### <mark style="color:purple;">Implementation Design Principles</mark>

#### Telescope Is Chain-Specific

While the underlying objectives are preserved, Geodes Developer Team needs to design unique a Infrastructure with different solutions for different Proof-of-Stake blockchains. Because all of them have a different understanding of what "stake" means.

#### Telescope is Pocket-Sized

It is easy to understand, deploy, run and update. There is nothing complicated on chain either.

#### Telescope Tracks All Operators and All Pools

Every Pool can have multiple Operators chosen, Telescope does not need to know the full context of the relationships, it tracks all of them.&#x20;

#### Telescope is Pessimistic

Telescope does not trust its operators at all, it expects the unexpected.&#x20;

Geode Portal does **not** allow any percentage of price changes on daily updates. There is no slashing mechanism on Avalanche, so it doesn't allow the price to decrease. Because of this, it only reports the **balanceIncrease**. Also, price increase has 0.2% **daily** upper-limit.

{% hint style="success" %}
If Quorum is not reached on any given day, the price increase upper-limit increases accordingly for the next daily update, etc..&#x20;
{% endhint %}

#### Telescope Nodes Are Black-Boxes

To make them more secure, Telescope Nodes shouldn't be public servers, URLs, or API end-points, and they don't speak with each other directly.&#x20;

#### Telescope Is Not Permissionless

Because the on-chain end point of the Oracle is basically a Gnosis Safe. A battle-tested Quorum mechanism.

More security, less decentralization for price updates.

#### Telescope Nodes Are Free-To-Run

Because of the gas fees, it is expected to cost some money or tokens to operate on-chain Oracle Nodes. However, Telescope Nodes do not need to pay for anything thanks to **Watchers** who collect the data, and submit it automatically whenever there is an off-chain quorum.

#### Telescope Is Persistent to a Single-Point of Failure&#x20;

Thanks to multiple Nodes and multiple Watchers powered by multiple parties, Telescope does not fail until most of the components fail.&#x20;

#### Telescope is Communicative

The operators of Telescope Nodes do **not** need to check or monitor their Node all the time. Telescope will notify it's operator regularly with e-mails. In case anything goes wrong, it sends messages via Whatsapp and/or Telegram. &#x20;

#### Telescope is Stateless

If a Node Operator choses to monitor their node, Telescope stores it's data within an online database. But, Telescope never uses or needs this database to operate normally, any Node can be stopped and rebooted at any given time, only using the information stored in on-chain events and functions.

#### Telescope is Deterministic

Thanks to the implementation of **p-Bank,** all of the Telescope Nodes will come to the same conclusion easily, without needing a lot of on-chain activity for verification.


# Telescope Ether

#### Telescope-Ether currently has 3 responsibilities:

## Reporting the Derivative Prices

Oracle updates the Price **Merkle Root** at least once a day and possibly more frequently.

1. All validator pub-keys of a pool are stored in Portal.
2. Oracle fetches all the pub-keys and validator specific details like fee etc.
3. Total Ether amount is calculated from the validator balances, and claimable portion of the Withdrawal Contract balance.
4. Total of the Fee is deducted from the total Ether.
5. New price is calculated with respect to totalSupply.
6. A Merkle Tree is created containing all the prices of all the pools.
7. A Merkle Root of the Merkle Tree is sent to Portal by Oracle.
8. Anyone can sync prices of the derivative to the Oracle price with valid proofs collected from watchers.
9. Updated price will be valid for the **next 24 hours, or until the next Merkle Root update**.

> Derivative prices can be synced by anyone with the correct Merkle Proofs.&#x20;

> A valid price is required whenever a deposit or a withdrawal operation is requested.

## Updating the Verification Index

Operators can create new validators on behalf of a staking pool, up to the allowance amount set by the maintainer of the pool.

Validator creation is a 3 step process:

1. Validator Proposal
2. Proposal Verification
3. Pooled Staking

Every validator has a unique index **`(0:n]`**

Oracle verifies the proposed validator pub-keys by simply stating the latest verified index.&#x20;

While doing so, the faulty proposals that have a lower index than the new verificationIndex are excluded.

{% hint style="danger" %}
These faulty proposals are called **aliens** and this pubkeys can not be ever used again.
{% endhint %}

## Regulating the Operator Marketplace

#### Alienation

Alienation process results in Node Operator being imprisoned for the next 14 days, meaning it can not access to the Portal at all.

#### All possible reasons of alienation:

* [Withdrawal credential frontrunning](https://bit.ly/3Tkc6UC)
* Faulty sig1
* Faulty sig31
* Stealing the block rewards from staking pools. Obviously this causes imprisonment.
* Validator is not exited by Operator although the `expectedExit` has past. Anyone can blame a validator and effectively imprison the Operator until the exit happens.


# Telescope Avax

{% hint style="info" %}
Geode is preparing for an upgrade on it's Avalanche Infrastructure that will make it compatible with the Ethereum Infrastructure with many improvements.

**Currently, Geode is working on improving its oracle on avalanche blockchain.**
{% endhint %}


# Future of Geode

## Improved User Experience

### Better Maintainers

{% content-ref url="/pages/23SLLbZ6cSo6j3lnlVJi" %}
[Better Maintainers (WIP)](/key-concepts/future-of-geode/better-maintainers-wip)
{% endcontent-ref %}

* LinearDistributionMaintainer - WIP
* ProfitableDistributionMaintainer - WIP

More is possible, create your own Maintainer:

{% content-ref url="/pages/pr7YAwNKRplvqovwxwxF" %}
[Maintainers](/key-concepts/permissionless-configurable-staking-pools/maintainers)
{% endcontent-ref %}

### More Interfaces

* ERC20Interface
* ERC20PermitInterface
* Erc20RebasingInterface - WIP
* Erc20RebasingPermitInterface - WIP

More is possible, create your own Interface:

{% content-ref url="/pages/NMzvFXpWn6oyM78TmdkQ" %}
[Current Interfaces](/key-concepts/permissionless-configurable-staking-pools/current-interfaces)
{% endcontent-ref %}

## Improved Financial Optimizations

* Synthetic Liquidity

{% content-ref url="/pages/dbkn4i9j3YIpqSsYDBc7" %}
[Synthetic Liquidity (WIP)](/key-concepts/future-of-geode/synthetic-liquidity-wip)
{% endcontent-ref %}

* Dynamic Withdrawals

{% content-ref url="/pages/zE53gGgMS4FfwVrNpLo9" %}
[Dynamic Withdrawals (WIP)](/key-concepts/future-of-geode/dynamic-withdrawals-wip)
{% endcontent-ref %}

## Further Decentralization

Currently, there are many components that adds trust component to the Staking Library:

* Centralized Governance
* Senate is a Multisig
* Permissioned Operators
* Centralized Oracle

We have a roadmap to decentralize every component further.

* Supporting EIP-4788

{% content-ref url="/pages/yDeevPHEdlyhrOnbrgHq" %}
[Supporting EIP-4788 (DRAFT)](/key-concepts/future-of-geode/further-decentralization/supporting-eip-4788-draft)
{% endcontent-ref %}

* Quadratic Weighted Senate.

{% content-ref url="/pages/BuwGF9OGVcDub71pHNXi" %}
[Quadratic Weighted Senate (DRAFT)](/key-concepts/future-of-geode/further-decentralization/quadratic-weighted-senate-draft)
{% endcontent-ref %}

* Decentralized Oracle

{% content-ref url="/pages/QesDoYLZJiiA13Dcj6HX" %}
[Decentralized Telescope (DRAFT)](/key-concepts/future-of-geode/further-decentralization/decentralized-telescope-draft)
{% endcontent-ref %}

* Decentralized Operators

{% content-ref url="/pages/NeVBKqnUYvM9kfWUypUN" %}
[Degen Operators (DRAFT)](/key-concepts/future-of-geode/further-decentralization/degen-operators-draft)
{% endcontent-ref %}

### Chain Sync for Avalanche Infrastructure


# Better Maintainers (WIP)

{% hint style="success" %} <mark style="color:green;">We are currently working on more ideas to improve the user experience on Operator Marketplace. Until then you can create an automation script, and choose it as your Maintainer.</mark>
{% endhint %}

### LinearDistributionMaintainer

To use **Linear Distribution** on your subset of operators, set this contract as your Pool Maintainer.

* Address: <mark style="color:red;">under construction - not available.</mark>

### ProfitableDistributionMaintainer&#x20;

To distribute your validators **according to the past performance** of your subset of operators, set this contract as your Pool Maintainer.

* Address: <mark style="color:red;">under construction - not available.</mark>


# Synthetic Liquidity (WIP)

{% hint style="info" %}
Utilizing this feature will require a **Bound Liquidity Pool**.
{% endhint %}

### Why?

Synthetic Liquidity will allow less than 100% collateralization ratio to be introduced for a staking derivative.

However, Synthetic Liquidity is only created on deposits and burned on withdrawals.

This way, we can allow a continuous liquidity flow to bound liquidity pool, without creating any issues on the supply model.&#x20;

### How much?

Staking Pool Owners can set a parameter up to x% for synthetic minting.&#x20;

x is potentially between 10-25.

### Example for **10%** Synthetic Liquidity

> The price of the derivative on the following example will be 1 Ether.

1. User puts 100 Ether in Portal to be used for Staking Operations.
2. 90 Ether is added to the Pool.
   * Decreases the pool APR.
3. Portal mints 110 Ether worth of gETH, 110 gETH
   * Created tokens are not backed by any collateral.
4. 100 Ether worth of gETH is given back to staker, 100 gETH
5. 10 Ether and 10 Ether worth of gETH (10 gETH) is put into Bound Liquidity Pool.
   * Increases the Pool APR.
6. The LP tokens are given to the Withdrawal Contract.
7. When user comes back with 100 gETH, which can represent more than 100 Ether, respective LP tokens are burned, and the remaining Ether amount will be filled by Validator Withdrawals.


# Dynamic Withdrawals (WIP)

{% hint style="info" %}
Utilizing this feature will require **supporting EIP-4788**
{% endhint %}

{% content-ref url="/pages/yDeevPHEdlyhrOnbrgHq" %}
[Supporting EIP-4788 (DRAFT)](/key-concepts/future-of-geode/further-decentralization/supporting-eip-4788-draft)
{% endcontent-ref %}

{% hint style="info" %}
Utilizing this feature will require a **Bound Liquidity Pool**.
{% endhint %}

## **Traditional Approach to Withdrawals**

<figure><img src="/files/Qsjrvl7iYeslLNDeX1G9" alt=""><figcaption></figcaption></figure>

**The traditional Staking process establishes 3 states with Staking/Unstaking functionalities from the perspective of the Staking Pool:**&#x20;

1. Liquid State&#x20;
2. **Locked State**&#x20;
3. Withdrawn State&#x20;

There are some ideas that aim to solve the problem of liquidity on Locked State for a staking derivative. For example, a Staking Pool can set aside a portion of the issued asset to allow withdrawals up to that amount... However, it is obvious that this method is not yield friendly since there will be idle tokens which aren't generating yield. Also determining how much liquidity should be kept is problematic, since there is no way to foresee the exact amount that stakers want to unstake.

Alternatively, there can be a withdrawal mechanism that requires a waiting period to be fulfilled, however forcing users to wait for their funds results in a poor user experience. Also, there is a risk that no funds will be available until the Locked State is finalized. As seen above, there is no way to have a liquid derivative that always fulfils a withdrawal request.&#x20;

## Dynamic Withdrawals

<figure><img src="/files/W4HdRvDHZYx8g1E3rblo" alt=""><figcaption></figcaption></figure>

Dynamic Withdrawals can be summarized as a decentralized stable-price liquidity pool designed to allocate any amount of requests instantly. When any of the funds are in the Withdrawn or Liquid State, withdrawal is finalized with a buy-back & burn, which **heals the price as a result**.&#x20;

Any withdrawal request would result in a slippage and a Withdrawal pool fee to be paid to the Liquidity Providers of the pool. Additionally, because the withdrawals are finalized by the state of the Staking Pool, with a guaranteed buy-back\&burn on the mentioned withdrawal pool, the price will be healed in a short amount of time. <mark style="color:purple;">Thereby, any request with excessive amounts should be spread over time</mark>, which is absolutely shorter than the initial Locked Period. Thus, **creating an equilibrium between price, amount and time**.&#x20;

As a result there is 3 States for a Dynamic Staking Pool:&#x20;

1. **Growth Period**: the price is stable, StakingPool has 0 debt to the withdrawal pool, new validators are created with the surplus.&#x20;
2. **Stable Phase**: there is little to no debt or surplus in the staking pool. No new Validators are created.&#x20;
3. **Resurrection Phase**: there is a price gap, resulting in a substantial debt for the Staking Pool. Validators are unstaked to pay the debt and heal the price.&#x20;

It should be noted that there can be multiple phases in a day but the Resurrection Phase can not continue more than the Lock Period. Even in the long Resurrection Phases, there will be a Stable Phase whenever the Node Operator responds. Finally, since the debt is known by the Pool’s Node Operator there is no need to create unnecessary transactions to move the funds between different subchains. This is another benefit of this method that applies specifically to the Avalanche Blockchain.


# Further Decentralization


# Supporting EIP-4788 (DRAFT)

#### EIP-4788 vs EIP-4895&#x20;

<https://eips.ethereum.org/EIPS/eip-4788> (WIP)

<https://eips.ethereum.org/EIPS/eip-4895> (CFI for Shanghai Update)

There are currently two possible methods suggested for Withdrawal Operations on the Beacon Chain.

4788, is a version that supports trustless withdrawals from Smart Contracts living in the Execution Layer. This provides ease to the staking pools, however it is not going to be live soon.

4895, is a version that only allows withdrawals when Operator triggers. This is not so trustless as there is no way to enforce the validator. However, currently this is the version to be implemented.

#### Geode supports withdrawals with EIP 4895 and will support EIP-4788 when it is ready.

* Operator withdraws remotely with a key, without any limits other than validator timeline stated when it is created.
* Funds emerges within "**withdrawalContract**" of the Pool, without triggering the fallback.

Since it is not trustless to handle all this operation, currently we are optimizing it further and preparing for the EIP-4788.

However, it is not coming soon.


# Quadratic Weighted Senate (DRAFT)

#### Senates are elected every year, they secure the underlying code. Senate elections are one of the most important events that will happen in the Geode's future.

Currently, every Planet has 1 vote in these elections and Comets doesn't have any.&#x20;

#### This doesn't seem fair.

We propose the implementation of weighted Senate Elections that uses the amount of staked tokens to give linear voting power to a Staking Pool's Maintainer.

We also propose to include a specific amount for Governance Fees that will be fixed within the period of the elected Senate.

#### Thus, we will be able to achieve 4 improvements:

1. Comets will now have a say in the Senate Elections
2. Planets can be made permissionless.
3. IDs can be used for market making.
4. Governance Fees can be negotiable.

#### This proposal also allows Senate-less implementations to be possible in the future.

"Senate" logic is still not decentralized enough.

Since we can achieve Permissionless Planets, now there are only 2 functionalities that will be secured by the Senate:

* Contract upgrades
* Node Operator Onboarding

both of these are not frequent events and can be handled directly by the Maintainer votes.


# Degen Operators (DRAFT)

### Decentralized General Purpose Node Operators

{% hint style="info" %}
Currently, there are not a lot of details about this proposal as there are many other proposals that needs to be implemented to support these functionalities.
{% endhint %}

#### Geode Finance is preparing to support home-stakers and there are multiple ways to achieve that in the future.

De-Gen Operators approach is focusing on providing better user experience to these stakers without increasing the complexity around Staking Pool management for the planet and comet maintainers.


# Decentralized Telescope (DRAFT)

### Decentralize the Holy Oracle

{% hint style="info" %}
Currently, there are not a lot of details about this proposal as there are many other proposals that needs to be implemented to support these functionalities.
{% endhint %}

#### Telescope is the only centralized component within Geode's Infrastructure.

While we are making efforts to increase the trustlessness and decentralization of our infrastructure, it is not desired to keep Telescope as a centralized entity.&#x20;

Thus, this is probably one of the most important improvements Geode developers are working on.


# Chain Sync (AVAX) (draft)

### Staking is a chain specific problem.

Every blockchain has a different approach to the Proof of Stake, and every approach requires a different solution to be found.

Currently, there are some implementations that are used to solve chain-specific problems of Avalanche blockchains. These are mostly related to the multi-chain structure of the chain.

With this improvement we are aiming to achieve two things:

* Eliminate chain-specific differences between Portal deployments on Avalanche and Ethereum.
  * Makes development processes easier, allowing us to provide more frequent improvements on the protocol without considering differences within code.
  * Makes onboarding of protocols on different blockchain easier. &#x20;
* Increase trustlessness of the Node Operators.
  * Allows us to onboard more Operators.
  * Allows us to decrease costs for Operators.
  * Strengthens Portal.&#x20;


# Staking Pool HandBook

## Be Your Own Solution.

Don't invest your time and resources on creating and maintaining a fragile development environment.

Don't integrate with intermediaries and inherit a tail risk to your funds.

#### Create your own staking pool instead, and you're good to go.&#x20;

{% hint style="success" %}

### Open the gates of Proof of Stake for your Protocol

<mark style="color:green;">Currently, the Geode Finance developers are providing comprehensive help and additional benefits to our first staking pools</mark><mark style="color:green;">**.**</mark>&#x20;

[<mark style="color:blue;">Get in touch with us</mark>](https://discord.com/invite/RC8fTTuJtm)<mark style="color:blue;">.</mark>
{% endhint %}

> **Use our App** or get smart contract details from:

{% content-ref url="/pages/kPkco4WHcldGJGYOUouu" %}
[Live Contracts](/developers/live-contracts)
{% endcontent-ref %}

### Initiate a Staking Pool

{% content-ref url="/pages/RCqdgs3oJRdoI3k4krUq" %}
[Initiating a Customizable Staking Pool](/ethereum-guides/staking-pool-handbook/initiating-a-customizable-staking-pool)
{% endcontent-ref %}

### Choose Your Node Operators

{% content-ref url="/pages/D5CDHSbTKimzVBsqA7u9" %}
[Managing Your Operator Set](/ethereum-guides/staking-pool-handbook/managing-your-operator-set)
{% endcontent-ref %}

### Manage Your Pool

{% content-ref url="/pages/vw0wgOa07tnJEg7TuCKn" %}
[Changing Your Pool's Owner](/ethereum-guides/staking-pool-handbook/changing-your-pools-owner)
{% endcontent-ref %}

{% content-ref url="/pages/suYp5S9I9NxMqcCsRwQ7" %}
[Manage Your Maintenance Fee](/ethereum-guides/staking-pool-handbook/manage-your-maintenance-fee)
{% endcontent-ref %}

### Making Your Pool Private and Using a Whitelist

{% content-ref url="/pages/ee1qPNg9mYqC5t04mRUo" %}
[Private Pools and Whitelisting](/ethereum-guides/staking-pool-handbook/private-pools-and-whitelisting)
{% endcontent-ref %}

### Create a Bound Liquidity Pool for Your Staking Pool

{% content-ref url="/pages/W7L0oImLen78WdEUAPiS" %}
[Using a Bound Liquidity Pool](/ethereum-guides/staking-pool-handbook/using-a-bound-liquidity-pool)
{% endcontent-ref %}

### Automate Your Tasks With Maintainers

{% content-ref url="/pages/uN9hLZh2n7GfHhyOSDCf" %}
[Using Maintainers for Your Pool](/ethereum-guides/staking-pool-handbook/using-maintainers-for-your-pool)
{% endcontent-ref %}

### Secure Your Withdrawal Contract

{% content-ref url="/pages/0b5Ca1LhwIw09a7Ajgm1" %}
[Securing Your Withdrawal Contract](/ethereum-guides/staking-pool-handbook/securing-your-withdrawal-contract)
{% endcontent-ref %}

### Bring Your Own Governance

{% content-ref url="/pages/GL5Bciozj2UU0sML3miE" %}
[Decentralizing Your Pool](/ethereum-guides/staking-pool-handbook/decentralizing-your-pool)
{% endcontent-ref %}


# Initiating a Customizable Staking Pool

## Before Initiation:

### 32 Ether

Creating a Pool is **permissionless**, anyone can claim any pool name.

To prevent sybil attacks, initiation requires **exactly 1 validator worth of funds**. However, you can **deposit more Ether later.**

However, this amount will be used to create your first validator.

### Pool ID

Every Pool will have a **unique** ID.

It will be used for your Pool operations, and you can find your ID from both our frontend or Portal.

```javascript
const pool_ID = Portal.generateId(pool_name, 5);
```

### Maintainers

Maintainers are useful to automate pool owners' daily tasks, such as choosing your Node Operators.

{% content-ref url="/pages/pr7YAwNKRplvqovwxwxF" %}
[Maintainers](/key-concepts/permissionless-configurable-staking-pools/maintainers)
{% endcontent-ref %}

## Initiate Your Pool!

Geode uses an initiator function to set some parameters for your staking pool and derivative.

```javascript
Portal.initiatePool(
    NAME,
    fee,
    interfaceVersion,
    maintainer,
    interface_data,
    config,
    {value: 32 Ether}
);
```

1. **NAME**: Unique name of your Pool. <mark style="color:red;">Can not be changed later.</mark>
2. **FEE**: Maintenance fee that will be charged for your services as the pool owner. 10^10 represents 100%, can be set to up to 10% (10^9). <mark style="color:blue;">Can be changed later.</mark>
3. **Interface Version**: Can be empty, or can be any interfaces from the list below. <mark style="color:red;">Can not be changed later.</mark>

{% content-ref url="/pages/NMzvFXpWn6oyM78TmdkQ" %}
[Current Interfaces](/key-concepts/permissionless-configurable-staking-pools/current-interfaces)
{% endcontent-ref %}

4. **Maintainer**: Any other address that will manage your pool's Node Operators. Can be a community owned Maintainer, or the address of an automation script, etc. <mark style="color:blue;">Can be changed later.</mark>
5. **Interface Data**: some interfaces require data to be present along with a gETH address and Pool id.
6. **Config**: initial configuration of your Pool as:
   1. **True** if a private pool - <mark style="color:blue;">Can be changed later.</mark>
   2. **True** if uses an interface<mark style="color:blue;">.</mark> <mark style="color:red;">Can not be changed later.</mark>
   3. **True** if uses a liquidity Pool - <mark style="color:blue;">Can be changed later.</mark>

{% hint style="info" %}
Note that, if you create private pool, you will need to create a Whitelisting Contract and register it.

However, Pool CONTROLLERs are allowed to use the pool even without creating and registering a contract.&#x20;
{% endhint %}

{% content-ref url="/pages/ee1qPNg9mYqC5t04mRUo" %}
[Private Pools and Whitelisting](/ethereum-guides/staking-pool-handbook/private-pools-and-whitelisting)
{% endcontent-ref %}

### Example of Pool Creation Transaction

### Basic Pool Initiation

The below transaction creates a **Private** Staking Pool with **no maintenance fee*****,*** **no interface**, and **no Liquidity Pool**:

<pre class="language-javascript"><code class="lang-javascript">// Pool
const your_address="0xabcdf....abcdf";
const pool_name= "IceBear's Pool";

// send the transaction
<strong>Portal
</strong>    .initiatePool(
        0,
        0,
        your_address,
        pool_name,
        "0x",
        [true, false, false])
    .send({
        value: String(32e18),
    });

pool_ID = Portal.generateId(pool_name, 5);
</code></pre>

### Complex Initiation

The below transaction creates a **Public** Staking Pool with a **5% maintenance fee**, and **ERC20InterfacePermitUpgradable** interface, which also has a bound **Liquidity Pool**:

```javascript
const getBytes = (key) => {
  return Web3.utils.toHex(key);
};

const intToBytes32 = (x) => {
  return ethers.utils.hexZeroPad(ethers.utils.hexlify(x), 32);
};


// EDIT HERE
// Pool
const your_address="0xabcdf....abcdf";
const pool_name= "IceBear's Pool";
const pool_fee = 5 // 5%
// interfaces = ["ERC20", "ERC20Permit"];
const interface_version = "ERC20Permit";
const interface_name = "IceBear Staked Ether";
const interface_symbol= "IETH"
// Config
const is_private_pool = false;
const use_interface = true;
const use_liquidity_pool = true;
// EDIT HERE



// DO NOT TOUCH HERE
const name_bytes = getBytes(interface_name ).substr(2);
const symbol_bytes = getBytes(interface_symbol).substr(2);
const interface_data =
  intToBytes32(nameBytes.length / 2) + nameBytes + symbolBytes;
const interface_id =  await Portal.generateId(interface_version, 31);
const denominator=10 ** 10;
await Portal
    .initiatePool(
    Math.floor((pool_fee * denominator) / 100),
    interface_id,
    deployer.address,
    getBytes(pool_name),
    interfaceData,
    [is_private_pool , use_interface , use_liquidity_pool ],
    {
      from: deployer,
      log: true,
      value: String(32e18),
    },
  );
  
  const pool_ID = Portal.generateId(pool_name, 5);
  console.log("your pool id:", pool_ID);
```


# Managing Your Operator Set

## Choose Freely!

Assume your balance is the number of validators within your pool.&#x20;

Your maintainer will be giving allowances to the Node Operators, and meanwhile, the Node Operators will compete to get as many validators as possible.

You can think of it as ERC-20 approvals. You are approving a certain amount of validators to be run by a Node Operator.

```javascript
Planet.approveOperators(
         poolId,
         [operatorIds],
         [allowances]
    );
```

### How To Choose?

There are number of factors to pay attention to while choosing your Node Operators:

* Choose Operators with lower fees, but make sure to consider whether they'll be sufficient for the task.
* Do not centralize around one, or even a few Operators -- try to spread your risk of being slashed as much as possible.
* Pay attention to **validatorPeriod** parameter of the Operators:
  * **A shorter period means better peg protection, and happier stakers.**
  * **A longer period means better yields.**
* Consider how many validators are they already running within Geode. Too many? Too little? Do your bit for validator diversification.


# Changing Your Pool's Owner

## <mark style="color:purple;">CONTROLLER</mark>

The "**CONTROLLER**" key stands for the owner of the ID of a given staking pool.

### Who Is the Current Owner?

```javascript
 const getBytes32 = (key) => {
    return ethers.utils.formatBytes32String(key);
  };

const owner = Portal.readAddressForId(id, getBytes32("CONTROLLER"))
```

### Set a New Owner

#### 1. Which address is the new owner?

This might be a developer's address, a developers' multisig, or a token address.&#x20;

#### <mark style="color:red;">2. Double check the address of your new Controller.</mark>

#### 3. Call `changeIdCONTROLLER()` in Portal with the ID of your Pool, and the address of your new Controller.&#x20;

```solidity
Portal.changeIdCONTROLLER(uint256 id, address newCONTROLLER)
```

#### 4. Change the Owner of Your Withdrawal Contract

Since the Withdrawal Contracts do not trust Portal, you will need to transfer its ownership as well.

```javascript
const getBytes32 = (key) => {
    return ethers.utils.formatBytes32String(key);
};

const wcAddress = Portal.readAddressForId(id, getBytes32("withdrawalContract");

await wcAddress.changeController(newController);
```

{% hint style="danger" %} <mark style="color:red;">If your Pool's Owner is not the Withdrawal Pool's Owner, it will go into</mark> <mark style="color:red;"></mark><mark style="color:red;">**Recovery Mode**</mark> <mark style="color:red;"></mark><mark style="color:red;">until you change it's ownership:</mark>
{% endhint %}

{% content-ref url="/pages/YmTvsIiMCDzgBxMMwPst" %}
[Recovery Mode](/key-concepts/withdrawal-contracts/recovery-mode)
{% endcontent-ref %}

#### Changing your Controller is easy, however it will override the ability of the previous Controller <mark style="color:red;">immediately</mark>.&#x20;

{% hint style="danger" %} <mark style="color:red;">**After changing your CONTROLLER, you will not be able to take this action back by using your old CONTROLLER address.**</mark>
{% endhint %}


# Manage Your Maintenance Fee

#### Changing your fee doesn't affect the previously created validators!

Learn more about the Maintenance Fee:

{% content-ref url="/pages/rIGZWSJishlr5v5VVXf9" %}
[Maintenance Fee](/operator-marketplace/maintenance-fee)
{% endcontent-ref %}

## Changing Your Fee

```javascript
const new_fee = x * 10**10 /100 // x%

await Portal.switchMaintenanceFee(id, new_fee)
```

{% hint style="info" %}

#### 3 Day Rule

When a Pool's fee is changed, it takes 3 days for new fee to take effect.&#x20;

<mark style="color:blue;">Within this 3-day period the fee cannot be changed again.</mark>

This applies to Operator Fees as well, and prevents misleading behavior within our marketplace.
{% endhint %}

## Claiming Your Fees

#### Internal Wallet

Every ID has an Internal Wallet, which makes transferring Ether easier for both Geode's Portal, and it's users.

The Internal Wallet is the place where your fees will accrue over time.

```javascript
const wallet_balance = Portal.readUintForId(id, getBytes("wallet"));

await Portal.decreaseWalletBalance(id, wallet_balance);
```


# Private Pools and Whitelisting

{% hint style="success" %} <mark style="color:green;">You can configure your pool as Public or Private on creation. However, pool owners can change this status easily.</mark>
{% endhint %}

#### Public Pools can be used by anyone

If you are a service provider willing to manage anyone's Ether, create a Public Pool.&#x20;

{% hint style="success" %} <mark style="color:green;">Public Pools will show up within on Geode's App.</mark>
{% endhint %}

#### Private Pools can only be used by whitelisted addresses

If you are using a personal staking pool, or worried about KYC/AML, create a Private Pool.

{% hint style="success" %} <mark style="color:green;">Private Pools do</mark> <mark style="color:green;"></mark><mark style="color:green;">**not**</mark> <mark style="color:green;"></mark><mark style="color:green;">show up on Geode's App.</mark>
{% endhint %}

### Making Your Pool Public

```javascript
Portal.setPoolVisibility(id, false);
```

### Making Your Pool Private

```javascript
Portal.setPoolVisibility(id, true);
```

### Whitelisting

#### You can use a whitelist to manage staker addresses on Private Pools

But you don't need to.

{% hint style="success" %} <mark style="color:green;">A Pool Owner is able to use their private Pool without being whitelisted.</mark>
{% endhint %}

This whitelist should be a contract that has implemented **isAllowed()** function:

{% code title="IWhiteList.sol" %}

```solidity
interface IWhiteList {
  // @notice returns true if the address is allowed
  function isAllowed(address) external view returns (bool);
}
```

{% endcode %}

After making your pool private and creating your whitelisting contract with required functionality, simply notify Portal:

```javascript
Porta.setWhitelist(id, contract_address);
```

> Here is an **unupgradable** ,**unaudited**, **untested, simple** Whitelist contract for you 💕

```solidity
pragma solidity =0.8.7;

import "@openzeppelin/contracts/access/Ownable.sol";

interface IWhiteList {
  // @notice returns true if the address is allowed
  function isAllowed(address) external view returns (bool);
}

contract Whitelist is IWhitelist, Ownable {
  event Listed(address indexed account, bool isWhitelisted);

  mapping(address => bool) private whitelist;

  function isAllowed(
    address _address
  ) external view virtual override returns (bool) {
    return whitelist[_address];
  }

  function setAddress(address _address, bool allow) external virtual onlyOwner {
    require(whitelist[_address] != allow);
    whitelist[_address] = allow;
    emit Listed(_address, allow);
  }
}
```


# Using a Bound Liquidity Pool

Learn more about the benefits of using a bound liquidity pool with your staking pool:

{% content-ref url="/pages/D6utzcdejMctLxSHh3Qr" %}
[Bound Liquidity Pools](/key-concepts/bound-liquidity-pools)
{% endcontent-ref %}

#### You can have a bound Liquidity Pool created upon initiation:

{% content-ref url="/pages/RCqdgs3oJRdoI3k4krUq" %}
[Initiating a Customizable Staking Pool](/ethereum-guides/staking-pool-handbook/initiating-a-customizable-staking-pool)
{% endcontent-ref %}

#### You can also create a bound Liquidity Pool after initiation:

```javascript
Portal.deployLiquidityPool(id);
```

{% hint style="danger" %} <mark style="color:red;">You can not deactivate a Bound Liquidity Pool later.</mark>
{% endhint %}


# Using Maintainers for Your Pool

### Why Are Maintainers Needed?

Not really needed per se...

Maintainers can be useful for bigger staking pools to automate some operations. Currently, its primary use for Staking Pools is **choosing new Operators and distributing the incoming deposits**.

Learn more about them here:

{% content-ref url="/pages/pr7YAwNKRplvqovwxwxF" %}
[Maintainers](/key-concepts/permissionless-configurable-staking-pools/maintainers)
{% endcontent-ref %}

{% hint style="info" %}
At any given point, a Staking Pool can have **1 maintainer** **at most.**
{% endhint %}

### Setting Your Maintainer

```javascript
Portal.changeMaintainer(id, new_maintainer_address);
```

You can set any address as your maintainer, it is <mark style="color:green;">safe to trust</mark>, as they can not do much harm 🙂

{% hint style="info" %}
If you have a script that will update your allowances as new stake comes in, set it as your Maintainer.&#x20;
{% endhint %}

If you want to use third party maintainers, we will provide some contracts in the future.

These will be community owned maintainers and will help you optimize your validators towards Profitability or Further decentralization.


# Securing Your Withdrawal Contract

#### Learn More About the Withdrawal Contracts:

{% content-ref url="/pages/fajxkHebpiVLDHZHMN44" %}
[Withdrawal Contracts](/key-concepts/withdrawal-contracts)
{% endcontent-ref %}

As a pool owner, it is your responsibility to keep your Withdrawal Contract up to date, or your pool will immediately go under <mark style="color:red;">**Recovery Mode**</mark>.

### Checking for Upgrades

```javascript
// compare these 2 version IDs:

const lastVersion = await Portal.getWithdrawalContractVersion();
const currentVersion = await WithdrawalContract.getContractVersion();

const needs_upgrade = lastVersion != currentVersion ;
```

### Fetching an Upgrade Proposal

Anyone can fetch an upgrade proposal and force your Staking Pool into Recovery Mode.

However, only the Controller can approve this upgrade proposal to effectively change the code:

```javascript
await WithdrawalContract.fetchUpgradeProposal();
```

### Upgrade

```javascript
await WithdrawalContract.upgradeTo(newImplementation);
```

{% hint style="success" %} <mark style="color:green;">It is always best practice to be in touch with us, in order to be notified for potential upgrades:</mark>\
[*<mark style="color:blue;">**Join Geode's Discord**</mark>*](https://discord.com/invite/RC8fTTuJtm)
{% endhint %}


# Decentralizing Your Pool

### Do It With Your Governance Token!

You can distribute the ownership of your Staking Pool by setting the pool owner as a Governance Token!

#### By making your Governance Token the <mark style="color:purple;">Controller</mark> of your Staking Pool, you can:

* Vote on Changing the Maintainer address.
* Vote on Node Operators.
* Vote on Senate Elections with your token.
* etc.

#### Simply,

{% content-ref url="/pages/vw0wgOa07tnJEg7TuCKn" %}
[Changing Your Pool's Owner](/ethereum-guides/staking-pool-handbook/changing-your-pools-owner)
{% endcontent-ref %}


# Operator Handbook

## Operate, Automate, Optimize.

No need to search for other staking pools within the market, or invest your resources into understanding multiple protocols and the way to integrate and optimize your workflow.&#x20;

**Now, there is a global standard.**

Geode's marketplace brings the ease of integrating with multiple trustless staking pools **at once!**

{% hint style="success" %} <mark style="color:green;">Currently, the Geode Finance developers are providing comprehensive help and additional benefits to</mark> <mark style="color:green;"></mark><mark style="color:green;">**Geode's Founder Operators.**</mark>&#x20;

[<mark style="color:blue;">Get in touch with us</mark>](https://discord.com/invite/RC8fTTuJtm)<mark style="color:blue;">.</mark>
{% endhint %}

No worries, the following steps will not take long. Follow them and see how easy it is to integrate with the Global Standard:

1. Get Onboarded to Goerli
2. Initiate your Operator and join the Operator Marketplace
3. Learn more about the Marketplace and Validator Creation process
4. Learn how to use the Portal
5. Learn how to Create Validators
6. Utilize a maintainer
7. Manage your Operator

## 0. Get Onboarded (on Goerli):

#### Simply provide an address for us to start the Validator Onboarding Process:

{% content-ref url="/pages/Dyz6vsALqRWmNYY9pvND" %}
[Get Onboarded](/ethereum-guides/operator-handbook/get-onboarded)
{% endcontent-ref %}

{% hint style="success" %}
**320 Goerli Ether** will be sent to this address upon onboarding, so you can start testing!
{% endhint %}

## 1. Get Portal's address and ABI:

{% content-ref url="/pages/Jtm3ZVzVyDphbVl7BLvr" %}
[Portal.sol](/developers/live-contracts/ethereum-v2/portal.sol)
{% endcontent-ref %}

## 2. Initiate:

**After onboarding, you will need to Initiate your Operator in order to join the Operator Marketplace:**

{% content-ref url="/pages/vYi83f0cnL2YCKx06wI5" %}
[Initiating an Operator](/ethereum-guides/operator-handbook/initiating-an-operator)
{% endcontent-ref %}

## 3. Now, lets take a look at the Marketplace and Validator Life-Cycle:

{% content-ref url="/pages/8al101kYMumrrAiepfDu" %}
[Operator Marketplace](/operator-marketplace)
{% endcontent-ref %}

## 4. Finally, we need to learn how to communicate with Portal:

{% content-ref url="/pages/RDEGmSk9s5IbQw6KFuZd" %}
[Communicating with Portal](/ethereum-guides/operator-handbook/communicating-with-portal)
{% endcontent-ref %}

## 5. We are ready to create some validators:

{% content-ref url="/pages/lV2zNRsttbKAswCl7igf" %}
[Creating Validators](/ethereum-guides/operator-handbook/creating-validators)
{% endcontent-ref %}

## + Manage Your Operator

{% content-ref url="/pages/W3FkuU78EWZrHJLfZ9oS" %}
[Changing an Operator's Owner](/ethereum-guides/operator-handbook/changing-an-operators-owner)
{% endcontent-ref %}

{% content-ref url="/pages/Dx8si68HmesHNMxfti8u" %}
[Switching Your Fee](/ethereum-guides/operator-handbook/switching-your-fee)
{% endcontent-ref %}

{% content-ref url="/pages/IVWM6sZLwuHJXEeXaZ0R" %}
[Switching Your Validator Period](/ethereum-guides/operator-handbook/switching-your-validator-period)
{% endcontent-ref %}

## + Automate Your Tasks With Maintainers

{% content-ref url="/pages/VUuGD0zmkRxeYxOlkK8W" %}
[Using Maintainers](/ethereum-guides/operator-handbook/using-maintainers)
{% endcontent-ref %}

## + Get Ahead of Your Competitors

{% content-ref url="/pages/PlvhRypc2syhBklsjS13" %}
[Optimizing Your Revenue](/ethereum-guides/operator-handbook/optimizing-your-revenue)
{% endcontent-ref %}

## + When Its Time, Exit Your Validators.

{% content-ref url="/pages/D2Cn6pfZDabsXHEBItve" %}
[Exiting Validators](/ethereum-guides/operator-handbook/exiting-validators)
{% endcontent-ref %}


# Get Onboarded

Geode Finance is currently allowing only the Permissioned Node Operators to take place in it's Operator Marketplace. However, it is a quick process:

{% content-ref url="/pages/VjqGpLYmMAQ3zzukicpP" %}
[Onboarding New Operators](/operator-marketplace/onboarding-new-operators)
{% endcontent-ref %}

## Have you been Onboarded? No?

#### We only need your Goerli Address.&#x20;

#### Send it to us and start experimenting!

{% hint style="success" %}
**320 Goerli Ether** will be sent to this address upon onboarding!
{% endhint %}


# Initiating an Operator

### Operator ID

Every Operator has a **unique** ID.

This ID will be used to distinguish you from other entities within Geode.

```javascript
// 4? the TYPE parameter that defines Operators
const type_operator = 4; 
const pool_ID = Portal.generateId(operator_name, type_operator);
```

> Want to see all the IDs of a type?&#x20;

```javascript
const type_operator = 4; 
const type_pool = 5; 
const allIds= Portal.allIdsByType(_type, index);
// index = [0,n] : probably stop calling when you see uint256(0)
```

> What are Maintainers?

Maintainers are useful to automate an operator's daily tasks, such as creating validators!

{% content-ref url="/pages/pr7YAwNKRplvqovwxwxF" %}
[Maintainers](/key-concepts/permissionless-configurable-staking-pools/maintainers)
{% endcontent-ref %}

## Initiate Your Operator!

> You can totally do this from [<mark style="color:blue;">Etherscan</mark> ](https://goerli.etherscan.io/address/0xb0334f08dec465ec180f1af04c6d7d3737407083#writeProxyContract#F15)if you want.

Portal uses an initiator function to set some parameters for your unique ID.

> <mark style="color:purple;">You can send some Ether on initiation!</mark> It will be added to your internal wallet.&#x20;
>
> Internal wallet will come handy on validator creation. Don't worry, you can take it out later.

```javascript
// EDIT THESE
const fee = 5; // 5%, [0, 10]
const validatorPeriod = 180; // 180 days, [90, 1825]
const maintainer_address= <your_address_here>;
const initial_wallet = 5e18; // you might use Bignumber.js for this one

// KEEP THESE
const denominator = 10**10;
const dayToSecond = 86400;

await Portal.initiateOperator(
    id,
    Math.floor((fee * denominator) / 100),
    validatorPeriod * 86400,
    maintainer_address,
    {value: initial_wallet }
);
```

1. **ID:** your operator ID
2. **FEE**: Maintenance fee that will be charged from validator rewards, block rewards, and MEV rewards. 10^10 represents 100%, can be set to up to 10% (10^9). <mark style="color:blue;">Can be changed later.</mark>
3. **Validator Period**: Every validator has an expiration date. Should be between 90 - 1825 days, given in seconds. <mark style="color:blue;">Can be changed later.</mark>
4. **Maintainer**: Your automation script's address. <mark style="color:blue;">Can be changed later.</mark>


# Communicating with Portal

## Portal is The Main Gateway to Trustless Staking

Learn more about Portal here, if you want:

{% content-ref url="/pages/qcA5U4R0s0WrBrEKLyji" %}
[Portal](/key-concepts/portal)
{% endcontent-ref %}

#### Portal utilizes a Modular Architecture build on top of an Isolated Storage.

This is good for us, because we can add any functionality without minding the backward compatibility. It is good for the users because no one can touch their instance of the contract storage.&#x20;

However, this means, sadly, things are not that direct...

Learn more about it here, if you want:

{% content-ref url="/pages/f6aPTl3GvoGb7XFJpfTl" %}
[Isolated Storage](/key-concepts/portal/isolated-storage)
{% endcontent-ref %}

### TYPE

{% hint style="info" %}
We have already learned a bit about IDs while initiating our Operator.
{% endhint %}

There are many TYPEs that are supported by Portal. Modules like Withdrawal Contract, Liquidity Pools, Interfaces...&#x20;

However, as Node Operators, we are only interested in two of them: **Operator** and **Pool**.&#x20;

#### Representation of an Operator' storage space:

```javascript
const OPERATOR = {
"CONTROLLER": <address>,
"NAME": <bytes>,
"TYPE": 4 <uint>,
"initiated": <uint>,
"maintainer": <address>,
"totalProposedValidators": <uint>,
"totalActiveValidators": <uint>,
"feeSwitch": <uint>,
"priorFee": <uint>,
"fee": <uint>,
"periodSwitch": <uint>,
"priorPeriod": <uint>,
"validatorPeriod": <uint>,
"wallet": <uint>,
"released": <uint>
};
```

#### Representation of a Pool's storage space:

```javascript
const POOL= {
"CONTROLLER": <address>,
"NAME": <bytes>,
"TYPE": 5 <uint>,
"initiated": <uint>,
"maintainer": <address>,
"surplus": <uint>,
"secured": <uint>,
"allowance": {<OPERATOR>: <uint>},
"proposedValidators": {<OPERATOR>: <uint>},
"activeValidators": {<OPERATOR>: <uint>},
"interfaces": [<address>],
"private": <uint>, // 1 = true
"whitelist": <address>,
"withdrawalCredential": <bytes>,
"withdrawalContract": <address>,
"liquidityPool": <address>,
"liquidityPoolVersion": <uint>,
"feeSwitch": <uint>,
"priorFee": <uint>,
"fee": <uint>,
"wallet": <uint>,
"validators": [<bytes>]
};
```

> *surplus, allowance and withdrawalContract are super important for us!*&#x20;

### Reading variables from Portal

#### First, some helpers:

```javascript
const getBytes32 = (key) => {
  return ethers.utils.formatBytes32String(key);
};

const getBytes = (key) => {
 return Web3.utils.toHex(key);
};
```

#### Reading UINT variable:

```javascript
await PORTAL.readUintForId(
  id,
  getBytes32("surplus")
);
```

#### Reading ADDRESS variable:

```javascript
await PORTAL.readAddressForId(
  id,
  getBytes32("CONTROLLER")
);
```

#### Reading BYTES variable:

```javascript
await PORTAL.readBytesForId(
  id,
  getBytes32("withdrawalCredential")
);
```

### Reading Arrays from Portal

#### Reading UINT array:

```javascript
await PORTAL.readUintArrayForId(
  id,
  getBytes32("something"),
  index
);
```

#### Reading ADDRESS array:

```javascript
await PORTAL.readBytesArrayForId(
  id,
  getBytes32("interfaces"),
  index
);
```

#### Reading BYTES array:

```javascript
await PORTAL.readAddressArrayForId(
  id,
  getBytes32("validators"),
  index
);
```

### Reading Relational Data from Portal

#### Reading UINT data:

```javascript
await PORTAL.readUintForId(
  poolId,
  await PORTAL.getKey(operatorId, getBytes32("allowance"))
);
```

#### Reading ADDRESS data:

```javascript
await PORTAL.readAddressForId(
  poolId,
  await PORTAL.getKey(operatorId, getBytes32("something"))
);
```

#### Reading BYTES data:

```javascript
await PORTAL.readBytesForId(
  poolId,
  await PORTAL.getKey(operatorId, getBytes32("something"))
);
```

## <mark style="color:purple;">Thats it!</mark>


# Creating Validators

<figure><img src="/files/D9deIpxchEElfEnZsGbL" alt=""><figcaption></figcaption></figure>

{% content-ref url="/pages/E0XOdijxPxVbc4Shq5aR" %}
[A Validator's Lifecycle](/operator-marketplace/a-validators-lifecycle)
{% endcontent-ref %}

## 0.1. Create a pool - optional

It might take some time for other pools to give you an allowance.

It is best to create some pools to start testing immediately.

We will provide some Goerli Ether upon onboarding.

#### Create a basic pool easily:

{% content-ref url="/pages/RCqdgs3oJRdoI3k4krUq" %}
[Initiating a Customizable Staking Pool](/ethereum-guides/staking-pool-handbook/initiating-a-customizable-staking-pool)
{% endcontent-ref %}

#### Give Yourself allowance:

{% content-ref url="/pages/D5CDHSbTKimzVBsqA7u9" %}
[Managing Your Operator Set](/ethereum-guides/staking-pool-handbook/managing-your-operator-set)
{% endcontent-ref %}

## 0.2 Fund Your Wallet

### Internal Wallet

Every ID has an Internal Wallet, which makes transferring Ether easier for both Geode's Portal, and it's users.

{% hint style="info" %}
The Internal Wallet is the place where your fees will accrue over time.
{% endhint %}

Because of [the bug explained here](https://medium.com/immunefi/rocketpool-lido-frontrunning-bug-fix-postmortem-e701f26d7971), you will need **1 Ether per validator proposal** available in your internal wallet.

<mark style="color:purple;">You will be reimbursed after activating the validator.</mark> However, this amount limits how many proposals you can have at the same time.

{% hint style="info" %}
If you have 100 Ether in your internal wallet, and if it takes 1 day for proposals to be approved:

* You can propose 100 validators a day.
  {% endhint %}

<pre class="language-javascript"><code class="lang-javascript"><strong>await Portal.increaseWalletBalance(id, {value: 100 eth});
</strong></code></pre>

#### Check Your Wallet Balance

```javascript
const balance = Portal.readUintForId(operatorId, getBytes("wallet"))
```

## 1. Pre-Proposal Checks&#x20;

{% hint style="danger" %} <mark style="color:red;">It is probably a good idea to initiate a couple staking pools and distribute your Goerli Funds among them, Someone else giving you allowance can take some time otherwise.</mark>&#x20;
{% endhint %}

#### Get the list of all Staking Pools:

<pre class="language-javascript"><code class="lang-javascript"><strong>const all_pool_ids_list = Portal.allIdsByType(5, index);
</strong></code></pre>

> Alternatively you can listen for **`OperatorApproval(indexed poolId,indexed yourId, amount);`**

#### Check Allowances

<pre class="language-javascript"><code class="lang-javascript"><strong>const allowance = Portal.readUintForId(
</strong><strong>    poolId,
</strong><strong>    Portal.getKey(
</strong><strong>        operatorId, 
</strong><strong>        getBytes32("allowance")
</strong><strong>    ));
</strong><strong>
</strong><strong>const proposedValidators = Portal.readUintForId(
</strong>    poolId,
    Portal.getKey(
        operatorId, 
        getBytes32("proposedValidators")
    ));

const activeValidators = Portal.readUintForId(
    poolId,
    Portal.getKey(
        operatorId, 
        getBytes32("activeValidators")
    ));
</code></pre>

> You can create new validators if <mark style="color:purple;">allowance is</mark> <mark style="color:purple;"></mark><mark style="color:purple;">**greater than**</mark> <mark style="color:purple;">`proposedValidators`</mark> <mark style="color:purple;">**+**</mark> <mark style="color:purple;">`activeValidators`</mark><mark style="color:purple;">.</mark>

#### Check Surplus

<pre class="language-javascript"><code class="lang-javascript"><strong>const surplus = Portal.readUintForId(poolId, getBytes("surplus"))
</strong></code></pre>

> Every 32 ETH in surplus means 1 potential validator.

#### Join the Race

When enough funds are pooled for a new validator, you will need to be faster than the other Operators with enough allowance.&#x20;

If you are the only Operator of the pool, you can take your time.

Otherwise, automate your tasks to be faster and capture the validator, or you will need to wait for another 32 Ether.

## 2. Proposing New Validators

### Get withdrawalCredential

It is very important for you to use pool specific withdrawalCredentials in your validators. Otherwise, your proposal will not be approved!

```javascript
await PORTAL.readAddressForId(
  id,
  getBytes32("withdrawalContract")
);

// or

await PORTAL.readBytesForId(
  id,
  getBytes32("withdrawalCredential")
);
```

### Staking Deposit Cli

We have forked the Ethereum's to add --amount parameter.

Using this CLI instead of the original one will allow you to customize the amount parameter:

{% embed url="<https://github.com/Geodefi/staking-deposit-cli>" %}

<pre class="language-bash"><code class="lang-bash">git clone https://github.com/Geodefi/staking-deposit-cli.git
cd staking-deposit-cli/
python3 -m pip3 install virtualenv
python3 -m virtualenv venv
source venv/bin/activate
python3 setup.py install
<strong>python3 -m pip3 install -r requirements.txt
</strong></code></pre>

### Create deposit data

Call these&#x20;

For signatures1:

* create with a new-mnemonic OR use an existing mnemonic but be careful with validator index.
* set --eth1\_withdrawal\_address  to withdrawalContract
* amount is 1

```bash
python3 ./staking_deposit/deposit.py new-mnemonic --num_validators=x --amount=1 --chain=prater --eth1_withdrawal_address 0xc82Ed5eC571673E6b18c4B092c9cbC4aE86C786e 
```

For signatures31:

* use the same mnemonic while creating signatures1.
* use the same validator index (0 if the same time).
* specify the amount of validators with --num\_validators
* use the same --eth1\_withdrawal\_address
* amount is 31

```
python ./staking_deposit/deposit.py existing-mnemonic --num_validators=x --amount=31 --mnemonic_language=english --chain=prater --eth1_withdrawal_address 0xc82Ed5eC571673E6b18c4B092c9cbC4aE86C786e
```

* Pubkeys of the deposit data files should match.

### Propose!

```solidity
Portal.proposeStake(
    uint256 poolId,
    uint256 operatorId,
    bytes[] calldata pubkeys,
    bytes[] calldata signatures1,
    bytes[] calldata signatures31
    ) 
```

* **signatures1**: signature that will be used while proposing validators, *sending 1 Ether to Deposit Contract.*
* **signatures31**: signature that will be used while activating validators, *sending 31 Ether to Deposit Contract.*

## 3. Check if You Can Stake for Your Proposal:

```javascript
await Portal.canStake(pubkey);
```

It takes less than 24 hours for the Beacon Chain and our Oracle to verify a proposal.

## 4. Batch Validator Activation!

If your proposal is approved, you can use the pooled funds. However, you can save gas by doing Batch Activations:

```solidity
Portal.beaconStake(uint256 operatorId, bytes[] calldata pubkeys);
```

{% hint style="info" %}
**Save gas cost:**

Pub-keys should be arranged by pool ids.&#x20;

For example: pub-keys = \[pk1, pk2, pk3, pk4, pk5, pk6, pk7]

* pk1, pk2, pk3 from pool1
* pk4, pk5 from pool2
* pk6 from pool3

Etc.
{% endhint %}


# Changing an Operator's Owner

## <mark style="color:purple;">CONTROLLER</mark>

"**CONTROLLER**" key stands for the owner of the ID of a given Operators.

### Who Is the Current Owner?

<pre class="language-javascript"><code class="lang-javascript"><strong>const getBytes = (key) => {
</strong> return Web3.utils.toHex(key);
};

const owner = Portal.readAddressForId(id, getBytes("CONTROLLER"))
</code></pre>

### Set a New Owner

#### 1. Which address is the new owner?

This might be a developer's address, a developers' multisig, or a Token address.&#x20;

#### <mark style="color:red;">2. Double check the new address of your Controller.</mark>

#### 3. Call `changeIdCONTROLLER()` in Portal with ID of your Operator, and the address of your new Controller.&#x20;

```solidity
Portal.changeIdCONTROLLER(uint256 id, address newCONTROLLER)
```

#### Changing your Controller is easy, however it will override the ability of the previous Controller <mark style="color:red;">immediately</mark>.&#x20;

{% hint style="danger" %} <mark style="color:red;">**After changing your CONTROLLER, you will not be able to take this action back by using your old CONTROLLER address.**</mark>
{% endhint %}


# Switching Your Fee

#### Changing your fee doesn't affect the previously created validators!

Learn more about the Validator Lifecycle:

{% content-ref url="/pages/E0XOdijxPxVbc4Shq5aR" %}
[A Validator's Lifecycle](/operator-marketplace/a-validators-lifecycle)
{% endcontent-ref %}

## Changing Your Fee

You can charge up to 10% of the pooled rewards for your *new* validators.

```javascript
const new_fee = Math.floor(x * 10**10 /100) // x%

await Portal.switchMaintenanceFee(id, new_fee)
```

{% hint style="info" %}

#### 3 Day Rule

When a Operator's fee is changed, it takes 3 days for new fee to take effect.&#x20;

<mark style="color:blue;">Within this period of 3 days, the fee can not be changed again.</mark>

This applies to Pool Fees as well, and prevents misleading behavior within our marketplace.

However, you can stop proposing new validators before your cool-down period ends.
{% endhint %}

## Claiming Your Fees

#### Internal Wallet

Every ID has an Internal Wallet, which makes transferring Ether easier for both Geode's Portal, and it's users.

The Internal Wallet is the place where your fees will accrue over time.

```javascript
const wallet_balance = Portal.readUintForId(id, getBytes("wallet"));

await Portal.decreaseWalletBalance(id, wallet_balance);
```


# Switching Your Validator Period

## Changing Your Validator Period

Your validator Period can be 90 - 1825 days, and should be defined in seconds.

```javascript
const new_period_in_days = <x> * 24 * 60 * 60;
await Portal.switchValidatorPeriod(id, new_period_in_days)
```

{% hint style="info" %}

#### 3 Day Rule

When a Operator's period is changed, it takes 3 days for new period to take effect.&#x20;

<mark style="color:blue;">Within this 3 day time span, the period can not be changed again.</mark>

However, you can stop proposing new validators before your cool-down period ends.
{% endhint %}


# Using Maintainers

### Why Use Maintainers?

For an Operator, ownership and maintenance are two tasks with different risk factors.

#### To make things easier for you, we've introduced Maintainers:

A special address that has limited capabilities.

#### Keep the ownership of your Operator safe with a multisig setup, while allowing a script to automate your daily tasks.

Learn more about them here:

{% content-ref url="/pages/pr7YAwNKRplvqovwxwxF" %}
[Maintainers](/key-concepts/permissionless-configurable-staking-pools/maintainers)
{% endcontent-ref %}

### Setting Your Maintainer

You can set any address as your maintainer, <mark style="color:red;">but it is not safe to trust random addresses!</mark>

You will be held responsible for faulty validator proposals, and other mistakes that your maintainer makes.

```javascript
Portal.changeMaintainer(id, newMaintainer);
```


# Optimizing Your Revenue

## Better Performing Validators Mean More Revenue

#### It is important to underline that your performance gets you profit, instead of sharing everything with the other Node Operators all the time, with linear distribution.

Other Operators do not affect you, and you do not affect other Operators.

You will only get fees from the generated capital your validators provide.

By providing better returns, more market participants will choose to create validators with you.

Outperform the other Operators, and get more validators!&#x20;

### Use MEV&#x20;

{% hint style="success" %} <mark style="color:green;">Node Operators also collect the same percentage of fees from the rewards / MEV profit from their validators!</mark>
{% endhint %}

You can get up to 10% of the MEV revenue and block rewards generated by your validators.

#### Node Operators need to provide the appropriate fee recipient for the block rewards and MEV profits.

Unlike other staking pools, which pools the MEV and block rewards directly, or even uses it to create more validators instantly; Geode sets them aside in a contract called `WithdrawalContract`.&#x20;

Every staking pool has a `WithdrawalContract`.

So, for every validator, there is a distinct address that comes from its origin Pool:

```javascript
Portal.readAddressForId(id, getBytes("WithdrawalContract"));
```

{% hint style="danger" %} <mark style="color:red;">Fee theft is detected with Telescope...</mark>
{% endhint %}

### Lower Your Fees

Geode is a competitive marketplace, and you might attract more validators if you lower your fees.

### Lower Your Validator Period

By promising a faster return, you can attract more validators.


# Exiting Validators

{% hint style="warning" %} <mark style="color:orange;">Under construction.</mark>
{% endhint %}


# Liquidity Pool HandBook

<mark style="color:orange;">Under construction.</mark>


# Staking Pool Handbook

{% hint style="warning" %}
Geode is preparing for an upgrade on it's Avalanche Infrastructure that will make it compatible with the Ethereum Infrastructure, and features many other improvements.

**Currently, we are not onboarding new staking pools on Avalanche.**
{% endhint %}


# Operator Handbook

{% hint style="warning" %}
Geode is preparing for an upgrade on it's Avalanche Infrastructure that will make it compatible with the Ethereum Infrastructure, and features many other improvements.

**Currently, we are not onboarding new Operators on Avalanche.**
{% endhint %}


# Networks


# Live Contracts

These section will be updated after the report.


# Avalanche v1

{% hint style="warning" %}
Geode is preparing for an upgrade on it's Avalanche Infrastructure that will make it compatible with the Ethereum Infrastructure, and features many other improvements.

**Currently, Geode is not publicly available on Avalanche.**
{% endhint %}


# Ethereum v2


# gETH.sol


# Portal.sol

## GOERLI DEPLOYMENT

{% embed url="<https://goerli.etherscan.io/address/0xb0334f08dec465ec180f1af04c6d7d3737407083>" %}

## GOERLI ABI

{% file src="/files/Kdc51nXPrzxUQ81sjAoQ" %}


# globals.sol


# DataStoreUtilsLib.sol


# GeodeUtilsLib.sol


# DepositContractUtilsLib.sol


# OracleUtilsLib.sol


# StakeUtilsLib.sol


# Swap.sol


# AmplificationUtils.sol


# MathUtils.sol


# SwapUtils.sol


# LPToken.sol


# WithdrawalContract.sol


# Interfaces


# ERC20InterfaceUpgaradable.sol

## Important changes to the ERC20 implementation

#### ERC20Interface will be using the balance info coming from gAVAX, so there is no *\_balances*&#x20;

```solidity
    /**
     * @dev gAVAX ERC20 interface doesn't use balance info, catches it from ERC1155.
     * mapping(address => uint256) private _balances;
    **/ 
    function _transfer(...) internal virtual {
        ...
        unchecked {
            _ERC1155.safeTransferFrom(sender,recipient,_id,amount,"0x00");
        }
        ...
    }
```

#### There is also a function for *pricePerShare,* so it is easy for any code to keep track of underlying AVAX balances.

```solidity
function pricePerShare() public view returns(uint){
            return _ERC1155.pricePerShare(_id);
    }
```

#### Balance info for the used ID's ERC20interface will show the gAVAX balance info.&#x20;

```solidity
function balanceOf(address account) public view virtual override returns (uint256) {
        return _ERC1155.balanceOf(account,_id);
    }
```

#### TotalSupply info for the used ID's ERC20interface will show the gAVAX totalSupply info.&#x20;

```solidity
    /**
     * @dev gAVAX ERC20 interface doesn't use totalSupply info, catches it from ERC1155.
     * uint256 private _totalSupply;
    **/ 
    function totalSupply() public view virtual override returns (uint256) {
        return _ERC1155.totalSupply(_id);
    }
```

{% hint style="danger" %}
**Note, these code pieces should NOT be used in production.**
{% endhint %}

### See it on [Diffchecker.](https://www.diffchecker.com/0PlrxJT9)

### See it on [Github.](https://github.com/Geodefi/Portal-Avax/blob/dev/contracts/Portal/gAvaxInterfaces/ERC20InterfaceUpgradable.sol)


# ERC20InterfacePermitUpgradable.sol

Differences between Geode's ERC20InterfacePermit and [Openzeppelin's implementation of ERC20Permit](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/54803be62207c2412e27d09325243f2f1452f7b9/contracts/token/ERC20/extensions/draft-ERC20PermitUpgradeable.sol) is:

* pragma set to `=0.8.7;`
* using ERC20Interface instead of ERC20
* added initialize

### See it on [Diffchecker.](< https://www.diffchecker.com/Hwmvi5HF >)

## See it on[ Github.](https://github.com/Geodefi/Portal-Avax/blob/dev/contracts/Portal/gAvaxInterfaces/ERC20InterfaceUpgradable.sol)


# Audits

Security first!

This page currently includes the audits for the Portal-Eth implementation and our Withdrawal contract.

**Portal-Eth**

{% file src="/files/Kw7Jnh6WoHseX8BtOW45" %}
This audit is conducted by [Consensys Diligence](https://consensys.io/diligence/).
{% endfile %}

{% file src="/files/mwm9YqbbkR7vKBpmnucd" %}
This is a <mark style="color:blue;">response to the above audit</mark> prepared by Ice Bear.
{% endfile %}

{% file src="/files/cdbEdLDC89J8sHMcjSGc" %}
This is an <mark style="color:blue;">internal audit</mark> conducted by Crash Bandicoot.
{% endfile %}

{% file src="/files/5zhKAoRzEl65NmKhBikk" %}
This is the second audit conducted by [Consensys Diligence](https://consensys.io/diligence/).
{% endfile %}

{% file src="/files/kIh1UDI8RIxEqWS0reIw" %}
This audit is conducted by [Shieldify](https://shieldify.org).
{% endfile %}

**Withdrawal Contract**

{% file src="/files/0sqZsCJn31SdDgFgMxL9" %}
This audit is conducted by[ Consensys Diligence](https://consensys.io/diligence/).
{% endfile %}


# Bug Bounties

## Immunefi

{% hint style="success" %}
<https://immunefi.com/bounty/geodefinance/>
{% endhint %}


