Skip to content

Commit

Permalink
writes
Browse files Browse the repository at this point in the history
  • Loading branch information
shrimalmadhur committed Jun 8, 2024
1 parent 6bcc901 commit 385c13c
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 1 deletion.
16 changes: 16 additions & 0 deletions pkg/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,20 @@ var (
Required: true,
Aliases: []string{"s"},
}

ShowMagnitudesFlag = cli.StringFlag{
Name: "show-magnitudes",
Usage: "Show magnitudes of stake share",
Required: true,
Aliases: []string{"m"},
}

RebalanceFilePathFlag = cli.PathFlag{
Name: "rebalance-file-path",
Usage: `Path to the CSV file.
The CSV file should have the following columns: operator set,allocation percentage.
This file must have all the operator sets and their allocation percentages for a strategy.`,
Required: true,
Aliases: []string{"r"},
}
)
1 change: 1 addition & 0 deletions pkg/operator/stakeallocation.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func StakeAllocationCmd(p utils.Prompter) *cli.Command {
Subcommands: []*cli.Command{
stakeallocation.ShowCmd(p),
stakeallocation.UpdateCmd(p),
stakeallocation.RebalanceCmd(p),
},
}
}
40 changes: 40 additions & 0 deletions pkg/operator/stakeallocation/rebalance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package stakeallocation

import (
"fmt"

"github.com/Layr-Labs/eigenlayer-cli/pkg/flags"
"github.com/Layr-Labs/eigenlayer-cli/pkg/telemetry"
"github.com/Layr-Labs/eigenlayer-cli/pkg/utils"
"github.com/urfave/cli/v2"
)

func RebalanceCmd(p utils.Prompter) *cli.Command {
return &cli.Command{
Name: "rebalance",
Aliases: []string{"r"},
Usage: "Rebalance stake allocation",
Description: `
Rebalance the stake allocation for the operator for a particular strategy.
This CSV file requires the following columns for only one stragegy:
operator_set,allocation percentage
Example
1,10
2,15
`,
Action: rebalanceStakeAllocation,
After: telemetry.AfterRunAction(),
Flags: []cli.Flag{
&flags.ConfigurationFileFlag,
&flags.DryRunFlag,
&flags.BroadcastFlag,
&flags.ShowMagnitudesFlag,
&flags.RebalanceFilePathFlag,
},
}
}

func rebalanceStakeAllocation(ctx *cli.Context) error {
fmt.Println("unimplemented")
return nil
}
2 changes: 1 addition & 1 deletion pkg/operator/stakeallocation/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/Layr-Labs/eigenlayer-cli/pkg/flags"
"github.com/Layr-Labs/eigenlayer-cli/pkg/telemetry"
"github.com/Layr-Labs/eigenlayer-cli/pkg/utils"

"github.com/urfave/cli/v2"
)

Expand Down
1 change: 1 addition & 0 deletions pkg/operator/stakeallocation/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func UpdateCmd(p utils.Prompter) *cli.Command {
&flags.BroadcastFlag,
&flags.AllocationPercentageFlag,
&flags.StakeSourceFlag,
&flags.ShowMagnitudesFlag,
},
}
}
Expand Down
113 changes: 113 additions & 0 deletions pkg/slashing/slashing.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package slashing

import (
"fmt"
"math"
)

type StakeSource string

const (
StakeSourceSlashable StakeSource = "slashable"
StakeSourceNonSlashable StakeSource = "non-slashable"
StakeSourceBoth StakeSource = "both"
)

type State struct {
totalMagnitude float64
operatorSets []int
slashableMagnitude []float64
}

