Special thanks to Marco Besier, Emile , and 0x18a6 for reviewing the blog and providing valuable feedback. Your comments helped improve its clarity and accuracy.
<aside> 🧭
In this blog, you will learn:
Before going deeper, it is important to separate two things:
<aside> 🧽
Poseidon Hash ≠ Poseidon Permutation.
So:
$$ Poseidon \, Hash = Sponge \, construction + Poseidon \, permutation \, π $$
The permutation itself is not the full hash. It is the function used inside the hash.
State memory (S)
r (rate) how much data you can absorb per round. The initial state starts as all zeros.c security margin.S = r + c.Permutation / compression function $Poseidon^π$ $( f )$
S as input and outputs a state of the same length.S is updated each time it is processed by $f$.Padding function
M so its length becomes a multiple of the bitrate r.Squeeze phase (output generation)
r from the state at a time.Z = Z0 || Z1 || ... and truncate to the required length if needed.
Now let’s see how Poseidon uses the sponge construction.
Assume:
$$ t = 3 \\ r = 2 \\ c = 1 $$
So the state is:
$$ [x₀, x₁ | x₂] $$
Assume we want to hash:
$$ m = [5, 7, 9] $$
Since the rate is $r = 2$ we split the message into chunks of 2 elements:
$$ m₁ = [5, 7] \\ m₂ = [9, pad] $$
The second chunk needs padding because it only has one element.
The sponge starts from the all-zero state:
$$ S₀ = [0, 0 | 0] $$
First chunk:
$$ m₁ = [5, 7] $$
Add it into the rate part:
[5, 7 | 0] $$
Then apply the full Poseidon permutation:
$$ π([5, 7 | 0]) = [a, b | cap₁] $$
Important:
$$ π = full \, Poseidon \, permutation $$
It is not one round. It contains many internal Hades rounds.
Second chunk:
$$ m₂ = [9, pad] $$
Current state:
$$ [a, b | cap₁] $$
Absorb the second chunk into the rate part:
[a + 9, b + pad | cap₁] $$
Then apply the full Poseidon permutation again:
$$ π([a + 9, b + pad | cap₁]) = [h₀, h₁ | cap₂] $$
The output is taken from the rate part:
$$ [h₀, h₁] $$
If we need one hash element:
$$ hash = h₀ $$
If we need two output elements:
$$ hash = [h₀, h₁] $$
If we need more output elements than the rate allows, we apply the permutation again and keep reading from the rate part.
This is called squeezing.

Many descriptions write:
$$ I_c \oplus m_1 $$