Skip to content

Commit

Permalink
FunctionsCoordinator v1.3.1 (#13815)
Browse files Browse the repository at this point in the history
* FunctionsCoordinator v1.3.1

* fix: add NPM token to fetch private repo

* fix: use npm config set

* revert

* add auth credentials

* add auth credentials

* remove auth for npm

---------

Co-authored-by: Pablo <[email protected]>
  • Loading branch information
KuphJr and ecPablo authored Jul 12, 2024
1 parent 055a9d2 commit fb177f4
Show file tree
Hide file tree
Showing 15 changed files with 206 additions and 137 deletions.
5 changes: 5 additions & 0 deletions .changeset/neat-peas-reflect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

#internal Updated wrappers for improved L1 -> L2 fee calculation for Functions
1 change: 1 addition & 0 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,7 @@ jobs:
docker rm "$CONTAINER_ID"
- name: Install Solana CLI # required for ensuring the local test validator is configured correctly
run: ./scripts/install-solana-ci.sh

- name: Install gauntlet
run: |
yarn --cwd ./gauntlet install --frozen-lockfile
Expand Down
5 changes: 5 additions & 0 deletions contracts/.changeset/serious-cats-fold.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@chainlink/contracts": patch
---

Implemented improved L1 fee calculation for L2 chains in Functions contracts
92 changes: 46 additions & 46 deletions contracts/gas-snapshots/functions.gas-snapshot

Large diffs are not rendered by default.

16 changes: 9 additions & 7 deletions contracts/src/v0.8/functions/dev/v1_X/FunctionsBilling.sol
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,15 @@ abstract contract FunctionsBilling is Routable, IFunctionsBilling {
gasPriceWei = s_config.minimumEstimateGasPriceWei;
}

uint256 gasPriceWithOverestimation = gasPriceWei +
((gasPriceWei * s_config.fulfillmentGasPriceOverEstimationBP) / 10_000);
/// @NOTE: Basis Points are 1/100th of 1%, divide by 10_000 to bring back to original units

uint256 executionGas = s_config.gasOverheadBeforeCallback + s_config.gasOverheadAfterCallback + callbackGasLimit;
uint256 l1FeeWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data);
uint96 estimatedGasReimbursementJuels = _getJuelsFromWei((gasPriceWithOverestimation * executionGas) + l1FeeWei);
uint256 l1FeeWei = ChainSpecificUtil._getL1FeeUpperLimit(s_config.transmitTxSizeBytes);
uint256 totalFeeWei = (gasPriceWei * executionGas) + l1FeeWei;

// Basis Points are 1/100th of 1%, divide by 10_000 to bring back to original units
uint256 totalFeeWeiWithOverestimate = totalFeeWei +
((totalFeeWei * s_config.fulfillmentGasPriceOverEstimationBP) / 10_000);

uint96 estimatedGasReimbursementJuels = _getJuelsFromWei(totalFeeWeiWithOverestimate);

uint96 feesJuels = uint96(donFeeJuels) + uint96(adminFeeJuels) + uint96(operationFeeJuels);

Expand Down Expand Up @@ -298,7 +300,7 @@ abstract contract FunctionsBilling is Routable, IFunctionsBilling {
FunctionsResponse.Commitment memory commitment = abi.decode(onchainMetadata, (FunctionsResponse.Commitment));

uint256 gasOverheadWei = (commitment.gasOverheadBeforeCallback + commitment.gasOverheadAfterCallback) * tx.gasprice;
uint256 l1FeeShareWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data) / reportBatchSize;
uint256 l1FeeShareWei = ChainSpecificUtil._getL1FeeUpperLimit(msg.data.length) / reportBatchSize;
// Gas overhead without callback
uint96 gasOverheadJuels = _getJuelsFromWei(gasOverheadWei + l1FeeShareWei);
uint96 juelsPerGas = _getJuelsFromWei(tx.gasprice);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ contract FunctionsCoordinator is OCR2Base, IFunctionsCoordinator, FunctionsBilli
using FunctionsResponse for FunctionsResponse.FulfillResult;

/// @inheritdoc ITypeAndVersion
string public constant override typeAndVersion = "Functions Coordinator v1.3.0";
string public constant override typeAndVersion = "Functions Coordinator v1.3.1";

