Skip to content

Commit

Permalink
resolving merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-de-leon-cll committed Feb 16, 2024
2 parents cf8c9f8 + da02459 commit dd24c6c
Show file tree
Hide file tree
Showing 57 changed files with 2,220 additions and 522 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/solidity-foundry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
strategy:
fail-fast: false
matrix:
product: [vrf, automation, llo-feeds, l2ep, functions, shared]
product: [vrf, automation, llo-feeds, l2ep, functions, keystone, shared]
needs: [changes]
name: Foundry Tests ${{ matrix.product }}
# See https://github.com/foundry-rs/foundry/issues/3827
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/solidity-hardhat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
with:
filters: |
src:
- 'contracts/src/!(v0.8/(llo-feeds|ccip)/**)/**/*'
- 'contracts/src/!(v0.8/(llo-feeds|keystone|ccip)/**)/**/*'
- 'contracts/test/**/*'
- 'contracts/package.json'
- 'contracts/pnpm-lock.yaml'
Expand Down
3 changes: 3 additions & 0 deletions common/txmgr/types/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ type TxMeta[ADDR types.Hashable, TX_HASH types.Hashable] struct {
ForceFulfilled *bool `json:"ForceFulfilled,omitempty"`
ForceFulfillmentAttempt *uint64 `json:"ForceFulfillmentAttempt,omitempty"`

// Used for Keystone Workflows
WorkflowExecutionID *string `json:"WorkflowExecutionID,omitempty"`

// Used only for forwarded txs, tracks the original destination address.
// When this is set, it indicates tx is forwarded through To address.
FwdrDestAddress *ADDR `json:"ForwarderDestAddress,omitempty"`
Expand Down
2 changes: 1 addition & 1 deletion contracts/GNUmakefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ALL_FOUNDRY_PRODUCTS contains a list of all products that have a foundry
# profile defined and use the Foundry snapshots.
ALL_FOUNDRY_PRODUCTS = l2ep llo-feeds functions shared
ALL_FOUNDRY_PRODUCTS = l2ep llo-feeds functions keystone shared

# To make a snapshot for a specific product, either set the `FOUNDRY_PROFILE` env var
# or call the target with `FOUNDRY_PROFILE=product`
Expand Down
6 changes: 6 additions & 0 deletions contracts/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ test = 'src/v0.8/llo-feeds/test'
solc_version = '0.8.19'
# We cannot turn on deny_warnings = true as that will hide any CI failure

[profile.keystone]
solc_version = '0.8.19'
src = 'src/v0.8/keystone'
test = 'src/v0.8/keystone/test'
optimizer_runs = 10_000

[profile.shared]
optimizer_runs = 1000000
src = 'src/v0.8/shared'
Expand Down
2 changes: 2 additions & 0 deletions contracts/gas-snapshots/keystone.gas-snapshot
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
KeystoneForwarderTest:test_abi_partial_decoding_works() (gas: 2068)
KeystoneForwarderTest:test_it_works() (gas: 993848)
2 changes: 1 addition & 1 deletion contracts/scripts/native_solc_compile_all
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ python3 -m pip install --require-hashes -r $SCRIPTPATH/requirements.txt
# 6 and 7 are legacy contracts, for each other product we have a native_solc_compile_all_$product script
# These scripts can be run individually, or all together with this script.
# To add new CL products, simply write a native_solc_compile_all_$product script and add it to the list below.
for product in 6 7 automation events_mock feeds functions llo-feeds logpoller operatorforwarder shared transmission vrf
for product in 6 7 automation events_mock feeds functions keystone llo-feeds logpoller operatorforwarder shared transmission vrf
do
$SCRIPTPATH/native_solc_compile_all_$product
done
31 changes: 31 additions & 0 deletions contracts/scripts/native_solc_compile_all_keystone
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env bash

set -e

echo " ┌──────────────────────────────────────────────┐"
echo " │ Compiling Keystone contracts... │"
echo " └──────────────────────────────────────────────┘"

SOLC_VERSION="0.8.19"
OPTIMIZE_RUNS=1000000


SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt
solc-select install $SOLC_VERSION
solc-select use $SOLC_VERSION
export SOLC_VERSION=$SOLC_VERSION

ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../../ && pwd -P )"

compileContract () {
local contract
contract=$(basename "$1" ".sol")

solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \
-o "$ROOT"/contracts/solc/v$SOLC_VERSION/"$contract" \
--abi --bin --allow-paths "$ROOT"/contracts/src/v0.8\
"$ROOT"/contracts/src/v0.8/"$1"
}

compileContract keystone/KeystoneForwarder.sol
11 changes: 11 additions & 0 deletions contracts/src/v0.8/automation/dev/chains/ArbitrumModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ contract ArbitrumModule is ChainModuleBase {

function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) {
(, uint256 perL1CalldataUnit, , , , ) = ARB_GAS.getPricesInWei();
// TODO: Verify this is an accurate estimate
return perL1CalldataUnit * dataSize * 16;
}

