Skip to content

Commit

Permalink
Add tests and update curve consts
Browse files Browse the repository at this point in the history
  • Loading branch information
ogtownsend committed Jan 21, 2025
1 parent e375627 commit 5353774
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 10 deletions.
26 changes: 18 additions & 8 deletions core/services/ocr2/plugins/ccip/internal/ccipcalc/calc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/logger"
)

const (
// DESTINATION_ETH_PPB_GATE is the deviation threshold when writing to ethereum's PriceRegistry
ETHEREUM_THRESHOLD_GATE_PPB = 4e9
)

// ContiguousReqs checks if seqNrs contains all numbers from min to max.
func ContiguousReqs(lggr logger.Logger, min, max uint64, seqNrs []uint64) bool {
if int(max-min+1) != len(seqNrs) {
Expand Down Expand Up @@ -68,26 +73,31 @@ func Deviates(x1, x2 *big.Int, ppb int64) bool {
// DeviatesOnGasCurve calculates a deviation threshold on the fly using xNew. For now it's only used for gas price
// deviation calculation. It's important to make sure the order of xNew and xOld is correct when passed into this
// function to get an accurate deviation threshold.
func DeviatesOnGasCurve(xNew, xOld *big.Int, ppb int64) bool {
// If ppb from config is not equal to 4000000000, do not apply the gas curve. This is a temporary gating mechanism
// that ensures we only apply the gas curve deviation logic to eth-bound price updates.
if ppb != 4000000000 {
func DeviatesOnGasCurve(xNew, xOld, noDeviationLowerBound *big.Int, ppb int64) bool {
// This is a temporary gating mechanism that ensures we only apply the gas curve deviation logic to eth-bound price
// updates. If ppb from config is not equal to 4000000000, do not apply the gas curve.
if ppb != ETHEREUM_THRESHOLD_GATE_PPB {
return Deviates(xOld, xNew, ppb)
}

// If xNew < noDeviationLowerBound, Deviates should never be true
if xNew.Cmp(noDeviationLowerBound) < 0 {
return false
}

xNewFloat := new(big.Float).SetInt(xNew)
xNewFloat64, _ := xNewFloat.Float64()

// Calculate the deviation threshold percentage with xNew using the formula: y = (5.64e10) / (x^0.654)
const constantFactor = 5.64e10
const exponent = 0.654
// Calculate the deviation threshold percentage with xNew using the formula: y = (10e11) / (x^0.665)
const constantFactor = 10e11
const exponent = 0.665
xNewPower := math.Pow(xNewFloat64, exponent)
threshold := constantFactor / xNewPower

// Convert percentage to PPB
thresholdPPB := int64(threshold * 1e7)

return Deviates(xOld, xNew, thresholdPPB)
return Deviates(xNew, xOld, thresholdPPB)
}

func MergeEpochAndRound(epoch uint32, round uint8) uint64 {
Expand Down
72 changes: 72 additions & 0 deletions core/services/ocr2/plugins/ccip/internal/ccipcalc/calc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,75 @@ func TestDeviates(t *testing.T) {
})
}
}

func TestDeviatesOnGasCurve(t *testing.T) {
type args struct {
xNew *big.Int
xOld *big.Int
noDev *big.Int
ppb int64
}
tests := []struct {
name string
args args
want bool
}{
{
name: "base case deviates from increase",
args: args{xNew: big.NewInt(4e14), xOld: big.NewInt(1e13), noDev: big.NewInt(3e13), ppb: ETHEREUM_THRESHOLD_GATE_PPB},
want: true,
},
{
name: "base case deviates from decrease",
args: args{xNew: big.NewInt(1e13), xOld: big.NewInt(4e15), noDev: big.NewInt(1), ppb: ETHEREUM_THRESHOLD_GATE_PPB},
want: true,
},
{
name: "does not deviate when equal",
args: args{xNew: big.NewInt(3e14), xOld: big.NewInt(3e14), noDev: big.NewInt(3e13), ppb: ETHEREUM_THRESHOLD_GATE_PPB},
want: false,
},
{
name: "does not deviate with small difference when xNew is bigger",
args: args{xNew: big.NewInt(3e14 + 1), xOld: big.NewInt(3e14), noDev: big.NewInt(3e13), ppb: ETHEREUM_THRESHOLD_GATE_PPB},
want: false,
},
{
name: "does not deviate with small difference when xOld is bigger",
args: args{xNew: big.NewInt(3e14), xOld: big.NewInt(3e14 + 1), noDev: big.NewInt(3e13), ppb: ETHEREUM_THRESHOLD_GATE_PPB},
want: false,
},
{
name: "deviates when ppb is not equal to ETHEREUM_THRESHOLD_GATE_PPB",
args: args{xNew: big.NewInt(1e9), xOld: big.NewInt(2e9), noDev: big.NewInt(1), ppb: 1},
want: true,
},
{
name: "does not deviate when xNew is below noDeviationLowerBound",
args: args{xNew: big.NewInt(2e13), xOld: big.NewInt(1e13), noDev: big.NewInt(3e13), ppb: ETHEREUM_THRESHOLD_GATE_PPB},
want: false,
},
// thresholdPPB = (10e11) / (xNew^0.665) * 1e7
// diff = (xNew - xOld) / min(xNew, xOld) * 1e9
// Deviates = abs(diff) > thresholdPPB
{
name: "xNew is just below deviation threshold and does deviate",
args: args{xNew: big.NewInt(3e13), xOld: big.NewInt(2.519478222838e12), noDev: big.NewInt(1), ppb: ETHEREUM_THRESHOLD_GATE_PPB},
want: false,
},
{
name: "xNew is just above deviation threshold and does deviate",
args: args{xNew: big.NewInt(3e13), xOld: big.NewInt(2.519478222838e12 - 30), noDev: big.NewInt(1), ppb: ETHEREUM_THRESHOLD_GATE_PPB},
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equalf(
t,
tt.want,
DeviatesOnGasCurve(tt.args.xNew, tt.args.xOld, tt.args.noDev, tt.args.ppb),
"DeviatesOnGasCurve(%v, %v, %v, %v)", tt.args.xNew, tt.args.xOld, tt.args.noDev, tt.args.ppb)
})
}
}
12 changes: 11 additions & 1 deletion core/services/ocr2/plugins/ccip/prices/da_price_estimator.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc"
)

const (
// EXEC_NO_DEVIATION_THRESHOLD_USD is the lower bound no deviation threshold for exec gas. If the exec gas price is
// less than this value, we should never trigger a deviation. 0.00003 USD.
EXEC_NO_DEVIATION_THRESHOLD_USD = 3e13

// DA_NO_DEVIATION_THRESHOLD_USD is the lower bound no deviation threshold for DA gas. If the DA gas price is less
// than this value, we should never trigger a deviation. 0.00006 USD.
DA_NO_DEVIATION_THRESHOLD_USD = 6e13
)

type DAGasPriceEstimator struct {
execEstimator GasPriceEstimator
l1Oracle rollups.L1Oracle
Expand Down Expand Up @@ -135,7 +145,7 @@ func (g DAGasPriceEstimator) Deviates(ctx context.Context, p1, p2 *big.Int) (boo
return execDeviates, nil
}

return ccipcalc.DeviatesOnGasCurve(p1DAGasPrice, p2DAGasPrice, g.daDeviationPPB), nil
return ccipcalc.DeviatesOnGasCurve(p1DAGasPrice, p2DAGasPrice, big.NewInt(DA_NO_DEVIATION_THRESHOLD_USD), g.daDeviationPPB), nil
}

func (g DAGasPriceEstimator) EstimateMsgCostUSD(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int, msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (g ExecGasPriceEstimator) Median(ctx context.Context, gasPrices []*big.Int)
}

func (g ExecGasPriceEstimator) Deviates(ctx context.Context, p1 *big.Int, p2 *big.Int) (bool, error) {
return ccipcalc.DeviatesOnGasCurve(p1, p2, g.deviationPPB), nil
return ccipcalc.DeviatesOnGasCurve(p1, p2, big.NewInt(EXEC_NO_DEVIATION_THRESHOLD_USD), g.deviationPPB), nil
}

func (g ExecGasPriceEstimator) EstimateMsgCostUSD(ctx context.Context, p *big.Int, wrappedNativePrice *big.Int, msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error) {
Expand Down

0 comments on commit 5353774

Please sign in to comment.