Skip to content

Commit

Permalink
Agent liquidation value (#59)
Browse files Browse the repository at this point in the history
* Clean up types, delete unused code

* More type cleanup

* Fetch MinerInfo directly from state, not api

* Return Vesting and pledged bal in PreviewTerminateSectorsReturn

* Cleanup agent liquidation summary method

* Add helper methods to the PreviewAgentTerminationSummary struct

* Move test helpers to utils package

* Add tests

* Add Agent Liquid balance for ADO integration

* Delete max withdraw query

* Update mocks

* Fix max borrow helpers

Fix tests and tweak rr calc

* Polish

* Use new liquidation value in econ.ComputeAgentData

* Prepare for set-recovered handling of faulty agents

* Prepare for set-recovered with agents with bad LV's

* Update types

* Remove incomplete test

* Fix AgentMaxBorrow

* Add AgentCollateralStatsQuick method

* Update types

* Improve naming, add Summarize fn

* Add LTV helper to PreviewATS struct

* Updated off-chain termination calculation for network v12

Requires Lotus build on master branch with this PR:

* filecoin-project/lotus#11566

* Use StateCall instead of StateCompute for on-chain terminations

* Check early terminations in state for on-chain

* Remove debug code

* Update go sum

* Change ComputeAgentData func sig

* Add econ package tests

* Remove old unused code

* Update naming

* Update use of WAD math

---------

Co-authored-by: Jim Pick <[email protected]>
  • Loading branch information
Schwartz10 and Jim Pick authored Jan 24, 2024
1 parent 281b474 commit 723c8a7
Show file tree
Hide file tree
Showing 23 changed files with 1,077 additions and 1,064 deletions.
7 changes: 7 additions & 0 deletions constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ var (
var dialAddr = "https://api.node.glif.io/rpc/v1"
var t_dialAddr = "https://api.calibration.node.glif.io/rpc/v1"

var EventsURL = "https://events.glif.link"

var MAX_UINT256 = new(big.Int).Sub(new(big.Int).Exp(big.NewInt(2), big.NewInt(256), nil), big.NewInt(1))
var WAD = big.NewInt(1e18)

Expand All @@ -64,3 +66,8 @@ var INFINITY_POOL_ID = big.NewInt(0)
var CHUNKSIZE = big.NewInt(50000)

var FAULTY_SECTOR_TOLERANCE = big.NewFloat(0.001)

// NOTE these should be generated in the future from the live values in the contracts
var MAX_DTE = big.NewInt(2e18)
var MAX_LTV = big.NewInt(8e17)
var MAX_DTI = big.NewInt(25e16)
79 changes: 30 additions & 49 deletions econ/econ.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/chain/types"
"github.com/glifio/go-pools/constants"
"github.com/glifio/go-pools/mstat"
poolstypes "github.com/glifio/go-pools/types"
"github.com/glifio/go-pools/vc"
Expand All @@ -16,81 +16,62 @@ import (
func ComputeAgentData(
ctx context.Context,
sdk poolstypes.PoolsSDK,
agentLiquidAssets *big.Int,
agentAvailableBalance *big.Int,
principal *big.Int,
minerIDs []address.Address,
aggMinerStats *mstat.MinerStats,
agentAddr common.Address,
tsk *types.TipSet,
) (*vc.AgentData, error) {
lapi, closer, err := sdk.Extern().ConnectLotusClient()
if err != nil {
return nil, err
}
defer closer()

// here we just work our way through the AgentData, computing each key
// TODO: could probably parellize this elegently to speed things up
data := &vc.AgentData{}

aggMinerStats, err := mstat.ComputeMinersStats(ctx, minerIDs, tsk, lapi)
if err != nil {
return nil, err
}

data.QaPower = aggMinerStats.QualityAdjPower

data.GreenScore = aggMinerStats.GreenScore

data.AgentValue = big.NewInt(0).Add(agentLiquidAssets, aggMinerStats.Balance)

data.LiveSectors = aggMinerStats.LiveSectors
data.FaultySectors = aggMinerStats.FaultySectors
data.AgentValue = big.NewInt(0).Add(agentAvailableBalance, aggMinerStats.Balance)

/* ~~~~~ CollateralValue ~~~~~ */

// CV = AgentValue * terminationPenalty
data.CollateralValue = CollateralValue(data.AgentValue)

/* ~~~~~ ExpectedDailyFaultPenalties ~~~~~ */

// COULD REMOVE
data.ExpectedDailyFaultPenalties = aggMinerStats.PenaltyFaultPerDay

/* ~~~~~ ExpectedDailyRewards ~~~~~ */
ats, err := sdk.Query().AgentPreviewTerminationPrecise(ctx, agentAddr, tsk)
if err != nil {
return nil, err
}
// here we replace the ats.AgentAvailableBal with the agentAvailableBalance passed in this call to compute the post-action liquidation value
ats.AgentAvailableBal = agentAvailableBalance

data.ExpectedDailyRewards = aggMinerStats.ExpectedDailyReward
data.CollateralValue = ats.LiquidationValue()

/* ~~~~~ Principal ~~~~~ */
data.Principal = principal

// TODO: What to do on a Pay action type? -> deduce principal _after_ the payment is made

/* ~~~~~ GCRED ~~~~~ */
/* ~~~~~ SectorInfo ~~~~~ */
data.LiveSectors = aggMinerStats.LiveSectors

// exposure at default is current principal, including newPrincipal
var ead = data.Principal
// loan to value computation uses agent's total value, less principal as its denominator
// valueDenominator := lockedFunds.Balance.Add(lockedFunds.Balance, agentLiquidAssets)
// subtract liabilities (upcoming payment or withdrawal) from the denominator
// valueDenominator = valueDenominator.Sub(valueDenominator, deductibles)
// if the LTV (loan to liquidationm value) is greater than the max LTV, we report faulty sectors in order to trigger a liquidation
// this is a bit of a workaround until the liquidation value buffer is built-in to the contracts directly
// using wad math
numerator := new(big.Int).Mul(principal, constants.WAD)

var ltv = LoanToValueRatio(ead, data.AgentValue)
// loan to collateral value
var ltcv = LoanToCollateralRatio(ead, data.CollateralValue)
if (new(big.Int).Div(numerator, data.CollateralValue)).Cmp(constants.MAX_LTV) > 0 {
// 100% faulty sectors if loan to liquidation value buffer is breached
data.FaultySectors = aggMinerStats.LiveSectors
} else {
data.FaultySectors = aggMinerStats.FaultySectors
}

var equity = big.NewInt(0).Sub(data.AgentValue, data.Principal)
/* ~~~~~ ExpectedDailyFaultPenalties ~~~~~ */

var dte = DebtToEquityRatio(ead, equity)
// COULD REMOVE
data.ExpectedDailyFaultPenalties = aggMinerStats.PenaltyFaultPerDay

var faultRatio = big.NewFloat(0)
var vestingToPledgeRatio = big.NewFloat(0)
/* ~~~~~ ExpectedDailyRewards ~~~~~ */

if data.LiveSectors.Int64() > 0 {
faultRatio = faultRatio.Quo(new(big.Float).SetInt(data.FaultySectors), new(big.Float).SetInt(data.LiveSectors))
vestingToPledgeRatio = vestingToPledgeRatio.Quo(new(big.Float).SetInt(aggMinerStats.VestingFunds), new(big.Float).SetInt(aggMinerStats.PledgedFunds))
}
data.ExpectedDailyRewards = aggMinerStats.ExpectedDailyReward

data.Gcred = CreditScoreSimple(ead, ltv, ltcv, data.ExpectedDailyRewards, dte, faultRatio, vestingToPledgeRatio)
/* ~~~~~ GCRED (NOT IN USE) ~~~~~ */
data.Gcred = big.NewInt(100)

return data, nil
}
Loading

0 comments on commit 723c8a7

Please sign in to comment.