event OracleRequest(
bytes32 indexed requestId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,6 @@ struct FunctionsBillingConfig {
uint224 fallbackNativePerUnitLink; // ═══════════╗ Fallback NATIVE CURRENCY / LINK conversion rate if the data feed is stale
uint32 requestTimeoutSeconds; // ════════════════╝ How many seconds it takes before we consider a request to be timed out
uint16 donFeeCentsUsd; // ═══════════════════════════════╗ Additional flat fee (denominated in cents of USD, paid as LINK) that will be split between Node Operators.
uint16 operationFeeCentsUsd; // ═════════════════════════╝ Additional flat fee (denominated in cents of USD, paid as LINK) that will be paid to the owner of the Coordinator contract.
uint16 operationFeeCentsUsd; // ║ Additional flat fee (denominated in cents of USD, paid as LINK) that will be paid to the owner of the Coordinator contract.
uint16 transmitTxSizeBytes; // ══════════════════════════╝ The size of the calldata for the transmit transaction in bytes assuming a single 256 byte response payload. Used to estimate L1 cost for fulfillments on L2 chains.
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@
pragma solidity ^0.8.19;

import {ArbGasInfo} from "../../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol";
import {GasPriceOracle} from "../../../../vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol";
import {GasPriceOracle} from "../../../../vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol";

/// @dev A library that abstracts out opcodes that behave differently across chains.
/// @dev The methods below return values that are pertinent to the given chain.
library ChainSpecificUtil {
// ------------ Start Arbitrum Constants ------------

/// @dev ARBGAS_ADDR is the address of the ArbGasInfo precompile on Arbitrum.
/// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbGasInfo.sol#L10
address private constant ARBGAS_ADDR = address(0x000000000000000000000000000000000000006C);
ArbGasInfo private constant ARBGAS = ArbGasInfo(ARBGAS_ADDR);
/// @dev ARB_DATA_PADDING_SIZE is the max size of the "static" data on Arbitrum for the transaction which refers to the tx data that is not the calldata (signature, etc.)
/// @dev reference: https://docs.arbitrum.io/build-decentralized-apps/how-to-estimate-gas#where-do-we-get-all-this-information-from
uint256 private constant ARB_DATA_PADDING_SIZE = 140;

uint256 private constant ARB_MAINNET_CHAIN_ID = 42161;
uint256 private constant ARB_GOERLI_TESTNET_CHAIN_ID = 421613;
Expand All @@ -21,13 +23,9 @@ library ChainSpecificUtil {
// ------------ End Arbitrum Constants ------------

// ------------ Start Optimism Constants ------------
/// @dev L1_FEE_DATA_PADDING includes 35 bytes for L1 data padding for Optimism
bytes internal constant L1_FEE_DATA_PADDING =
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
/// @dev OVM_GASPRICEORACLE_ADDR is the address of the GasPriceOracle precompile on Optimism.
/// @dev reference: https://community.optimism.io/docs/developers/build/transaction-fees/#estimating-the-l1-data-fee
address private constant OVM_GASPRICEORACLE_ADDR = address(0x420000000000000000000000000000000000000F);
GasPriceOracle private constant OVM_GASPRICEORACLE = GasPriceOracle(OVM_GASPRICEORACLE_ADDR);
/// @dev GAS_PRICE_ORACLE_ADDR is the address of the GasPriceOracle precompile on Optimism.
address private constant GAS_PRICE_ORACLE_ADDR = address(0x420000000000000000000000000000000000000F);
GasPriceOracle private constant GAS_PRICE_ORACLE = GasPriceOracle(GAS_PRICE_ORACLE_ADDR);

uint256 private constant OP_MAINNET_CHAIN_ID = 10;
uint256 private constant OP_GOERLI_CHAIN_ID = 420;
Expand All @@ -40,18 +38,17 @@ library ChainSpecificUtil {

// ------------ End Optimism Constants ------------

/// @notice Returns the L1 fees in wei that will be paid for the current transaction, given any calldata
/// @notice for the current transaction.
/// @notice When on a known Arbitrum chain, it uses ArbGas.getCurrentTxL1GasFees to get the fees.
/// @notice On Arbitrum, the provided calldata is not used to calculate the fees.
/// @notice On Optimism, the provided calldata is passed to the GasPriceOracle predeploy
/// @notice and getL1Fee is called to get the fees.
function _getCurrentTxL1GasFees(bytes memory txCallData) internal view returns (uint256 l1FeeWei) {
/// @notice Returns the upper limit estimate of the L1 fees in wei that will be paid for L2 chains
/// @notice based on the size of the transaction data and the current gas conditions.
/// @notice This is an "upper limit" as it assumes the transaction data is uncompressed when posted on L1.
function _getL1FeeUpperLimit(uint256 calldataSizeBytes) internal view returns (uint256 l1FeeWei) {
uint256 chainid = block.chainid;
if (_isArbitrumChainId(chainid)) {
return ARBGAS.getCurrentTxL1GasFees();
// https://docs.arbitrum.io/build-decentralized-apps/how-to-estimate-gas#where-do-we-get-all-this-information-from
(, uint256 l1PricePerByte, , , , ) = ARBGAS.getPricesInWei();
return l1PricePerByte * (calldataSizeBytes + ARB_DATA_PADDING_SIZE);
} else if (_isOptimismChainId(chainid)) {
return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(txCallData, L1_FEE_DATA_PADDING));
return GAS_PRICE_ORACLE.getL1FeeUpperBound(calldataSizeBytes);
}
return 0;
}
Expand Down
Loading

0 comments on commit fb177f4

Please sign in to comment.