Skip to content

feat: get slashable stake from contract call #265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
with:
repository: layr-labs/eigensdk-go
token: ${{ github.token }}
ref: 525ebfea245aadbd0497a5be2999c3b19dbbd68b
ref: 7d3c828d8b48fd334d1805c2ecc27cddb7b20487

- name: Run anvil chain
run: |
Expand Down Expand Up @@ -96,7 +96,7 @@ jobs:
with:
repository: layr-labs/eigensdk-go
token: ${{ github.token }}
ref: 525ebfea245aadbd0497a5be2999c3b19dbbd68b
ref: 7d3c828d8b48fd334d1805c2ecc27cddb7b20487
- name: Run anvil chain
run: |
nohup make start-anvil-with-contracts-deployed > nohup.out 2>&1 &
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/Layr-Labs/eigenlayer-contracts v0.3.2-mainnet-rewards
github.com/Layr-Labs/eigenlayer-rewards-proofs v0.2.12
github.com/Layr-Labs/eigenpod-proofs-generation v0.0.14-stable.0.20240730152248-5c11a259293e
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241216183922-525ebfea245a
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241217185241-7d3c828d8b48
github.com/blang/semver/v4 v4.0.0
github.com/consensys/gnark-crypto v0.12.1
github.com/ethereum/go-ethereum v1.14.5
Expand Down
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ github.com/Layr-Labs/eigenlayer-rewards-proofs v0.2.12 h1:G5Q1SnLmFbEjhOkky3vIHk
github.com/Layr-Labs/eigenlayer-rewards-proofs v0.2.12/go.mod h1:OlJd1QjqEW53wfWG/lJyPCGvrXwWVEjPQsP4TV+gttQ=
github.com/Layr-Labs/eigenpod-proofs-generation v0.0.14-stable.0.20240730152248-5c11a259293e h1:DvW0/kWHV9mZsbH2KOjEHKTSIONNPUj6X05FJvUohy4=
github.com/Layr-Labs/eigenpod-proofs-generation v0.0.14-stable.0.20240730152248-5c11a259293e/go.mod h1:T7tYN8bTdca2pkMnz9G2+ZwXYWw5gWqQUIu4KLgC/vM=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241213014620-7831a35a43a7 h1:58JjbKZs0oaGRQv/AU+XtqWvD3+dyKM4NIbqjACANN0=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241213014620-7831a35a43a7/go.mod h1:aYdNURUhaqeYOS+Cq12TfSdPbjFfiLaHkxPdR4Exq/s=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241216183922-525ebfea245a h1:SW/dP6D6YjN3y/vXC++TBmekXo/fDGcPXoYHitARz/I=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241216183922-525ebfea245a/go.mod h1:aYdNURUhaqeYOS+Cq12TfSdPbjFfiLaHkxPdR4Exq/s=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241217185241-7d3c828d8b48 h1:tAuh8CCvqAY9tf8WUhAMdUFx2UiSqWfwrjmNB4prRfQ=
github.com/Layr-Labs/eigensdk-go v0.1.14-0.20241217185241-7d3c828d8b48/go.mod h1:aYdNURUhaqeYOS+Cq12TfSdPbjFfiLaHkxPdR4Exq/s=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
Expand Down
95 changes: 72 additions & 23 deletions pkg/operator/allocations/show.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package allocations