function getGasOverhead()
external
view
override
returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead)
{
// TODO: Calculate
return (0, 0);
}
}
9 changes: 9 additions & 0 deletions contracts/src/v0.8/automation/dev/chains/ChainModuleBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,13 @@ contract ChainModuleBase is IChainModule {
function getMaxL1Fee(uint256) external view virtual returns (uint256) {
return 0;
}

function getGasOverhead()
external
view
virtual
returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead)
{
return (0, 0);
}
}
12 changes: 12 additions & 0 deletions contracts/src/v0.8/automation/dev/chains/OptimismModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,25 @@ contract OptimismModule is ChainModuleBase {
OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR);

function getCurrentL1Fee() external view override returns (uint256) {
// TODO: Verify this is accurate calculation with appropriate padding
return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(msg.data, OP_L1_DATA_FEE_PADDING));
}

function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) {
// fee is 4 per 0 byte, 16 per non-zero byte. Worst case we can have all non zero-bytes.
// Instead of setting bytes to non-zero, we initialize 'new bytes' of length 4*dataSize to cover for zero bytes.
bytes memory txCallData = new bytes(4 * dataSize);
// TODO: Verify this is an accurate estimate
return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(txCallData, OP_L1_DATA_FEE_PADDING));
}

function getGasOverhead()
external
view
override
returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead)
{
// TODO: Calculate
return (0, 0);
}
}
12 changes: 12 additions & 0 deletions contracts/src/v0.8/automation/dev/chains/ScrollModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,26 @@ contract ScrollModule is ChainModuleBase {
IScrollL1GasPriceOracle private constant SCROLL_ORACLE = IScrollL1GasPriceOracle(SCROLL_ORACLE_ADDR);

function getCurrentL1Fee() external view override returns (uint256) {
// TODO: Verify this is accurate calculation with appropriate padding
return SCROLL_ORACLE.getL1Fee(bytes.concat(msg.data, SCROLL_L1_FEE_DATA_PADDING));
}

function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) {
// fee is 4 per 0 byte, 16 per non-zero byte. Worst case we can have all non zero-bytes.
// Instead of setting bytes to non-zero, we initialize 'new bytes' of length 4*dataSize to cover for zero bytes.
// this is the same as OP.
// TODO: Verify this is an accurate estimate
bytes memory txCallData = new bytes(4 * dataSize);
return SCROLL_ORACLE.getL1Fee(bytes.concat(txCallData, SCROLL_L1_FEE_DATA_PADDING));
}

function getGasOverhead()
external
view
override
returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead)
{
// TODO: Calculate
return (0, 0);
}
}

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions contracts/src/v0.8/automation/dev/interfaces/v2_2/IChainModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,20 @@ interface IChainModule {

// retrieve the L1 data fee for a L2 transaction. it should return 0 for L1 chains and
// L2 chains which don't have L1 fee component. it uses msg.data to estimate L1 data so
// it must be used with a transaction.
// it must be used with a transaction. Return value in wei.
function getCurrentL1Fee() external view returns (uint256);

// retrieve the L1 data fee for a L2 simulation. it should return 0 for L1 chains and
// L2 chains which don't have L1 fee component.
// L2 chains which don't have L1 fee component. Return value in wei.
function getMaxL1Fee(uint256 dataSize) external view returns (uint256);

// Returns an upper bound on execution gas cost for one invocation of blockNumber(),
// one invocation of blockHash() and one invocation of getCurrentL1Fee().
// Returns two values, first value indicates a fixed cost and the second value is
// the cost per msg.data byte (As some chain module's getCurrentL1Fee execution cost
// scales with calldata size)
function getGasOverhead()
external
view
returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead);
}
76 changes: 40 additions & 36 deletions contracts/src/v0.8/automation/dev/v2_2/AutomationRegistry2_2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ contract AutomationRegistry2_2 is AutomationRegistryBase2_2, OCR2Abstract, Chain
Chainable(address(logicA))
{}

/**
* @notice holds the variables used in the transmit function, necessary to avoid stack too deep errors
*/
struct TransmitVars {
uint16 numUpkeepsPassedChecks;
uint256 totalCalldataWeight;
uint96 totalReimbursement;
uint96 totalPremium;
}

// ================================================================
// | ACTIONS |
// ================================================================
Expand Down Expand Up @@ -96,21 +106,20 @@ contract AutomationRegistry2_2 is AutomationRegistryBase2_2, OCR2Abstract, Chain