func CalculateNewState(
oldState State,
stakeSource StakeSource,
operatorSet int,
slashableProportion float64,
) *State {

if stakeSource == StakeSourceSlashable {
// non slashable proportion
nonSlashableProportion := (oldState.totalMagnitude - sumFloatArray(oldState.slashableMagnitude)) / oldState.totalMagnitude
fmt.Println("nonSlashableProportion: ", nonSlashableProportion)

allocatedMagnitude := sumFloatArray(oldState.slashableMagnitude)
fmt.Println("allocatedMagnitude: ", allocatedMagnitude)

totalMagnitudeNew := allocatedMagnitude / (1 - slashableProportion - nonSlashableProportion)
fmt.Println("totalMagnitudeNew: ", totalMagnitudeNew)

slashableMagnitude := slashableProportion * totalMagnitudeNew
fmt.Println("slashableMagnitude: ", slashableMagnitude)

nonSlashableMagnitude := nonSlashableProportion * totalMagnitudeNew
fmt.Println("nonSlashableMagnitude: ", nonSlashableMagnitude)

opSetToUpdate := []int{operatorSet}
slashableMagnitudeSet := []float64{Round(slashableMagnitude, 10)}

return &State{
totalMagnitude: Round(totalMagnitudeNew, 10),
operatorSets: opSetToUpdate,
slashableMagnitude: slashableMagnitudeSet,
}
} else if stakeSource == StakeSourceNonSlashable {
// TODO: need to first verify if the operator set is already in the state
// and also if there is enough non slashable stake to allocate

return &State{
totalMagnitude: oldState.totalMagnitude,
operatorSets: []int{operatorSet},
slashableMagnitude: []float64{Round(oldState.totalMagnitude*slashableProportion, 10)},
}
} else {
// Stake is sourced from both slashable and non-slashable proportionally
}

// non slashable proportion
nonSlashableProportion := (oldState.totalMagnitude - sumFloatArray(oldState.slashableMagnitude)) / oldState.totalMagnitude
fmt.Println("nonSlashableProportion: ", nonSlashableProportion)

allocatedMagnitude := sumFloatArray(oldState.slashableMagnitude)
fmt.Println("allocatedMagnitude: ", allocatedMagnitude)

/*
i = new operator set
slashablePercentage = slashable magnitude (i) / total magnitude new
*/
totalMagnitudeNew := allocatedMagnitude / (1 - slashableProportion - nonSlashableProportion)
fmt.Println("totalMagnitudeNew: ", totalMagnitudeNew)

slashableMagnitude := slashableProportion * totalMagnitudeNew
fmt.Println("slashableMagnitude: ", slashableMagnitude)

nonSlashableMagnitude := nonSlashableProportion * totalMagnitudeNew
fmt.Println("nonSlashableMagnitude: ", nonSlashableMagnitude)

opSetToUpdate := []int{operatorSet}
slashableMagnitudeSet := []float64{Round(slashableMagnitude, 10)}

return &State{
totalMagnitude: Round(totalMagnitudeNew, 10),
operatorSets: opSetToUpdate,
slashableMagnitude: slashableMagnitudeSet,
}
}

func sumFloatArray(arr []float64) float64 {
sum := 0.0
for _, i := range arr {
sum += i
}
return sum
}

// Round rounds the floating point number to the specified number of decimal places.
func Round(val float64, places int) float64 {
if places < 0 {
return val
}
factor := math.Pow(10, float64(places))
return math.Round(val*factor) / factor
}
61 changes: 61 additions & 0 deletions pkg/slashing/slashing_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package slashing

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestCalculateNewState(t *testing.T) {

var tests = []struct {
name string
oldState State
stakeSource StakeSource
operatorSet int
slashableProportion float64
newState *State
}{
{
name: "Simple case where stake is sourced from slashable stake",
oldState: State{
totalMagnitude: 10,
operatorSets: []int{1, 2},
slashableMagnitude: []float64{1, 1},
},
stakeSource: StakeSourceSlashable,
operatorSet: 4,
slashableProportion: 0.1,
newState: &State{
totalMagnitude: 20.0,
operatorSets: []int{4},
slashableMagnitude: []float64{2.0},
},
},
{
name: "Simple case where stake is sourced from non slashable stake",
oldState: State{
totalMagnitude: 10,
operatorSets: []int{1, 2},
slashableMagnitude: []float64{1, 1},
},
stakeSource: StakeSourceNonSlashable,
operatorSet: 4,
slashableProportion: 0.1,
newState: &State{
totalMagnitude: 10.0,
operatorSets: []int{4},
slashableMagnitude: []float64{1.0},
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
newState := CalculateNewState(tt.oldState, tt.stakeSource, tt.operatorSet, tt.slashableProportion)
assert.Equal(t, tt.newState, newState)
})

}

}

0 comments on commit 385c13c

Please sign in to comment.