import (
"context"
"fmt"
"math/big"
"sort"
Expand Down Expand Up @@ -132,7 +133,7 @@ func showAction(cCtx *cli.Context, p utils.Prompter) error {
}

/*
5. Get the operator scaled shares for all strategies
5. Get the operator shares for all strategies
*/
operatorDelegatedSharesMap := make(map[string]*big.Int)
shares, err := elReader.GetOperatorShares(ctx, config.operatorAddress, config.strategyAddresses)
Expand All @@ -144,24 +145,43 @@ func showAction(cCtx *cli.Context, p utils.Prompter) error {
}

/*
6. Using all of the above, calculate SlashableMagnitudeHolders object
for displaying the allocation state of the operator
6. Using all of the above, get Slashable Shares for the operator
*/
slashableSharesMap, err := getSlashableShares(
ctx,
config.operatorAddress,
registeredOperatorSets,
config.strategyAddresses,
elReader,
)
if err != nil {
return eigenSdkUtils.WrapError("failed to get slashable shares", err)
}

/*
7. Using all of the above, calculate SlashableMagnitudeHolders object
for displaying the allocation state of the operator
*/
slashableMagnitudeHolders := make(SlashableMagnitudeHolders, 0)
dergisteredOpsets := make(DeregsiteredOperatorSets, 0)
for strategy, allocations := range allAllocations {
logger.Debugf("Strategy: %s, Allocations: %v", strategy, allocations)
strategyShares := operatorDelegatedSharesMap[strategy]
totalMagnitude := totalMagnitudeMap[strategy]
for _, alloc := range allocations {
currentShares, currentSharesPercentage := getSharesFromMagnitude(
strategyShares,
alloc.CurrentMagnitude.Uint64(),
)
currentShares := slashableSharesMap[gethcommon.HexToAddress(strategy)][getUniqueKey(alloc.AvsAddress, alloc.OperatorSetId)]
currentSharesPercentage := getSharePercentage(currentShares, strategyShares)

newMagnitudeBigInt := big.NewInt(0)
if alloc.PendingDiff.Cmp(big.NewInt(0)) != 0 {
newMagnitudeBigInt = big.NewInt(0).Add(alloc.CurrentMagnitude, alloc.PendingDiff)
}
newShares, newSharesPercentage := getSharesFromMagnitude(strategyShares, newMagnitudeBigInt.Uint64())

newShares, newSharesPercentage := getSharesFromMagnitude(
strategyShares,
newMagnitudeBigInt.Uint64(),
totalMagnitude,
)

// Check if the operator set is not registered and add it to the unregistered list
// Then skip the rest of the loop
Expand Down Expand Up @@ -235,36 +255,65 @@ func showAction(cCtx *cli.Context, p utils.Prompter) error {
return nil
}

func getSharesFromMagnitude(totalScaledShare *big.Int, magnitude uint64) (*big.Int, *big.Float) {
func getSharePercentage(shares *big.Int, totalShares *big.Int) *big.Float {
percentageShares := big.NewInt(1)
percentageShares = percentageShares.Mul(shares, big.NewInt(100))
percentageSharesFloat := new(
big.Float,
).Quo(new(big.Float).SetInt(percentageShares), new(big.Float).SetInt(totalShares))
return percentageSharesFloat
}

func getSlashableShares(
ctx context.Context,
operatorAddress gethcommon.Address,
opSets []allocationmanager.OperatorSet,
strategyAddresses []gethcommon.Address,
reader elChainReader,
) (map[gethcommon.Address]map[string]*big.Int, error) {
result := make(map[gethcommon.Address]map[string]*big.Int)
for _, opSet := range opSets {
slashableSharesMap, err := reader.GetSlashableShares(ctx, operatorAddress, opSet, strategyAddresses)
if err != nil {
return nil, err
}

for strat, shares := range slashableSharesMap {
if _, ok := result[strat]; !ok {
result[strat] = make(map[string]*big.Int)
}
result[strat][getUniqueKey(opSet.Avs, opSet.Id)] = shares
}
}
return result, nil
}

func getSharesFromMagnitude(totalShare *big.Int, magnitude uint64, totalMagnitude uint64) (*big.Int, *big.Float) {
/*
* shares = totalScaledShare * magnitude / PrecisionFactor
* percentageShares = (shares / totalScaledShare) * 100
* shares = totalShare * magnitude / totalMagnitude
* percentageShares = (shares / totalShare) * 100
*/
// Check for zero magnitude or totalScaledShare to avoid divide-by-zero errors
if magnitude == 0 || totalScaledShare.Cmp(big.NewInt(0)) == 0 {
if magnitude == 0 || totalShare.Cmp(big.NewInt(0)) == 0 {
return big.NewInt(0), big.NewFloat(0)
}

slashableMagBigInt := big.NewInt(1)
slashableMagBigInt = slashableMagBigInt.SetUint64(magnitude)

scaledOpShares := big.NewInt(1)
scaledOpShares = scaledOpShares.Set(totalScaledShare)
scaledOpShares = scaledOpShares.Div(scaledOpShares, PrecisionFactor)
shares := scaledOpShares.Mul(scaledOpShares, slashableMagBigInt)
opShares := big.NewInt(1)
opShares = opShares.Set(totalShare)
shares := opShares.Mul(opShares, big.NewInt(int64(magnitude)))
shares = shares.Div(shares, big.NewInt(int64(totalMagnitude)))

percentageShares := big.NewInt(1)
percentageShares = percentageShares.Mul(scaledOpShares, big.NewInt(100))
percentageShares = percentageShares.Mul(opShares, big.NewInt(100))
percentageSharesFloat := new(
big.Float,
).Quo(new(big.Float).SetInt(percentageShares), new(big.Float).SetInt(totalScaledShare))
).Quo(new(big.Float).SetInt(percentageShares), new(big.Float).SetInt(totalShare))

return shares, percentageSharesFloat
}

func getUniqueKey(strategyAddress gethcommon.Address, opSetId uint32) string {
return fmt.Sprintf("%s-%d", strategyAddress.String(), opSetId)
func getUniqueKey(avsAddress gethcommon.Address, opSetId uint32) string {
return fmt.Sprintf("%s-%d", avsAddress.String(), opSetId)
}

func readAndValidateShowConfig(cCtx *cli.Context, logger *logging.Logger) (*showConfig, error) {
Expand Down
6 changes: 6 additions & 0 deletions pkg/operator/allocations/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ type elChainReader interface {
operator gethcommon.Address,
strategy gethcommon.Address,
) (uint64, error)
GetSlashableShares(
ctx context.Context,
operatorAddress gethcommon.Address,
operatorSet allocationmanager.OperatorSet,
strategies []gethcommon.Address,
) (map[gethcommon.Address]*big.Int, error)
}

func UpdateCmd(p utils.Prompter) *cli.Command {
Expand Down
10 changes: 10 additions & 0 deletions pkg/operator/allocations/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"math"
"math/big"
"os"
"testing"

Expand Down Expand Up @@ -76,6 +77,15 @@ func (f *fakeElChainReader) GetAllocatableMagnitude(
return magnitude, nil
}

func (f *fakeElChainReader) GetSlashableShares(
ctx context.Context,
operatorAddress gethcommon.Address,
operatorSet allocationmanager.OperatorSet,
strategies []gethcommon.Address,
) (map[gethcommon.Address]*big.Int, error) {
return nil, errors.New("not implemented")
}

func TestGenerateAllocationsParams(t *testing.T) {
avsAddress := testutils.GenerateRandomEthereumAddressString()
strategyAddress := testutils.GenerateRandomEthereumAddressString()
Expand Down
Loading