function _handleReport(HotVars memory hotVars, Report memory report, uint256 gasOverhead) private {
UpkeepTransmitInfo[] memory upkeepTransmitInfo = new UpkeepTransmitInfo[](report.upkeepIds.length);
uint16 numUpkeepsPassedChecks;
TransmitVars memory transmitVars = TransmitVars({
numUpkeepsPassedChecks: 0,
totalCalldataWeight: 0,
totalReimbursement: 0,
totalPremium: 0
});

uint256 blocknumber = hotVars.chainModule.blockNumber();
uint256 l1Fee = hotVars.chainModule.getCurrentL1Fee();

for (uint256 i = 0; i < report.upkeepIds.length; i++) {
upkeepTransmitInfo[i].upkeep = s_upkeep[report.upkeepIds[i]];
upkeepTransmitInfo[i].triggerType = _getTriggerType(report.upkeepIds[i]);
upkeepTransmitInfo[i].maxLinkPayment = _getMaxLinkPayment(
hotVars,
upkeepTransmitInfo[i].triggerType,
uint32(report.gasLimits[i]),
uint32(report.performDatas[i].length),
report.fastGasWei,
report.linkNative,
true
);

(upkeepTransmitInfo[i].earlyChecksPassed, upkeepTransmitInfo[i].dedupID) = _prePerformChecks(
report.upkeepIds[i],
blocknumber,
Expand All @@ -120,7 +129,7 @@ contract AutomationRegistry2_2 is AutomationRegistryBase2_2, OCR2Abstract, Chain
);

if (upkeepTransmitInfo[i].earlyChecksPassed) {
numUpkeepsPassedChecks += 1;
transmitVars.numUpkeepsPassedChecks += 1;
} else {
continue;
}
Expand All @@ -132,66 +141,61 @@ contract AutomationRegistry2_2 is AutomationRegistryBase2_2, OCR2Abstract, Chain
report.performDatas[i]
);

// To split L1 fee across the upkeeps, assign a weight to this upkeep based on the length
// of the perform data and calldata overhead
upkeepTransmitInfo[i].calldataWeight =
report.performDatas[i].length +
TRANSMIT_CALLDATA_FIXED_BYTES_OVERHEAD +
(TRANSMIT_CALLDATA_PER_SIGNER_BYTES_OVERHEAD * (hotVars.f + 1));
transmitVars.totalCalldataWeight += upkeepTransmitInfo[i].calldataWeight;

// Deduct that gasUsed by upkeep from our running counter
gasOverhead -= upkeepTransmitInfo[i].gasUsed;

// Store last perform block number / deduping key for upkeep
_updateTriggerMarker(report.upkeepIds[i], blocknumber, upkeepTransmitInfo[i]);
}
// No upkeeps to be performed in this report
if (numUpkeepsPassedChecks == 0) {
if (transmitVars.numUpkeepsPassedChecks == 0) {
return;
}

// This is the overall gas overhead that will be split across performed upkeeps
// Take upper bound of 16 gas per callData bytes, which is approximated to be reportLength
// Rest of msg.data is accounted for in accounting overheads
// NOTE in process of changing accounting, so pre-emptively changed reportLength to msg.data.length
gasOverhead =
(gasOverhead - gasleft() + 16 * msg.data.length) +
ACCOUNTING_FIXED_GAS_OVERHEAD +
(ACCOUNTING_PER_SIGNER_GAS_OVERHEAD * (hotVars.f + 1));
gasOverhead = gasOverhead / numUpkeepsPassedChecks + ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD;
// Take upper bound of 16 gas per callData bytes
gasOverhead = (gasOverhead - gasleft()) + (16 * msg.data.length) + ACCOUNTING_FIXED_GAS_OVERHEAD;
gasOverhead = gasOverhead / transmitVars.numUpkeepsPassedChecks + ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD;

uint96 totalReimbursement;
uint96 totalPremium;
{
uint96 reimbursement;
uint96 premium;
for (uint256 i = 0; i < report.upkeepIds.length; i++) {
if (upkeepTransmitInfo[i].earlyChecksPassed) {
upkeepTransmitInfo[i].gasOverhead = _getCappedGasOverhead(
gasOverhead,
upkeepTransmitInfo[i].triggerType,
uint32(report.performDatas[i].length),
hotVars.f
);

(reimbursement, premium) = _postPerformPayment(
hotVars,
report.upkeepIds[i],
upkeepTransmitInfo[i],
upkeepTransmitInfo[i].gasUsed,
report.fastGasWei,
report.linkNative,
numUpkeepsPassedChecks
gasOverhead,
(l1Fee * upkeepTransmitInfo[i].calldataWeight) / transmitVars.totalCalldataWeight
);
totalPremium += premium;
totalReimbursement += reimbursement;
transmitVars.totalPremium += premium;
transmitVars.totalReimbursement += reimbursement;

emit UpkeepPerformed(
report.upkeepIds[i],
upkeepTransmitInfo[i].performSuccess,
reimbursement + premium,
upkeepTransmitInfo[i].gasUsed,
upkeepTransmitInfo[i].gasOverhead,
gasOverhead,
report.triggers[i]
);
}
}
}
// record payments
s_transmitters[msg.sender].balance += totalReimbursement;
s_hotVars.totalPremium += totalPremium;
s_transmitters[msg.sender].balance += transmitVars.totalReimbursement;
s_hotVars.totalPremium += transmitVars.totalPremium;
}

/**
Expand Down
Loading

0 comments on commit dd24c6c

Please sign in to comment.